@nzelajs/node-advanced
v0.1.0
Published
Advanced node handlers for the Nzela engine: subprocess fan-out with join semantics and external wait/timeout parking. Vendor-free.
Maintainers
Readme
@nzelajs/node-advanced
English below · Version francaise plus bas.
The advanced node handlers of the Nzela engine: subprocess (spawn child instances and join on
their completion) and wait (park until a signed external event or a timeout). Opt-in: a generic
app never loads them. Vendor-free.
English
Install
npm add @nzelajs/node-advanced @nzelajs/coreWhat it provides
subprocessNodeHandler({ outboxSigner }): the fan-out/join node.- On entry: runs the node's effects, then reads
node.subprocess(joindefaults toall;resumeActiondefaults to the node's first outgoing transition, else it throws). Behavior:- No spec, no children, or
join: "none": crosses the resume transition immediately. Anonejoin still spawns its children fire-and-forget (per-specautoSubmit), WITHOUT a blocking dependency. all/anywith children: creates every child and its join dependency FIRST (so a child that completes synchronously on submit already sees every sibling dependency), then submits the children (unlessautoSubmitis explicitlyfalse). The parent stays parked on the node; the core wakes it via its dependency joins when the join is met (all= every child done,any= the first). Each child inherits the parent's requester and beneficiary;formMapcopies parent form fields into the child (child key -> parent key). Waking the parent may in turn wake ITS parent (DAG recursion).
- No spec, no children, or
- Emits a signed
case.subcase.spawnedoutbox event per child.
- On entry: runs the node's effects, then reads
waitNodeHandler({ outboxSigner }): the external-parking node.- On entry: runs the node's effects, registers an external wait (a fresh token), schedules
the timeout timer when
wait.timeoutis declared, emits a signedcase.external.waitingevent, then rests on the node. The instance is resumed by the engine'sresumeFromExternal(webhook:wait.onResolve, else the first outgoing transition) orexpireExternalWait(timeout:wait.onTimeout; a no-op when noonTimeoutis declared). This handler only parks; it never resumes.
- On entry: runs the node's effects, registers an external wait (a fresh token), schedules
the timeout timer when
registerAdvancedHandlers(registry, { outboxSigner }): register both handlers at once.- Building block:
resumeActionFor.
Example
import { InMemoryNodeHandlerRegistry, NzelaEngine } from "@nzelajs/core";
import { registerAdvancedHandlers } from "@nzelajs/node-advanced";
import { registerGenericHandlers } from "@nzelajs/node-auto";
const handlers = new InMemoryNodeHandlerRegistry();
registerGenericHandlers(handlers); // state + auto, for the states around the advanced nodes
registerAdvancedHandlers(handlers, { outboxSigner });
const engine = new NzelaEngine({
uow,
blueprints,
guards,
effects,
clock,
outboxSigner,
handlers,
});Security note: everything fails closed. A subprocess node without a resume transition throws; the
handler requires the core engine context (spawnChild / submitChild) and throws outside it. An
unknown or already-closed external wait throws (never double-applied).
Francais
Installation
npm add @nzelajs/node-advanced @nzelajs/coreCe que ca fournit
subprocessNodeHandler({ outboxSigner }): le noeud d'essaimage/jointure.- A l'entree : execute les effets du noeud, puis lit
node.subprocess(joinvautallpar defaut ;resumeActionvaut par defaut la 1re transition sortante du noeud, sinon leve). Comportement :- Pas de spec, aucun enfant, ou
join: "none": franchit la reprise immediatement. Une jointurenoneengendre quand meme ses enfants (fire-and-forget,autoSubmitde la spec), SANS dependance bloquante. all/anyavec enfants : cree TOUS les enfants et leur dependance de jointure d'abord (un enfant qui se termine de facon synchrone a la soumission voit deja toutes les dependances soeurs), puis soumet les enfants (sauf siautoSubmitvaut explicitementfalse). Le parent reste gare sur le noeud ; le coeur le reveille via ses jointures de dependance quand la jointure est atteinte (all= tous les enfants finis,any= le premier). Chaque enfant herite du demandeur et du beneficiaire du parent ;formMaprecopie des champs du parent vers l'enfant (cle enfant -> cle parent). Reveiller le parent peut a son tour reveiller SON parent (recursion du DAG).
- Pas de spec, aucun enfant, ou
- Emet un evenement outbox signe
case.subcase.spawnedpar enfant.
- A l'entree : execute les effets du noeud, puis lit
waitNodeHandler({ outboxSigner }): le noeud d'attente externe.- A l'entree : execute les effets du noeud, enregistre une attente externe (jeton neuf),
planifie le timer de timeout si
wait.timeoutest declare, emet un evenement signecase.external.waiting, puis se gare sur le noeud. Le dossier est repris par le moteur viaresumeFromExternal(webhook :wait.onResolve, sinon la 1re transition sortante) ouexpireExternalWait(timeout :wait.onTimeout; no-op sansonTimeout). Ce handler ne fait que garer ; il ne reprend jamais.
- A l'entree : execute les effets du noeud, enregistre une attente externe (jeton neuf),
planifie le timer de timeout si
registerAdvancedHandlers(registry, { outboxSigner }): enregistre les deux handlers.- Brique :
resumeActionFor.
Note de securite : tout echoue ferme. Un noeud subprocess sans transition de reprise leve ; le
handler exige le contexte du moteur (spawnChild / submitChild) et leve en dehors. Une attente
externe inconnue ou deja close leve (jamais appliquee deux fois).
License
Apache-2.0.
