Module: OpenLoam::Events

Defined in:
lib/open_loam/events.rb

Overview

A thin domain event bus over ActiveSupport::Notifications.

Convention: event names are domain.thing.happened, e.g. "billing.subscription.renewed", "rental.equipment.created". Publishing stamps the current tenant and actor onto the payload so subscribers are always tenant-aware.

Constant Summary collapse

NAME_FORMAT =
/\A[a-z0-9_]+(\.[a-z0-9_]+){2,}\z/
PREFIX =
"open_loam.event."

Class Method Summary collapse

Class Method Details

.pattern_matches?(pattern, event_name) ⇒ Boolean

The subscription rule, in one place: a trailing dot is a domain prefix, anything else is an exact event name. OpenLoam::WebhookEndpoint matches against this too, so a pattern means the same thing everywhere.

Returns:

  • (Boolean)


27
28
29
30
31
32
# File 'lib/open_loam/events.rb', line 27

def self.pattern_matches?(pattern, event_name)
  pattern = pattern.to_s
  event_name = event_name.to_s

  pattern.end_with?(".") ? event_name.start_with?(pattern) : event_name == pattern
end

.publish(name, payload = {}) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/open_loam/events.rb', line 12

def self.publish(name, payload = {})
  name = name.to_s
  unless name.match?(NAME_FORMAT)
    raise InvalidEventNameError, "Event name #{name.inspect} must follow `domain.thing.happened`"
  end

  ActiveSupport::Notifications.instrument(
    PREFIX + name,
    payload.merge(tenant_id: OpenLoam::Current.tenant&.id, actor_id: OpenLoam::Current.actor&.id)
  )
end

.subscribe(name_or_prefix, &block) ⇒ Object

Subscribe to one event ("rental.equipment.created") or a whole domain ("rental.") — the block receives (event_name, payload).



43
44
45
46
47
48
49
# File 'lib/open_loam/events.rb', line 43

def self.subscribe(name_or_prefix, &block)
  pattern = PREFIX + name_or_prefix.to_s
  matcher = pattern.end_with?(".") ? /\A#{Regexp.escape(pattern)}/ : pattern
  ActiveSupport::Notifications.subscribe(matcher) do |full_name, _start, _finish, _id, payload|
    block.call(full_name.delete_prefix(PREFIX), payload)
  end
end

.subscribe_all(&block) ⇒ Object

Every OpenLoam event, whatever its domain — the empty prefix matches them all. Used by the webhook dispatcher, which decides per event which endpoints care.



37
38
39
# File 'lib/open_loam/events.rb', line 37

def self.subscribe_all(&block)
  subscribe("", &block)
end