@oop_ru

Страница 441 из 785
Sergey
27.12.2017
08:10:35
так что если у тебя логика чувствительна к порядку возникновения доменных ивентов - то сингелтон может быть разумным вариантом.

если не чувствительна - у тебя больше вариантов

но зашквара я как не видел так и не вижу

Bohdan
27.12.2017
08:11:00
(ивент рекооордер)

Google
Maksim
27.12.2017
08:11:10
если асинхронная, толку от синглтона чуть меньше 0)

Sergey
27.12.2017
08:11:15
(ивент рекооордер)
я это ивент стором называю

Bohdan
27.12.2017
08:11:30
тут да, пофиг как называть

Sergey
27.12.2017
08:11:54
если асинхронная, толку от синглтона чуть меньше 0)
ммм... в пределах одного актора профит всеравно есть, а асинхронщина начнется уже по окончанию логической транзакции

у тебя могут несколько логических транзакций паралельно идти но тут уже сагами надо обмазываться, это совсем другая история

Maksim
27.12.2017
08:13:02
да нету никакого профита, если честно) у тебя в сущности всё равно события по очереди идут) как зарайзил, так и отправишь)

либо засейвишь

Sergey
27.12.2017
08:13:11
то есть все упирается в то как у тебя сущности организованы, дробишь ты на конексты или нет, и что тебе нужно от доменных ивентов. Если email-ы отправлять - то вообще плевать как делать

да нету никакого профита, если честно) у тебя в сущности всё равно события по очереди идут) как зарайзил, так и отправишь)
вопрос в том есть у тебя один единый стор на транзакцию или много маленьких (у каждой сущности свои). Да, по хорошему у тебя есть корень агрегата который ивенты хранит только у себя в пределах одной бизнес транзакции...

и по сути только он их должен генерить, но... жизнь не всегда так сладка)

Sergey
27.12.2017
08:16:17
event_stream (aggregate id) -> one-to-many -> events
да да, а что делать если у тебя в пределах одной бизнес транзакции несколько логических в разных контекстах, причем все не настолько плохо что надо сагами обмазываться. и вот у тебя уже будет больше одного агрегата задействовано

Maksim
27.12.2017
08:17:23
у меня каждое событие в разном контексте. и если что-то пошло не так, то на совести программиста что с этим делать. Так как уж обмазались сагами, пускай сагами и исправляют

Google
Maksim
27.12.2017
08:17:57
исправим)

всех по колено в саги посадим)

Roman
27.12.2017
08:18:09
обработчики доменных событий - это что? не является ли это тоже инфраструктурой?
Ну вот давай пример с юзером. Сверху вниз. Прилетает POST-запрос на /api/v1/users Запрос суть DTO. Далее эта DTO через автомаппер преобразуется в команду "Создать юзера". Эта команда улетает в диспетчер команд. Диспетчер, внутри себя, через какую-нить фабрику (которая скроет работу с IoC контейнером) - срезолвит обработчик (1 команда - 1 обработчик) и вызовет какой-нить метод Handle, в который передаст команду. Обработчику в конструктор приходят: - контекст бд - сервис юзеров Через контекст БД открывается транзакция, через сервис создаётся юзер. По факту создания юзера, из сервиса юзеров возвращается ивент "Создан юзер". В контексте БД сохраняются изменения (но транзакция не коммитится). Если изменения сохранились - то вызывается диспетчер доменных ивентов, куда передаётся ивент "Юзер создан". Далее, диспетчер находит обработчики (1 ивент - много обработчиков) доменного ивента "Юзер создан" и вызывает их. В обработчиках происходит создание инфраструктурных событий, например, формирование имейлов для нотификации. Т.е. ивент "Юзер создан" превращается в команду "Отправить имейл с текстом таким-то туда-то". Сами обработчики эти инфраструктурные команды отправляют в шину. Если все обработчики успешно отработали - происходит коммит транзакции и возврат созданного юзера из команды, который вернётся в ответе на POST-запрос. Параллельно с этим пачка инфраструктурных сервисов разгребает очередь ивентов в рэбите и делает нотификации.

