Module: Hecks::Runtime::Routing
- Defined in:
- lib/hecks/runtime/routing.rb
Overview
The invocation address is not part of a command's domain payload. Aggregate commands carry one receiver identity; entity commands carry the aggregate receiver followed by one identity for every entity hop.
Defined Under Namespace
Classes: Envelope
Class Method Summary collapse
- .envelope(to, entity_depth: 0) ⇒ Object
-
.payload(command, with:, legacy:) ⇒ Object
with:is deliberately strict.
Class Method Details
.envelope(to, entity_depth: 0) ⇒ Object
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 47 |
# File 'lib/hecks/runtime/routing.rb', line 19 def envelope(to, entity_depth: 0) return nil if to.nil? aggregate, entities = if to.is_a?(Hash) hash = to.transform_keys(&:to_sym) unknown = hash.keys - %i[aggregate entity entities] unless unknown.empty? raise TypeMismatch, "to: does not recognize #{unknown.sort.join(', ')}" end [hash[:aggregate], entity_identities(hash)] else [to, []] end if aggregate.nil? || aggregate.to_s.empty? raise TypeMismatch, "to: must name the receiving aggregate identity" end if entities.size != entity_depth raise TypeMismatch, "to: for an entity command needs #{entity_depth} entity " \ "#{entity_depth == 1 ? 'identity' : 'identities'} after the aggregate — got #{entities.size}" end if entities.any? { |identity| identity.nil? || identity.to_s.empty? } raise TypeMismatch, "to: contains a blank entity identity" end Envelope.new(aggregate: aggregate, entities: entities) end |
.payload(command, with:, legacy:) ⇒ Object
with: is deliberately strict. Compatibility-only calls still pass
loose keyword arguments through the old addressing gate, but a caller
choosing the explicit envelope cannot smuggle receiver identity back
into the payload.
53 54 55 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 |
# File 'lib/hecks/runtime/routing.rb', line 53 def payload(command, with:, legacy:) if with && !legacy.empty? raise TypeMismatch, "dispatch takes command facts in with:, not both with: and loose keyword arguments" end return legacy unless with unless with.is_a?(Hash) raise TypeMismatch, "with: must be a hash of command facts" end offered = with.transform_keys(&:to_sym) declared = command.attributes.map { |attribute| attribute.name.to_sym } unknown = (offered.keys - declared).sort unless unknown.empty? reading = declared.empty? ? "none" : declared.join(", ") raise UnknownArgument, RefusalWording.render("UnknownArgument", "unknown_args", command: command.hecks_name, unknown: unknown.join(", "), declared: reading) end absent = command.attributes.reject(&:optional?).map { |attribute| attribute.name.to_sym } - offered.keys unless absent.empty? reading = declared.empty? ? "none" : declared.join(", ") raise AbsentArgument, RefusalWording.render("AbsentArgument", "absent_args", command: command.hecks_name, absent: absent.sort.join(", "), declared: reading) end offered end |