Vladimir Alexeev
А есть какие-то ограничения по тому, как может быть реализован обработчик события? Может ли он, скажем, включать какие-нибудь IoC зависимости? Например, возвращаясь к примеру с SMS, у меня есть операция над юзером, и при определенном ветвлении в ней я хочу отправить ему SMS. Может ли SomeOpOnUserEventHandler содержать внешнюю зависимость, например, SMSSender?
если говорить про разумные ограничения, но в целом я рекомендую следующие:
- обработчик должен быть абсолютно независим от других обработчиков того же события. У меня было масса проблем из-за неявных зависимостей мол "один ивент - несколько обработчиков - они внезапно зависят от того кто в каком порядке отработал". Лучше сразу договориться мол "в пределах сообщения порядок обработки не гарантирован и не надо на него завязываться - важен порядок - кидайте новые события или дергаейте операции явно.
- очень опасная штука время, когда обработчики зависят от того когда сообщение дошло. Например есть кейсы когда кинули ивент, после чего стэйт поменялся еще раз. То есть на момент получения события стэйт уже слегка поменялся и могут быть проблемы в плане принятия решений. потому в ситуациях когда "это норма" и нужны всякие там Саги которые не зависят от внешнего стэйта и свой выстраивают только по событиям которые к ним приходят.
- Обработчики желательно делать атомарными. Если тебе надо сходить во внешнюю систему и потом в базу результат записать - лучше делать это по отдельности. Ивент - сходили во внешнюю сситему - кинули ивент который содержит результат - запустили другую операцию которая уже в базу пишет. Однако тут вопрос в инфраструктуре. Если у тебя инфраструктура может ивенты терять то в целом "не так важно это".
Большинство ограничений в целом будут проистекать из того как у тебя инфраструктура организована. У меня например мы делали "аля nservicebus" и там компитинг консюмеры (нет гарантий порядка), возможность гарантий того что сообщение будет сохранено и доставлено но ценой того что "иногда можем доставить не один раз", что вынуждает делать операции идемпотентными. Есть кейсы когда обработчики отрабатывают без ретраев в одном процессе - тогда важно что бы один обработчик не сломал всю цепочку. Есть кейсы когда каждый обработчик работает изолировано + ретраи которые "чинят" кейсы с out-of-order доставкой сообщений (случается в случае компитинг консюмеров). Но в некоторых ситуациях можно скажем юзать консистентные хэши для роутинга и за счет этого гарантировать очередность сообщений там где это важно.
Вариантов масса. Все упирается в инфраструктуру для месседжинга и какие гарантии оно тебе предоставляет.