Class: Hecks::Runtime::EntityInterpreter
- Inherits:
-
Object
- Object
- Hecks::Runtime::EntityInterpreter
- Includes:
- CommandInterpreter::ArgumentGate, Interpreting
- Defined in:
- lib/hecks/runtime/entity_interpreter.rb
Defined Under Namespace
Classes: Context
Constant Summary collapse
- DISPATCH_ORDER =
THE DECLARED ORDER, HAND-TYPED — mirrors Vocabulary::EntityDispatchOrder (language/bluebook/vocabulary.bluebook:217-232), held equal to it by spec/vocabulary_conformance_spec.rb the same way CommandInterpreter's own DISPATCH_ORDER is; see that constant's doc comment for why this is hand-typed rather than read live off the meta-domain at every dispatch.
refuse_unknown_arguments/refuse_absent_argumentsnow lead it, same positionAggregateDispatchOrderholds them at (H1, above) — the only remaining difference from the aggregate order is noassign_creation_attributes(an entity is never created through this path). Hecks::Vocabulary.symbols("EntityDispatchOrder")
- MAX_STALE_WRITE_RETRIES =
Same safety valve as
CommandInterpreter::MAX_STALE_WRITE_RETRIES— see that constant's own comment. 5
Instance Attribute Summary collapse
-
#registry ⇒ Object
readonly
Returns the value of attribute registry.
Instance Method Summary collapse
-
#call(domain, aggregate, dotted, legacy_args, route: nil, with: nil, dry_run: false) ⇒ Object
dry_run:— CommandInterpreter#call's own twin, see that method's comment for the shared reasoning (Dispatcher#dry_run?'s own entry point). -
#initialize(registry, rules:) ⇒ EntityInterpreter
constructor
A new instance of EntityInterpreter.
Methods included from Interpreting
Constructor Details
#initialize(registry, rules:) ⇒ EntityInterpreter
Returns a new instance of EntityInterpreter.
68 69 70 71 |
# File 'lib/hecks/runtime/entity_interpreter.rb', line 68 def initialize(registry, rules:) @registry = registry @rules = rules end |
Instance Attribute Details
#registry ⇒ Object (readonly)
Returns the value of attribute registry.
33 34 35 |
# File 'lib/hecks/runtime/entity_interpreter.rb', line 33 def registry @registry end |
Instance Method Details
#call(domain, aggregate, dotted, legacy_args, route: nil, with: nil, dry_run: false) ⇒ Object
dry_run: — CommandInterpreter#call's own twin, see that method's
comment for the shared reasoning (Dispatcher#dry_run?'s own entry
point). step_save/step_emit are the only two steps here that
read it either.
RETRIES THE WHOLE METHOD BODY on StaleWrite — same reasoning as
CommandInterpreter#call's own retry: a fresh ctx, a fresh
step_hydrate_parent/step_locate_element re-reading current
state.
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 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/hecks/runtime/entity_interpreter.rb', line 81 def call(domain, aggregate, dotted, legacy_args, route: nil, with: nil, dry_run: false) *entity_names, command_name = dotted.to_s.split(".") if entity_names.empty? raise UnknownVerb, RefusalWording.render("UnknownVerb", "entity_unknown", aggregate: aggregate.hecks_name, entity: dotted.to_s.inspect) end chain = walk_entity_chain(aggregate, entity_names) entity = chain.last command = entity.command(command_name) || raise(UnknownVerb, RefusalWording.render("UnknownVerb", "entity_no_command", entity: entity.hecks_name, command: command_name.inspect)) args = Routing.payload(command, with: with, legacy: legacy_args) attempt = 0 begin ctx = Context.new(domain, aggregate, entity, entity_names.join("."), command, command_name, args) ctx.chain = chain ctx.route = route ctx.dry_run = dry_run # `root_aggregate:` — `entity` is the immediate owner (what # `owner_fields` inside the Analyzer means), but a `parent.X` # read inside this command's own given/ensures means the ROOT # aggregate's own field, not the entity's — `aggregate` here IS # that root (this method's own first parameter, never the # entity). See DependencyPlanning::Analyzer.call's own header # for the bug this closes. ctx.plan = DependencyPlanning::Analyzer.call(aggregate: entity, command: command, root_aggregate: aggregate) # RESOLVED HERE, ONCE — see CommandInterpreter#call's own comment; # `step_hydrate_parent` reads `ctx.repository` without re-fetching. ctx.repository = @registry.repository(domain, aggregate) lock_id = Identity.best_effort(aggregate, args, route) run_dispatch_order_with_isolation(DISPATCH_ORDER, ctx, lock_key_id: lock_id) [ctx.instance, ctx.result, ctx.plan, ctx.persistence_outcome] rescue StaleWrite attempt += 1 retry if attempt < MAX_STALE_WRITE_RETRIES raise end end |