Domain events и websocket
Domain events и websocket
Изучаю вопрос, как уведомлять UI клиента о том, что данные, которые ему интересны изменились. Например UI должен обновить список пользователей онлайн в чате, если кто-то вошел на сайт, покинул сайт или сменил комнату чата на другую. Для каждого из этих действий (вошел/покинул/сменил) у сущности User есть свой метод. Я могу внутри этих методов выбрасывать доменные события.
Но теперь хочется понять, как довести доменные события до UI клиента. Протокол передачи данных - websocket. Я думал о методе сервиса ChatService::getUsers, который возвращает клиенту список пользователей онлайн в чате и подписывает клиента на доменные события (вошел/покинул/сменил). То есть это некий аналог GET запроса в HTTP протоколе, но отличие в том, что он не просто отдает данные и забывает про клиента, он обязуется в будущем уведомлять клиента о всех изменениях связанных с этим запросом (вошел/покинул/сменил).
Но меня настораживает то, что количество доменных событий будет расти и соответственно количество доменных событий, на которые необходимо подписываться и обрабатывать их в ChatService::getUsers тоже будет увеличиваться. То есть когда в системе будет появляться новое доменное событие, то разработчику нужно как-то знать, каким методам, каких сервисов это доменное событие может быть интересно и соответственно внести правки в методы этих сервисов, чтобы каждый из них, каким-то своим образом обрабатывал это новое событие.
Например доменное событие "вошел на сайт" и "покинул сайт" может влиять не только на отображение пользователей в чате, но и также на страницу с информацией о пользователе. Соответственно обработку этих доменных событий нужно будет сделать не только в ChatService::getUsers, который отдает данные для формирования списка пользователей в чате, но и в UserService::getById, который отдает данные для формирования страницы с информацией о конкретном пользователе. И например, если забыть сделать обработку этих доменных событий в UserService::getById, то ничего страшного не произойдет, страница с информацией о пользователе просто никак не будет реагировать на события входа и выхода на сайт.
Не приведет ли это к аду, когда новое доменное событие требуется проанализировать, каким UI экранам оно может быть интересно и соответственно внести обработку этого нового доменного события в различные методы различных сервисов? Может быть есть какие-то другие решения уведмолять UI об изменившихся данных?
Но теперь хочется понять, как довести доменные события до UI клиента. Протокол передачи данных - websocket. Я думал о методе сервиса ChatService::getUsers, который возвращает клиенту список пользователей онлайн в чате и подписывает клиента на доменные события (вошел/покинул/сменил). То есть это некий аналог GET запроса в HTTP протоколе, но отличие в том, что он не просто отдает данные и забывает про клиента, он обязуется в будущем уведомлять клиента о всех изменениях связанных с этим запросом (вошел/покинул/сменил).
Но меня настораживает то, что количество доменных событий будет расти и соответственно количество доменных событий, на которые необходимо подписываться и обрабатывать их в ChatService::getUsers тоже будет увеличиваться. То есть когда в системе будет появляться новое доменное событие, то разработчику нужно как-то знать, каким методам, каких сервисов это доменное событие может быть интересно и соответственно внести правки в методы этих сервисов, чтобы каждый из них, каким-то своим образом обрабатывал это новое событие.
Например доменное событие "вошел на сайт" и "покинул сайт" может влиять не только на отображение пользователей в чате, но и также на страницу с информацией о пользователе. Соответственно обработку этих доменных событий нужно будет сделать не только в ChatService::getUsers, который отдает данные для формирования списка пользователей в чате, но и в UserService::getById, который отдает данные для формирования страницы с информацией о конкретном пользователе. И например, если забыть сделать обработку этих доменных событий в UserService::getById, то ничего страшного не произойдет, страница с информацией о пользователе просто никак не будет реагировать на события входа и выхода на сайт.
Не приведет ли это к аду, когда новое доменное событие требуется проанализировать, каким UI экранам оно может быть интересно и соответственно внести обработку этого нового доменного события в различные методы различных сервисов? Может быть есть какие-то другие решения уведмолять UI об изменившихся данных?
Re: Domain events и websocket
итак, в сущности у вас генерятся доменные события, в репозитории при сохранении сущности вы вытаскиваете нагенеренные за сессию события и кидаете их в шину (или что там у вас события разруливает). В шине стандартная ситуация с событиями: сервер вебсокета подписывается на события и при их возникновении пишет что-то в чат. Это если у вас шина асинхронная. Иначе записываем события в таблицу, вебсокет-сервер оттуда их читает.sda писал(а):Но теперь хочется понять, как довести доменные события до UI клиента. Протокол передачи данных - websocket. Я думал о методе сервиса ChatService::getUsers, который возвращает клиенту список пользователей онлайн в чате и подписывает клиента на доменные события (вошел/покинул/сменил). То есть это некий аналог GET запроса в HTTP протоколе, но отличие в том, что он не просто отдает данные и забывает про клиента, он обязуется в будущем уведомлять клиента о всех изменениях связанных с этим запросом (вошел/покинул/сменил).
модуль User ничего не знает о веб-сокетах. Его задача выкинуть события наружу. А снаружи хочешь подбирай их, хочешь не подбирай.sda писал(а):Но меня настораживает то, что количество доменных событий будет расти и соответственно количество доменных событий, на которые необходимо подписываться и обрабатывать их в ChatService::getUsers тоже будет увеличиваться.
То есть когда в системе будет появляться новое доменное событие, то разработчику нужно как-то знать, каким методам, каких сервисов это доменное событие может быть интересно и соответственно внести правки в методы этих сервисов, чтобы каждый из них, каким-то своим образом обрабатывал это новое событие.
Например доменное событие "вошел на сайт" и "покинул сайт" может влиять не только на отображение пользователей в чате, но и также на страницу с информацией о пользователе. Соответственно обработку этих доменных событий нужно будет сделать не только в ChatService::getUsers, который отдает данные для формирования списка пользователей в чате, но и в UserService::getById, который отдает данные для формирования страницы с информацией о конкретном пользователе. И например, если забыть сделать обработку этих доменных событий в UserService::getById, то ничего страшного не произойдет, страница с информацией о пользователе просто никак не будет реагировать на события входа и выхода на сайт.
Не приведет ли это к аду, когда новое доменное событие требуется проанализировать, каким UI экранам оно может быть интересно и соответственно внести обработку этого нового доменного события в различные методы различных сервисов? Может быть есть какие-то другие решения уведмолять UI об изменившихся данных?
Re: Domain events и websocket
У меня весь бекенд приложения асинхронный он полностью написан на ноде. Я планировал подбирать события в application layer, в сервисах. Там решается вопрос с тем, каким пользователям отправить событие. Затем управление передается инфраструктурному сервису, который уже непосредственно делает броадкаст события в нужные сокеты. Нормально это?
Re: Domain events и websocket
нормальноsda писал(а):У меня весь бекенд приложения асинхронный он полностью написан на ноде. Я планировал подбирать события в application layer, в сервисах. Там решается вопрос с тем, каким пользователям отправить событие. Затем управление передается инфраструктурному сервису, который уже непосредственно делает броадкаст события в нужные сокеты. Нормально это?
Re: Domain events и websocket
Что-то не пойму где регистрировать подписчиков событий. Вон вернон в своей книге делает это в методе аппликейшн сервиса, до вызова метода доменного объекта. Это не подходит для приложения, которое запущенно как демон. Для такого приложения всех подписчиков нужно зарегистировать только один раз. Где это делать?
Re: Domain events и websocket
в любом bootstrap-файле (файле, который запускается в любом инстансе приложения). Но вообще мне очевидно, что это должно происходить в конфиге приложения и собираться во время запуска.sda писал(а):Что-то не пойму где регистрировать подписчиков событий. Вон вернон в своей книге делает это в методе аппликейшн сервиса, до вызова метода доменного объекта. Это не подходит для приложения, которое запущенно как демон. Для такого приложения всех подписчиков нужно зарегистировать только один раз. Где это делать?
Re: Domain events и websocket
Про bootstrap файл понял, а про конфиг приложения не очень. Имеется ввиду хранить в конфиге путь где лежат подписчики, а затем в bootstrap файле загружать и регистировать всех подписчиков, которые располагаются по этому пути?
Re: Domain events и websocket
это все зависит от вашего event manager'а.sda писал(а):Про bootstrap файл понял, а про конфиг приложения не очень. Имеется ввиду хранить в конфиге путь где лежат подписчики, а затем в bootstrap файле загружать и регистировать всех подписчиков, которые располагаются по этому пути?
Re: Domain events и websocket
Еще такая проблема. В UI бывает, что на 1 событие нужно обновить данные в нескольких местах. Например если кто-то меняет логин, нужно его обновить в нескольких местах. Если этот юзер есть в чате то поменять ему логин в чате, если он сидит за покерным столом также поменять ему логин в покерном столе и т.д. Данные о том, кто в чате и кто за покерным столом являются разными экзеплярами данных. Поэтому обновлять нужно в нескольких местах.
Я планировал использовать Redux для изменения состояния приложения. Каждое событие, которое упало с сервера в UI я планировал трансформировать в экшен редакса. Затем те редьюсеры кому интересно событие обрабатывают экшен и изменяют свою часть общего состояния приложения. Таким образом, изменение логина произойдет в нескольких различных частях состояния приложения и изменения будут отображены во вью.
Это нормальное решение?
Я планировал использовать Redux для изменения состояния приложения. Каждое событие, которое упало с сервера в UI я планировал трансформировать в экшен редакса. Затем те редьюсеры кому интересно событие обрабатывают экшен и изменяют свою часть общего состояния приложения. Таким образом, изменение логина произойдет в нескольких различных частях состояния приложения и изменения будут отображены во вью.
Это нормальное решение?
Re: Domain events и websocket
как сделать, чтобы domain events выбрасывались после сохранения агрегата?
Re: Domain events и websocket
Через $this->recordEvent(new Event(...)) в агрегате и $aggregate->releaseEvents() после сохранения.sda писал(а):как сделать, чтобы domain events выбрасывались после сохранения агрегата?
Re: Domain events и websocket
ElisDN примерно такой же подход нашел здесь https://lostechies.com/jimmybogard/2014 ... s-pattern/
Вроде самое адекватное решение из всех, которые видел. Но получается придется научить репозиторий репозиторий как-то отбрасывать свойство агрегата в котором хранятся события, чтобы он его в базу не сохранял.
Вроде самое адекватное решение из всех, которые видел. Но получается придется научить репозиторий репозиторий как-то отбрасывать свойство агрегата в котором хранятся события, чтобы он его в базу не сохранял.
Re: Domain events и websocket
не надо было репозиторий этому учить изначально.sda писал(а):ElisDN примерно такой же подход нашел здесь https://lostechies.com/jimmybogard/2014 ... s-pattern/
Вроде самое адекватное решение из всех, которые видел. Но получается придется научить репозиторий репозиторий как-то отбрасывать свойство агрегата в котором хранятся события, чтобы он его в базу не сохранял.
http://www.yiiframework.ru/forum/viewto ... 46#p203985
http://www.yiiframework.ru/forum/viewto ... 46#p204421
Re: Domain events и websocket
Ну хорошо. А что по поводу доменного события, которое возникает при создании нового доменного объекта ? Если выбрасывать его в конструкторе, то это событие будет возникать не только при создании нового объекта, но и при восстановлении объекта из базы тоже. Я пока думаю, что доменный сервис этого самое наилучшее решение, чтобы решить эту проблему. Что скажете?
Re: Domain events и websocket
Для восстановления из базы используйте рефлексию.sda писал(а):...но и при восстановлении объекта из базы тоже.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Domain events и websocket
И в этом топике дам ссылку на https://github.com/samdark/hydrator ...
Нравится Yii? Давайте сделаем его лучше!.
Re: Domain events и websocket
точки к ссылке прилиплиSam Dark писал(а):И в этом топике дам ссылку на https://github.com/samdark/hydrator...
Re: Domain events и websocket
Ну в php ок, есть решение http://php.net/manual/en/reflectionclas ... ructor.phpElisDN писал(а):Для восстановления из базы используйте рефлексию.sda писал(а):...но и при восстановлении объекта из базы тоже.
А в javascript как лучше? Там у рефлекшена таких фишек нет.
Re: Domain events и websocket
без рефлексии есть практика создавать отдельный метод для восстановления из базы.sda писал(а):Ну в php ок, есть решение http://php.net/manual/en/reflectionclas ... ructor.phpElisDN писал(а):Для восстановления из базы используйте рефлексию.sda писал(а):...но и при восстановлении объекта из базы тоже.
А в javascript как лучше? Там у рефлекшена таких фишек нет.