Доброго времени суток.
Начал знакомиться/разбираться с очередями для выполнения асинхронных задач, сразу встал вопрос как это гибче реализовать (будет активно переиспользоваться).
Пока на ум пришло только использование некой шины куда будут передаваться задача и которая уже будет всё разруливать и отправлять задачу в очередь.
Думаю что это не должно быть в доменном слое, но вот не уверен слой ли это приложения или инфраструктуры.
Пример с отправкой email'ов:
https://bitbucket.org/nootropil/studyin ... er.php-165
https://bitbucket.org/nootropil/studyin ... ler.php-66
https://bitbucket.org/nootropil/studyin ... ?at=master
Любая адекватная критика как по архитектуре так и по реализации работы с очередями приветствуется.
Слоение очередей
Re: Слоение очередей
Я реализую это через Domain Event'ы - ну т.е. в инфраструктурном слое есть слушатели событий, которые могут, либо выполнять действия сразу, либо помещать задание в очередь (в зависимости от того что требуется - выполнить в рамках одной транзакции или нет).
Что касается транзакционности - у меня по факту 2 EventPublisher'a, через которых можно подписаться на события:
P.S. не претендую на правильность решения/терминологии - пока такая связка работает
Что касается транзакционности - у меня по факту 2 EventPublisher'a, через которых можно подписаться на события:
- Доменный (моментальная реакция подписчиков на публикуемое событие в рамках одной транзакции)
- Инфраструктурный (агрегирует все доменные события, произошедшие в рамках транзакции, и по ее успешному завершению начинает скармливать их своим подписчикам)
P.S. не претендую на правильность решения/терминологии - пока такая связка работает
Re: Слоение очередей
я делаю через шину событий, один exchange и topic'и. Консьюмеры могут подписываться на топики и получать свои события.
https://bitbucket.org/nootropil/studyin ... er.php-165
зачем разделены выполнение команды и генерация события по его результатам? это должно быть в хэндлере.
В целом в коде все намешано и перепутано местами. Рекомендую такой подход:
Event - обычный объект (PostCreated, UserRegistered итд)
EventBus - шина с методом handle, принимающим объект события. Внутри RabbitMqConnection, посылающий RabbitMqEvent в шину.
RabbitMqConnection работает с одним эксченджем типа topic.
RabbitMqEvent - простой объект, состоящий из payload (непосредственно Event), type (короткое имя класса, типа PostCreated), topic (неймспейс объекта, нормализованный до имени топика - module.domain.blog.event.post_created - позволит удобно подписываться на нужные топики типа module.domain.blog.*)
Событие сериализуется Serializer'ом. В моем случае это ObjectDeepSerializer, который с помощью hydrator рекурсивно нормализует объект до массивов ['class' => '...', 'payload' => '...'], а потом восстанавливает обратно. Так сделано для отсутствия связанности между различными частями приложения. Если связанность не пугает, то можно реализовывать интерфейс JsonSerializable.
Консьюмеры подписываются на топики.
https://github.com/zelenin/message-bus - шина с поддержкой middleware с контекстом, передаваемого через весь стек мидлварей, с помощью которого можно пробрасывать результаты выполнения хэндлеров или мидлварей (например вернуть ошибки валидации или свежесозданные объект). Из коробки HandlerMiddleware, который позволит обрабатывать события в рамках запроса. Ручками можно дописать RabbitMqMiddleware, который будет хэндлить все события и кидать в rabbit.
https://github.com/zelenin/hydrator - гидратор для извлечения данных из объекта и создания объекта на основе извлеченных данных.
Serializer пока не релизил.
https://bitbucket.org/nootropil/studyin ... er.php-165
зачем разделены выполнение команды и генерация события по его результатам? это должно быть в хэндлере.
В целом в коде все намешано и перепутано местами. Рекомендую такой подход:
Event - обычный объект (PostCreated, UserRegistered итд)
EventBus - шина с методом handle, принимающим объект события. Внутри RabbitMqConnection, посылающий RabbitMqEvent в шину.
RabbitMqConnection работает с одним эксченджем типа topic.
RabbitMqEvent - простой объект, состоящий из payload (непосредственно Event), type (короткое имя класса, типа PostCreated), topic (неймспейс объекта, нормализованный до имени топика - module.domain.blog.event.post_created - позволит удобно подписываться на нужные топики типа module.domain.blog.*)
Событие сериализуется Serializer'ом. В моем случае это ObjectDeepSerializer, который с помощью hydrator рекурсивно нормализует объект до массивов ['class' => '...', 'payload' => '...'], а потом восстанавливает обратно. Так сделано для отсутствия связанности между различными частями приложения. Если связанность не пугает, то можно реализовывать интерфейс JsonSerializable.
Консьюмеры подписываются на топики.
https://github.com/zelenin/message-bus - шина с поддержкой middleware с контекстом, передаваемого через весь стек мидлварей, с помощью которого можно пробрасывать результаты выполнения хэндлеров или мидлварей (например вернуть ошибки валидации или свежесозданные объект). Из коробки HandlerMiddleware, который позволит обрабатывать события в рамках запроса. Ручками можно дописать RabbitMqMiddleware, который будет хэндлить все события и кидать в rabbit.
https://github.com/zelenin/hydrator - гидратор для извлечения данных из объекта и создания объекта на основе извлеченных данных.
Serializer пока не релизил.
Re: Слоение очередей
glagola, а как соблюдается консистентность и дедупликация событий?
Re: Слоение очередей
Спасибо за ответы.
https://bitbucket.org/nootropil/studyin ... er.php-111
https://bitbucket.org/nootropil/studyin ... ler.php-63
https://bitbucket.org/nootropil/studyin ... ew-default
https://bitbucket.org/nootropil/studyin ... ler.php-73
Могли бы вы прокомментировать на сколько правильно я вас понял?
Интересный вариант. Попробовал реализовать близко к тому, что вы предложили.
https://bitbucket.org/nootropil/studyin ... er.php-111
https://bitbucket.org/nootropil/studyin ... ler.php-63
https://bitbucket.org/nootropil/studyin ... ew-default
https://bitbucket.org/nootropil/studyin ... ler.php-73
Могли бы вы прокомментировать на сколько правильно я вас понял?
Re: Слоение очередей
да, похоже. только тут:
https://bitbucket.org/nootropil/studyin ... ew-default
я бы две разных мидлвари использовал - одну, ту, что из коробки - для хэндлеров, вторую самописную для rabbit, которая бы только в рэббит отсылала.
https://bitbucket.org/nootropil/studyin ... ew-default
я бы две разных мидлвари использовал - одну, ту, что из коробки - для хэндлеров, вторую самописную для rabbit, которая бы только в рэббит отсылала.