ситуация, есть приложение, которое создает пользователя, а потом хочет сделать кучу разной работы в бэкграунде (послать данные пользователю, отправить аналитику в сегмент, сделать какие-то модели в БД, выкачать дамп данных, etc)
вариант первый, взять сайдкик:
class CreatedUserNotificationWorker
# ...
end
class CreatedUserAnalyticsWorker
# ...
end
...
а потом вызывать что-то в таком духе:
user = repository.create(attributes)
CreatedUserNotificationWorker.perform_async(user.id)
CreatedUserAnalyticsWorker.perform_async(user.id)
# ...
можно создать супервайзер, который сам будет спавнить воркеры
class CreatedUserSuperviserWorker
def perform(payload)
WORKERS.each { |worker| worker.perform_async(payload) }
end
end
плюсы:
- сайдкик вылезан майком полностью, поэтому быстро ставится и быстро делается все
- все знают как это работает и объяснять не нужно, порог входа низкий
минусы:
- у тебя создается N сообщений в бд на событие, за этим сложно следить в реальной системе (много абстракций, за каждой по своему следить надо, потому что имя другое)
- редис, это как плюс (быстро и легко в поддержке), так и минус, потому что персистентность нулевая. если у тебя события важные (например биллинг какой-то), я бы не советовал юзать его + только в про версии сайдкиа есть вариант с нормальным завершением воркеров
- если ты хочешь взять не руби или дергать воркеры из проекта в проект (*аля сервисы) - придется соснуть, взять фактори или писать обвязку для того, что бы вызывать воркер из другого проекта
Есть другой вариант, можно взять что угодно (кафку, реббит, да хоть постгрес) и сделать subscribers на событие. пример вот тут https://github.com/davydovanton/hanami_event_example, посмотреть лучше https://github.com/davydovanton/hanami_event_example/blob/master/event_server.rb вот этот файл.
В общих чертах выглядит так, что ты делаешь в разных частях приложения, которые подписываются на событие какое-то (user_created
) в нашем случае
class NotificationHandler
on 'user_created' do |payload|
# code for sending sms and email to user
end
end
class AnalyticsHandler
on 'user_created' do |payload|
# code for sending some events to analytics services
end
end
class PrerareHandler
on 'user_created' do |payload|
# code for creatring some related things for user
end
end
...
А потом просто создаешь событие, и каждый из хендлеров будет выполнять код под событие
плюсы:
- не прибито к языку или проекту. можешь писать хендлеры хоть на хаскеле и вызывать из 1-N сервисов
- персистентность выше, это автоматическое логгирование событий в системе
- нет кучи разных событй, есть просто куча хендлеров
минусы:
- дебажить сложно (асинхронно же) в реальных системах
- выше порог входа
- придется писать свою обвязку
- некоторые персистенс штуки дороги в поддержке (например та же кафка)