require 'messaging/routing/message_matcher' require 'messaging/routing/subscriber' require 'messaging/routing/background_job_subscriber' require 'messaging/routing/enqueue_message_handler' module Messaging module Routing # Public: Sets up subscribers for the events that matches the given pattern # # pattern - Which messages to subscribe to. Can be a string, a regexp, # a Message class, a module or anything that responds to call. # # call: - Any object that responds to call. # Will be called immediately for matching messages. # # enqueue: - A constant that responds to call. # Will be enqueued with Sidekiq for matching messages. # Needs to be a constant that Sidekiq can serialize to a string # and back again to a constant as you can't store procs in Redis. # # block - An optional block that will be called with each matching message. # # # Examples # # Messaging.routes.draw do # on 'Events::BidPlaced', call: NotifyOtherBidders # # on Events::BidPlaced, enqueue: NotifyOtherBidders # # on Events, do |event| # puts event.inspect # end # # on /.*Updated$/, enqueue: AuditChanges # # on ->(m) { m.topic == 'my-topic' }, call: DoSometing, enqueue: DoSomethingElseWithSidekiq # end # def on(pattern = /.*/, topic: nil, call: nil, enqueue: nil, &block) subscribers << Subscriber.new(pattern, topic, call) if call subscribers << Subscriber.new(pattern, topic, block) if block_given? subscribers << BackgroundJobSubscriber.new(pattern, topic, enqueue) if enqueue end # Internal: Handles the message with the matching subscribers def handle(message) subscribers.map { |subscriber| subscriber.call(message) } message end # Internal: Used by Rails reloading in development. def clear_subscribers! @subscribers = Set.new end private def subscribers @subscribers ||= Set.new end def topics subscribers.flat_map(&:topics).map(&:to_s).uniq end end end