Maksim
27.12.2017
08:19:36
ну это ты обмазывался, а сферический разработчик еще не обмазывался)
т.е. в моей картине мира приложение следит только за консистентностью в рамках 1 агрегата. Согласованность на уровне всех сразу получить в асунковой схеме проблематично. Я как-то красивых вариантов даже не вижу.

Sergey
27.12.2017
08:22:15
Ну вот давай пример с юзером. Сверху вниз. Прилетает POST-запрос на /api/v1/users Запрос суть DTO. Далее эта DTO через автомаппер преобразуется в команду "Создать юзера". Эта команда улетает в диспетчер команд. Диспетчер, внутри себя, через какую-нить фабрику (которая скроет работу с IoC контейнером) - срезолвит обработчик (1 команда - 1 обработчик) и вызовет какой-нить метод Handle, в который передаст команду. Обработчику в конструктор приходят: - контекст бд - сервис юзеров Через контекст БД открывается транзакция, через сервис создаётся юзер. По факту создания юзера, из сервиса юзеров возвращается ивент "Создан юзер". В контексте БД сохраняются изменения (но транзакция не коммитится). Если изменения сохранились - то вызывается диспетчер доменных ивентов, куда передаётся ивент "Юзер создан". Далее, диспетчер находит обработчики (1 ивент - много обработчиков) доменного ивента "Юзер создан" и вызывает их. В обработчиках происходит создание инфраструктурных событий, например, формирование имейлов для нотификации. Т.е. ивент "Юзер создан" превращается в команду "Отправить имейл с текстом таким-то туда-то". Сами обработчики эти инфраструктурные команды отправляют в шину. Если все обработчики успешно отработали - происходит коммит транзакции и возврат созданного юзера из команды, который вернётся в ответе на POST-запрос. Параллельно с этим пачка инфраструктурных сервисов разгребает очередь ивентов в рэбите и делает нотификации.
> из сервиса юзеров возвращается ивент "Создан юзер" прям вот сервис вернет тебе событие? не сущность? > В обработчиках происходит создание инфраструктурных событий зачем так сложно? Просто pub/sub и нужные штуки уже пусть обрабатывают. > Сами обработчики эти инфраструктурные команды отправляют в шину. зачем если они просто могут метод вызвать? или ты думаешь что наличие шины волшебным образом связанность уменьшит? Оно только сделает это неявным. > Если все обработчики успешно отработали - происходит коммит транзакции то есть транзакция не считается успешной если письмо небыло отправлено? а если было отправлено но зависло в баунсед на smtp сервере?

если у тебя выкинулось доменное событие на обработку - это уже факт, то есть все, финито ля транзакция. Все остальное - это уже второстепенные действия которые не влияют на предыдущую.

если тебе надо что бы влияло - добро пожаловать в клуб Maksim любителей саг

Bohdan
27.12.2017
08:24:19
если ты хочешь добиться обязательной отправки всех сообщений (в этом примере) - это нужно делать иначе

Roman
27.12.2017
08:24:34
> из сервиса юзеров возвращается ивент "Создан юзер" прям вот сервис вернет тебе событие? не сущность? > В обработчиках происходит создание инфраструктурных событий зачем так сложно? Просто pub/sub и нужные штуки уже пусть обрабатывают. > Сами обработчики эти инфраструктурные команды отправляют в шину. зачем если они просто могут метод вызвать? или ты думаешь что наличие шины волшебным образом связанность уменьшит? Оно только сделает это неявным. > Если все обработчики успешно отработали - происходит коммит транзакции то есть транзакция не считается успешной если письмо небыло отправлено? а если было отправлено но зависло в баунсед на smtp сервере?
> прям вот сервис вернет тебе событие? не сущность? А почему нет. А внутри события будет содержать созданного юзера. > зачем так сложно? Просто pub/sub и нужные штуки уже пусть обрабатывают. микросервисы > зачем если они просто могут метод вызвать? у другого сервиса? это дорого.

