Module: Easyop::Plugins::Recording::RunWrapper

Defined in:
lib/easyop/plugins/recording.rb

Instance Method Summary collapse

Instance Method Details

#_easyop_run(ctx, raise_on_failure:) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/easyop/plugins/recording.rb', line 172

def _easyop_run(ctx, raise_on_failure:)
  return super unless self.class._recording_enabled?
  return super unless (model = self.class._recording_model)
  return super unless self.class.name # skip anonymous classes

  # Snapshot the keys present in ctx RIGHT NOW — before any internal
  # tracing keys are written and before the operation body runs. This
  # lets _recording_safe_params emit only what was passed IN, not values
  # computed during the call (those belong in result_data).
  input_keys = ctx.to_h.keys

  # -- Flow tracing --
  # Each operation gets its own reference_id. The root_reference_id is
  # shared across the entire execution tree via ctx (set once, inherited).
  reference_id      = SecureRandom.uuid
  root_reference_id = ctx[:__recording_root_reference_id] ||= SecureRandom.uuid

  # Read current parent context — these become THIS operation's parent fields.
  parent_operation_name = ctx[:__recording_parent_operation_name]
  parent_reference_id   = ctx[:__recording_parent_reference_id]

  # Execution index: 1-based position among siblings (nil for root operations).
  # Counts are tracked per-parent in a hash stored in ctx so sibling chains
  # and nested sub-trees each maintain independent counters.
  execution_index = if parent_reference_id
    counts = ctx[:__recording_child_counts] ||= {}
    counts[parent_reference_id] = (counts[parent_reference_id] || 0) + 1
  end

  # Set THIS operation as the parent for any children that run inside super.
  # Save the previous values so we can restore them after (for siblings).
  prev_parent_name = parent_operation_name
  prev_parent_id   = parent_reference_id
  ctx[:__recording_parent_operation_name] = self.class.name
  ctx[:__recording_parent_reference_id]   = reference_id

  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  super
ensure
  # Always record — including when raise_on_failure: true raises Ctx::Failure
  # (e.g. when this operation is a step inside a Flow). Without the ensure
  # branch the tap block would be skipped and failures inside flows would
  # never be persisted.
  if start
    # Restore parent context so sibling steps see the correct parent.
    ctx[:__recording_parent_operation_name] = prev_parent_name
    ctx[:__recording_parent_reference_id]   = prev_parent_id

    ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
    _recording_persist!(ctx, model, ms,
      root_reference_id:     root_reference_id,
      reference_id:          reference_id,
      parent_operation_name: parent_operation_name,
      parent_reference_id:   parent_reference_id,
      execution_index:       execution_index,
      input_keys:            input_keys)
  end
end