Class: Koine::EventManager::TransactionalEventManager

Inherits:
Koine::EventManager show all
Defined in:
lib/koine/event_manager/rails.rb

Overview

Dispatches listeners after the current DB transaction commits (or runs immediately when none is open), so they never react to changes a rollback would undo. Requires ActiveRecord >= 7.2.

Individual subscribers/listeners may opt into synchronous, in-transaction dispatch with ‘after_commit: false`. Those run inline and their errors propagate (bypassing `on_error` isolation), so an integrity reaction can abort the surrounding transaction. Post-commit listeners stay isolated.

Constant Summary

Constants included from Koine::EventManager

VERSION

Instance Method Summary collapse

Constructor Details

#initialize(on_error: nil) ⇒ TransactionalEventManager

Returns a new instance of TransactionalEventManager.



18
19
20
21
22
23
# File 'lib/koine/event_manager/rails.rb', line 18

def initialize(on_error: nil)
  super
  # In-transaction listeners: no on_error isolation, so a failure propagates
  # and can roll the surrounding transaction back.
  @synchronous = EventListener.new
end

Instance Method Details

#listen_to(event, after_commit: true, &block) ⇒ Object



31
32
33
34
35
# File 'lib/koine/event_manager/rails.rb', line 31

def listen_to(event, after_commit: true, &block)
  return @synchronous.listen_to(event, &block) unless after_commit

  super(event, &block)
end

#subscribe(subscriber, to:, after_commit: true) ⇒ Object



25
26
27
28
29
# File 'lib/koine/event_manager/rails.rb', line 25

def subscribe(subscriber, to:, after_commit: true)
  return @synchronous.subscribe(subscriber, to: to) unless after_commit

  super(subscriber, to: to)
end

#trigger(event) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/koine/event_manager/rails.rb', line 42

def trigger(event)
  @synchronous.trigger(event)

  unless active_record_available?
    raise LoadError, 'TransactionalEventManager requires ActiveRecord >= 7.2 ' \
                     '(after_all_transactions_commit). Load Rails before using it.'
  end

  ::ActiveRecord.after_all_transactions_commit do
    deferred_dispatch(event)
  end
end

#unsubscribe(subscriber, from:) ⇒ Object



37
38
39
40
# File 'lib/koine/event_manager/rails.rb', line 37

def unsubscribe(subscriber, from:)
  @synchronous.unsubscribe(subscriber, from: from)
  super
end