> то есть транзакция не считается успешной если письмо небыло отправлено? а если было отправлено но зависло в баунсед на smtp сервере? нет. меня волнует факт порождения инфраструктурных событий и отправку их в рэбит. А вот если там smtp будет тупить или телега упадёт - меня уже волновать не будет. Это проблемы инфраструктуры.

Sergey
27.12.2017
08:26:00
> нет. меня волнует факт порождения инфраструктурных событий и отправку их в рэбит. почему бы в рэббит не кинуть доменный ивент? Что за инфраструктурые события? зачем они?

Roman
27.12.2017
08:26:30
а нафига он нужен?)
Ну, например, при создании юзера нужно пароль похэшировать.

Sergey
27.12.2017
08:26:48
короч.... тут проблема не с доменными событиями

Google
Roman
27.12.2017
08:27:04
> микросервисы о госпади....
Ога. 3 чела на яве, 2 на го, 1 на ноде и дотнетчиков 2 + я)

Sergey
27.12.2017
08:27:32
Ога. 3 чела на яве, 2 на го, 1 на ноде и дотнетчиков 2 + я)
не к об этом, я про то что "инфраструктурные события" звучит как ужасная идея

Maksim
27.12.2017
08:27:32
и чё?)

Roman
27.12.2017
08:27:49
Инфраструктурные сервисы.

Я вот такое только придумал.

Sergey
27.12.2017
08:28:31
но связанность то не исчезла - кто-то теперь должен знать о инфраструктуре и к какому сервису это будет относиться?

Maksim
27.12.2017
08:28:35
нету никаких инфраструктурных сервисов, событий и команд

Sergey
27.12.2017
08:28:54
или у тебя 10 сервисов будут знать о сервисе нотификаций?)

короч - микросервисы это про связанность а то что ты описываешь это какой-то трэш

короч... https://www.youtube.com/watch?v=Fuac__g928E

пойду работать а вам вот видяшки

Sergey
27.12.2017
08:30:34
Почему трэш то?
вот есть у тебя ну не 10, пускай 5 сервисов. Каждый генерит какие-то доменные ивенты на которые надо отправлять email-ы. для имейлов у тебя есть "инфраструктурные события". кто и где будет преобразовывать доменное событие в инфраструктурное?

Sergey
27.12.2017
08:31:11
все в каше

Roman
27.12.2017
08:31:18
Я же писал в длиннопосте

Появилось событие "Создан юзер". Оно бросается в диспетчер, который хэндлит обрботчики этого события. Эти обработчики создают команды для инфраструктуры и пуляют их в рэбит. Если не пульнулось - не создалось - рэбит лёг - качу транзакцию обратно.

Sergey
27.12.2017
08:33:02
1. получили команду - нашли обработчик 2. обработчик попросил сервис юзеров что-то сделать на что тот вернул результат (то что ты называешь "событием"). Какой-то факт. что он вернет в случае неудачи? Чем это отличается от "вернуть юзера"? 3. обработчик взял этот "доменный ивент" (который оным по факту не является) и сгенерил "инфраструктурные события" - это не события скорее а команды, то есть описание что сделать и данные для этого. так?

Google
Sergey
27.12.2017
08:33:31
типа ProductPurchased -> [SendProductPurchasedNotification]`

по факту "доменный ивент" тут не особо нужен

Roman
27.12.2017
08:33:58
типа ProductPurchased -> [SendProductPurchasedNotification]`
да и вот это SendProductPurchasedNotification пуляется в рэбит

Sergey
27.12.2017
08:34:09
точно так же как нет разницы между "инфраструктрным" событием и просто RPC вызовом

Roman
27.12.2017
08:34:18
по факту "доменный ивент" тут не особо нужен
А этих нотификаций может уева гора быть всяких разных.

Sergey
27.12.2017
08:34:29
все сервисы которые генерият "инфраструктурные события" по факту неявно знают о инфраструктуре

Sergey
27.12.2017
08:34:33
связанность системы повышается

добро пожаловать в ад через пол годика

Roman
27.12.2017
08:35:20
кролик умеет RPC)
Я не хочу дожидаться отправки имейла. Я хочу кинуть в кролик команду и работать дальше.

