Module: Plutonium::Wizard::InstanceKey

Defined in:
lib/plutonium/wizard/instance_key.rb

Overview

Computes the deterministic identity digest a wizard session row is keyed by (§4). There are two builders, mirroring the two identity axes:

  • InstanceKey.concurrency — a wizard with a concurrency_key. The digest is over the wizard name and the serialized key value(s) (which already include the folded tenant, §4.4). The keyed row IS the lock — two launches with the same key collapse to one digest, so the second resumes the first.
  • InstanceKey.tokened — a wizard without a concurrency_key. The digest is over the wizard name and the per-launch wizard_token, so every launch is a fresh, independent (repeatable) run.

The two recipes MUST stay byte-identical between the place that creates rows (runner/driving) and the place that recomputes the key (the gate), or one-time gating silently breaks.

Class Method Summary collapse

Class Method Details

.concurrency(wizard_name, key_values) ⇒ String

Keyed (concurrency_key) identity.



30
31
32
# File 'lib/plutonium/wizard/instance_key.rb', line 30

def self.concurrency(wizard_name, key_values)
  digest("concurrency", wizard_name, serialize(key_values))
end

.serialize(value) ⇒ Object

Serialize a key value into a STRUCTURED, unambiguous form for the digest:

- Array 

Structure (not a flat join) is the point: the digest hashes the JSON of the nested form, so ["a", "b"] and the scalar "a|b" serialize to distinct JSON (["a","b"] vs "a|b") and can never collide. A separator-joined form would make a key element containing the separator indistinguishable from a structural boundary (two distinct runs collapsing to one row — cross-run data exposure / one-time gating satisfied by the wrong run).



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/plutonium/wizard/instance_key.rb', line 58

def self.serialize(value)
  case value
  when Array
    value.map { |v| serialize(v) }
  when nil
    nil
  when String, Symbol, Numeric, true, false
    value.to_s
  else
    if value.respond_to?(:to_global_id)
      value.to_global_id.to_s
    else
      value.to_s
    end
  end
end

.tokened(wizard_name, token) ⇒ String

Tokened (no concurrency_key) identity.



39
40
41
# File 'lib/plutonium/wizard/instance_key.rb', line 39

def self.tokened(wizard_name, token)
  digest("tokened", wizard_name, token.to_s)
end