Module: Easyop::Flow::CallBehavior

Defined in:
lib/easyop/flow.rb

Overview

Prepended so that Flow’s ‘call` takes precedence over Operation’s no-op even though Operation is included inside Flow.included (which would otherwise place Operation earlier in the ancestor chain than Flow itself).

Instance Method Summary collapse

Instance Method Details

#callObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/easyop/flow.rb', line 56

def call
  # ── Flow-tracing forwarding for the Recording plugin ──────────────────
  # When Recording is NOT installed on this flow class (i.e. the flow does
  # not inherit from a base operation that has Recording), set the
  # __recording_parent_* ctx keys manually so every step operation knows
  # this flow is its parent.  When Recording IS installed on the flow (its
  # RunWrapper runs before `call` is reached), it has already set up the
  # parent context correctly — we detect that via _recording_enabled? and
  # skip to avoid a conflict.  If Recording is not used at all, these ctx
  # keys are unused and ignored.
  _flow_tracing = self.class.name &&
                  !self.class.respond_to?(:_recording_enabled?)
  if _flow_tracing
    ctx[:__recording_root_reference_id]     ||= SecureRandom.uuid
    _prev_parent_name                         = ctx[:__recording_parent_operation_name]
    _prev_parent_id                           = ctx[:__recording_parent_reference_id]
    ctx[:__recording_parent_operation_name]   = self.class.name
    ctx[:__recording_parent_reference_id]     = SecureRandom.uuid
  end

  pending_guard = nil

  self.class._flow_steps.each do |step|
    if step.is_a?(Proc)
      pending_guard = step
      next
    end

    # Evaluate lambda guard if present (placed before step in flow list)
    if pending_guard
      skip = !pending_guard.call(ctx)
      pending_guard = nil
      next if skip
    end

    # Evaluate class-level skip_if predicate declared on the step itself
    next if step.respond_to?(:skip?) && step.skip?(ctx)

    instance = step.new
    instance._easyop_run(ctx, raise_on_failure: true)
    ctx.called!(instance)
  end
rescue Ctx::Failure
  ctx.rollback!
  raise
ensure
  # Restore parent context so any caller above this flow sees the right parent.
  if _flow_tracing
    ctx[:__recording_parent_operation_name] = _prev_parent_name
    ctx[:__recording_parent_reference_id]   = _prev_parent_id
  end
end