Sergey
27.12.2017
08:35:22
проблема со связанностью - у тебя с таким подходом она выходит дико огромной и в целом во всем этом нет смысла

Sergey
27.12.2017
08:35:41
Я не хочу дожидаться отправки имейла. Я хочу кинуть в кролик команду и работать дальше.
ну то есть ты признаешь что это "инфраструктурные команды" которые по факту просто RPC

Roman
27.12.2017
08:35:59
Получается инфраструктура должна знать о доменных ивентах?

Sergey
27.12.2017
08:36:01
RPC не означает что ты должен ждать результат

Получается инфраструктура должна знать о доменных ивентах?
какая-то инфраструктура должна, а вот обработчики команд твоих об инфраструктуре знать ничего не должны.

Roman
27.12.2017
08:36:25
Sergey
27.12.2017
08:36:47
RPC - это вызвал и дождался - у меня - запаблишил и забыл
асинхронный вызов метода, отправка сообщения, как хочешь называй. Это никак не влияет на связанность

короч... посмотри видосик) тебе понравится)

Google
Roman
27.12.2017
08:37:44
какая-то инфраструктура должна, а вот обработчики команд твоих об инфраструктуре знать ничего не должны.
Ну если я не делаю инфраструктурных команд - то как минимум они умеют ивенты паблишить в кролик

Sergey
27.12.2017
08:38:18
Ну если я не делаю инфраструктурных команд - то как минимум они умеют ивенты паблишить в кролик
потому что у тебя нет доменных событий по факту - у тебя это результат выполнения операции (ты же сам про CQS не так давно говорил)

Roman
27.12.2017
08:38:24
Тут короче 2 варианта - либо инфраструктура знает про домен, либо домен про инфраструктуру)

Sergey
27.12.2017
08:38:45
инфраструктура знает о тригерах - это норм. Домен знает о инфраструктуре - это не ок

Roman
27.12.2017
08:39:04
Sergey
27.12.2017
08:39:10
вся проблема в том что твои "доменные события" это не доменные события

Roman
27.12.2017
08:39:36
Sergey
27.12.2017
08:39:46
А являются ли обработчики команд частью домена?
это что-то типа application level сервисы, уровень оркестрации. Он тоже не должен о инфраструктуре знать

А Ъ доменные события тогда это как?
1. обработчик попросил сервис создать юзера 2. юзер в контроллере запомнил событие что "я жив" 3. кто-то кто знает что транзакция завершилась возьмет у сущност и события и пробросит их в кролик. Это может и хэндлер делать но это не удобно

Maksim
27.12.2017
08:42:06
вся проблема в том что твои "доменные события" это не доменные события
у меня в реализации доменные события - просто графоманство. Они создаются на основании обычных и только в рамках агрегатов. В общем, просто так модно было назвать :) с концептуальной точки зрения я не понял особой разницы, ибо их поведение на миллион процентов одинаковое.

Sergey
27.12.2017
08:42:43
потому янг (или уди, не помню кто из них) и топили за сингелтон EventStore так как в этом случае у тебя при выходе из обработчика команды можно: - закоммитить транзакцию - пробросить все события в кролик

доменное событие может быть выкинуто в кролик ТОЛЬКО когда транзакция завершена и доменное событие становится фактом

ай не, работать

Maksim
27.12.2017
08:44:35
что такое "обычные события"?))
просто события) ни чем не отличающиеся от "не просто событий") о том и речь)

асунковый эвент соурсинг кафно) я не могу придумать как красиво блокировки и согласованность выстроить :( уже месяц возни, а работающей схемы даже на горизонте нету :(

Roman
27.12.2017
14:26:39
Я тут почитал немного. Сага это грубо говоря - обработчик, начинающийся с определённого доменного события, описывающий бизнес-процесс что ли?

Или неправильно понял?

Aleh
27.12.2017
14:27:56
А это зашкварище.
не, нормально вполне

Roman
27.12.2017
14:28:25
не, нормально вполне
Ну он тогда будет контейнер дёргать же(

Страница 441 из 785