Module: StateMachines::AsyncMode::AsyncEventExtensions

Defined in:
lib/state_machines/async_mode/async_event_extensions.rb

Overview

Extensions to Event class for async bang methods

Instance Method Summary collapse

Instance Method Details

#define_helper(scope, method, *args, &block) ⇒ Object

Generate async bang methods for events when async mode is enabled



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/state_machines/async_mode/async_event_extensions.rb', line 8

def define_helper(scope, method, *args, &block)
  result = super

  # If this is an async-enabled machine and we're defining an event method
  if scope == :instance && method !~ /_async[!]?$/ && machine.async_mode_enabled?
    qualified_name = method.to_s

    # Create async version that returns a task
    machine.define_helper(scope, "#{qualified_name}_async") do |machine, object, *method_args, **kwargs|
      # Find the machine that has this event
      target_machine = object.class.state_machines.values.find { |m| m.events[name] }

      unless defined?(::Async::Task) && ::Async::Task.current?
        raise RuntimeError, "#{qualified_name}_async must be called within an Async context"
      end

      Async do
        target_machine.events[name].fire(object, *method_args, **kwargs)
      end
    end

    # Create async bang version that raises exceptions when awaited
    machine.define_helper(scope, "#{qualified_name}_async!") do |machine, object, *method_args, **kwargs|
      # Find the machine that has this event
      target_machine = object.class.state_machines.values.find { |m| m.events[name] }

      unless defined?(::Async::Task) && ::Async::Task.current?
        raise RuntimeError, "#{qualified_name}_async! must be called within an Async context"
      end

      Async do
        # Use fire method which will raise exceptions on invalid transitions
        target_machine.events[name].fire(object, *method_args, **kwargs) || raise(StateMachines::InvalidTransition.new(object, target_machine, name))
      end
    end
  end

  result
end