Class: Axn::Core::Executor

Inherits:
Object
  • Object
show all
Defined in:
lib/axn/core/executor.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: ConsistencyMismatch, ContractFailure

Instance Method Summary collapse

Constructor Details

#initialize(action) ⇒ Executor

Returns a new instance of Executor.



211
212
213
214
215
# File 'lib/axn/core/executor.rb', line 211

def initialize(action)
  @action = action
  @action_class = action.class
  @context = action.instance_variable_get(:@__context)
end

Instance Method Details

#prepare_inbound_for_facets!Object

Best-effort inbound preparation for OUT-OF-BAND facet resolution — the async exhaustion/discard report path (Axn::Async::ExceptionReporting), where an action is reconstructed from job args and never executed. Top-level and subfield coerce/preprocess/default now resolve lazily on the read path (ContractForSubfields.resolve_value), so a facet reading a coerced/defaulted/preprocessed input resolves the value the worker would see with no eager pass — the same lazy behavior model: readers already relied on here. This just clears any pre-pipeline memo so those reads resolve against the settled inputs. Deliberately does NOT validate (a report on already-dead work must never raise) and does NOT run the action. Any failure is swallowed — a partially-prepared instance still yields more facets than a bare one.



244
245
246
247
248
# File 'lib/axn/core/executor.rb', line 244

def prepare_inbound_for_facets!
  Axn::Extensions.best_effort("preparing inbound context for async facet resolution", action: @action) do
    _clear_pre_pipeline_memos!
  end
end

#resolve_inbound_facets(sources) ⇒ Object

Input-phase facet resolution for enqueue-time sinks (e.g. Sidekiq job tags), where there is no run to hang completion-time resolution on. Resolves only from: :inputs facets (via the memoized resolved_input_* readers) against the RAW enqueued inputs. It deliberately does NOT run preprocess/defaults: those are user hooks that must execute once, at perform — a dynamic default:/preprocess: run here would both double-execute (enqueue AND perform) and compute a value that can differ from the run, so the facet would drift from its own job. Resolving from raw inputs keeps the facet in lockstep with the serialized payload the worker receives. from: :result facets are excluded by construction (they can't resolve before the body runs); a model: field's record still loads lazily (facade.rb) if a resolver reads it. Returns one resolved map per enabled source (tags, then dimensions), kept SEPARATE so a name declared as both a tag and a dimension yields two facets rather than one clobbering the other. sources is a subset of %i[tag dimension]. See PRO-2855.



262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/axn/core/executor.rb', line 262

def resolve_inbound_facets(sources)
  # Resolve readers in raw mode (ContractForSubfields.resolve_value): a facet reading an input sees the
  # raw serialized value, not the coerced/preprocessed/defaulted run-time value, so it stays in lockstep
  # with the payload the worker receives and a dynamic hook is not run at enqueue.
  @action.instance_variable_set(:@__resolve_raw_reads, true)
  maps = []
  maps << resolved_input_tags if sources.include?(:tag)
  maps << resolved_input_dimensions if sources.include?(:dimension)
  maps
ensure
  @action.remove_instance_variable(:@__resolve_raw_reads) if @action.instance_variable_defined?(:@__resolve_raw_reads)
end

#runObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/axn/core/executor.rb', line 217

def run
  Core::NestingTracking.tracking(@action) do
    with_tracing do
      with_logging do
        with_timing do
          with_exception_handling do
            with_contract do
              with_hooks do
                @action.call
              end
            end
          end
        end
      end
    end
  end
end