Descrizione
Operatore enterprise di composizione workflow-as-function — il pattern fondamentale di modularizzazione che permette di chiamare un altro workflow del tenant come fosse uno step del workflow corrente, l'equivalente di una funzione nella programmazione classica. Invoca un sub-workflow target (identificato via workflowId selezionato dal picker della UI editor) passando l'output dello step upstream come input al sub, ed il return value del sub-workflow diventa l'output del nodo logic_subworkflow nel parent — pattern transparent che permette di astrarre logica condivisa in un mini-workflow riusabile in N posti. Esecuzione sincrona di default (await fino al completamento del sub) — il workflow parent blocca su questo step finché il sub non ritorna (anche se gira per ore per task long-running come ETL nightly). Opzione asincrona fire-and-forget configurable: lancia il sub e prosegue immediatamente con runId del sub come output — pattern per orchestrazione di N children parallel senza dover aspettarli tutti (es. master workflow che lancia 50 children "process customer" in parallelo e prosegue alla aggregation step dopo che tutti hanno emit signal completed). Anti-loop guard enterprise multi-livello: self-recursion detection (workflow A che chiama A → block immediato con errore semantico esplicito "self-recursion detected"), depth-cap configurable via env FLOWFORGE_MAX_SUBWORKFLOW_DEPTH (default 10 — il valore comfortable per il pattern enterprise di nesting ragionevole; oltre serve override esplicito operatore per evitare resource exhaustion); propagation della depth via X-Subworkflow-Depth header tra parent→child HTTP run dispatch — l'engine incrementa di +1 ad ogni nested call e block se cap raggiunto, prevenendo recursion-bomb attack o workflow malformati con cycle indiretto. Tenant isolation: il sub-workflow DEVE appartenere allo stesso tenant del parent (non possiamo chiamare workflow di altri tenant — multi-tenant security boundary), enforce a livello del runtime via tenantId check. Use case classici di modularizzazione: estrarre logica condivisa "send-notification-email" usata da 20 workflow diversi del tenant — invece di copy-paste della sequence Sentinel + audit + render + send in ognuno, creo un sub "notification" riusato in tutti; orchestrare workflow gerarchici master → children (es. master nightly batch che lancia 10 children paralleli per ognuno dei tenant del SaaS managed); modularizzare workflow grossi in mini-workflow indipendenti (un workflow "onboarding cliente" decomposto in 5 sub: validate_form, create_user, provision_resources, send_welcome_email, schedule_followup_call — ciascuno testabile e maintainable separatamente); pattern Strategy programmation con sub-workflow configurati dinamicamente in base al tipo di evento upstream (logic_switch → 5 logic_subworkflow diversi per 5 type di evento gestiti); DRY refactoring di workflow legacy con duplicazione enorme di logica in un canonical sub.
