Fief.Key.VnodeImpl (Fief v0.1.0)

Copy Markdown View Source

The sanctioned Fief.Vnode implementation (implementation.md §7): a plain key→pid map with monitors in the impl state (Decision: no Registry — every lookup already happens in the agent, so concurrent-read machinery buys nothing), key servers under a linked DynamicSupervisor started from init/2 (on_fence: :terminate) or the instance's Fief.Key.Limbo (weaker modes — see Fief.Key), and the M5 migration machines embedded per their moduledoc obligations. Built purely on the public behaviour — the proof the contract is sufficient.

Migration embedding (build-order M5 obligations → here)

  • handoff_outtwo-phase freeze (docs/key-redesign.md §4.2): every live key server gets the freeze advisory ({:fief_key_freeze, deadline_ms}, an EEP 76 priority message via the key's alias, normal-send fallback) then :fief_key_extract (parallel across servers — the agent is not the bottleneck); completions come back through the impl-message channel (handle_info/2, the M6 contract change). One per-freeze deadline timer (extract_deadline opt) backstops a key that never drains: at expiry every still-pending key is killed and converges through the died-before-extract path. Decision: the Donor machine is created when the ledger is complete; peer messages arriving mid-freeze are buffered and replayed into the machine in arrival order (a pull cannot be answered before the key's extraction settles anyway). A :frozen checkpoint marks completion.
  • handoff_in(session)Recipient.new/1; handoff_in(nil) after handoff_outDonor.regained/1 (the taint rule); an observed settle/abort while serving (the agent's reconcile rebind, handoff_in(nil)) → Recipient.session_over/1.
  • handle_peer → the five delivery events; key liveness is the key→pid map, consulted honestly — live keys are messaged directly and never reach the machine; first_touch runs only for non-live keys; live? for grant/push/not-here is Map.has_key?(keys, key_id).
  • The two tick cadences are seam timers armed in the agent (:fief_key_sweep / :fief_key_pull_retry, matched by ref — the impl-level stale-timer catch-all), interpreted through Donor.tick/1 / Recipient.tick/1. Effects are interpreted in list order.

Decisions recorded here

  • Cold-start origin (init/3, docs/key-redesign.md §2.3, §4.1): every incarnation runs the one init(key, source, ctx) callback; this impl chooses source and ctx.origin. {:escheat, key} effects and taint memory (escheat_next: Donor.regained/1's shipped set, surviving the machine) start keys {:fresh, :escheat}; a cold start with no machine and no memory is {:fresh, :first_touch}. A fresh owner after donor death cannot distinguish "existed elsewhere before" from "never existed" — :fresh is the locate-durable-truth path (design §8: "Start/locate is transparent"); the :escheat origin is the informational signal that the protocol knows recovery is happening.
  • Residual arrival vs resume: {:inject, key, blob} (grant/push arrival) starts {{:residual, blob}, :transfer}; {:resume, key, blob} and a late mid-freeze extraction start {{:residual, blob}, :resume}. Either way the blob is exactly an extract_state/1 product handed back to init/3.
  • Blob cap enforced at freeze (ledger assembly), the earliest donor-side ship gate — see Fief.Transfer.Channel. The ledger only ever holds shippable (already-ship/2-ed) blobs; fetch/2 runs before a {:residual, blob} init/3 and before a resume.
  • Sweep pacing is sweep_rate keys per sweep_interval ms (two opts composed with the seam-timer cadence, in place of §9's {100, :per_second} sketch); pull_retry_interval is the recipient cadence. Timers are armed lazily and cancelled when idle.

Impl opts (vnode_impl: {Fief.Key.VnodeImpl, ...}): hasher (Fief.Hasher.Default, a Fief.Hasher module — the fingerprinted key→vnode seam), sweep_rate (100), sweep_interval (1_000 ms), pull_retry_interval (1_000 ms), extract_deadline (5_000 ms — the per-freeze extract backstop, per-node tuning like the sweep/pull cadences, not fingerprinted), max_pending_per_key (128), max_blob_size (65_536), channel (Fief.Transfer.Channel.InBand).