Workflows — Execution Model
Dit document beschrijft het execution model van Workflows 2.0: de database-entiteiten, statusovergangen, hoe execution results worden opgebouwd en hoe het Management Portal de status opvraagt.
Database-entiteiten
Het execution model bestaat uit drie primaire tabellen:
Workflows_Executions
Elke workflow execution heeft één rij in deze tabel. De kolommen:
Kolom | Type | Beschrijving |
|---|---|---|
| GUID | Unieke execution identifier |
| GUID | Tenant waarvoor de execution loopt |
| GUID | Verwijzing naar |
| GUID | Gelocked versie op moment van aanmaak |
| string | ID van de Hangfire Batch die alle jobs groepeert |
| string |
|
| JSON | Employee-object + changes + trigger metadata |
| string | Zie statusovergangen |
| bit |
|
| datetime | Gezet wanneer status overgaat naar |
| datetime | Gezet wanneer |
| string | Foutmelding bij |
De VersionId wordt bij aanmaken van de execution bepaald en nooit meer gewijzigd. Dit garandeert dat een lopende execution altijd de workflow definitie gebruikt die gold bij de start — ook als de workflow nadien wordt aangepast en opnieuw gepubliceerd.
Workflows_ExecutionJobs
Per node in de workflow die wordt uitgevoerd, wordt één rij aangemaakt. De kolommen:
Kolom | Type | Beschrijving |
|---|---|---|
| GUID | Unieke job identifier |
| GUID | Verwijzing naar |
| GUID | Verwijzing naar de node-ID in de workflow definitie |
| string |
|
| string | Leesbare naam (label uit de node data) |
| JSON | Geserialiseerde |
| JSON | Resultaat van de activity (bijv. email MessageId, webhook response) |
| string | ID van de bijbehorende Hangfire job |
| string | Zie statusovergangen |
| int | Volgorde binnen de execution (incrementeel) |
| bit |
|
| datetime | Begin van uitvoering |
| datetime | Einde van succesvolle uitvoering |
| datetime | Tijdstip van fout |
| long | Uitvoerduur in milliseconden |
| string | Foutmelding |
| string | Stack trace bij fout |
| int | Automatisch verhoogd bij elke |
| datetime | Tijdstip waarvoor de job is gepland (bij hire date of delay) |
Workflows_Definitions en Workflows_Versions
De workflow definitie en versies zijn twee aparte entiteiten:
Workflows_Definitions— bevat naam, trigger type,IsActive, en een verwijzing naarActiveVersionId.Workflows_Versions— bevat de daadwerkelijke JSON payload met nodes en edges. Een definitie heeft maximaal één draft-versie en één actieve versie.
Bij publiceren van een draft wordt in een SQL-transactie:
De huidige actieve versie op
IsActive = 0gezet.De draft-versie gepubliceerd (
IsPublished = 1,IsActive = 1).De
ActiveVersionIdvan de definitie bijgewerkt.
Statusovergangen van een execution
De UpdateExecutionStatusAsync in de repository handelt de StartedAtUtc en CompletedAtUtc automatisch af:
Statusovergangen van een job
Jobs die zijn aangemaakt voor nodes op een niet-genomen conditietak worden direct op Skipped gezet (IsSkipped = 1). Ze ontvangen geen Hangfire job ID en worden nooit uitgevoerd.
De RetryCount kolom wordt verhoogd bij elke transitie naar Failed:
Opbouw van execution results
De output van een activity job wordt opgeslagen in OutputData als JSON. Elk activity type produceert een eigen formaat:
WorkflowTriggerActivityJob
Slaat de volledige TriggerData op als output — het employee-object inclusief alle Graph-properties. Downstream action jobs lezen dit via GetTriggerNodeForExecutionAsync:
WorkflowActionActivityJob — Email
Bij geen geldige ontvangers na template-resolutie:
WorkflowActionActivityJob — Webhook
WorkflowConditionActivityJob
Status opvragen — API endpoints
GET /api/workflows/executions//status
De GetExecutionStatusCommandHandler bouwt een volledig statusoverzicht op. Het response bevat:
Execution metadata (status, tijdstippen, employee info)
De gelocked versie ID en het versienummer
Een geordende lijst van
ExecutionStepInfoper node (topologisch gesorteerd)
De stappen worden via een topologische sortering van de graph bepaald, niet via de volgorde in de database. Dit zorgt voor een correcte volgorde ook bij parallelle paden.
Voor jobs met status Pending en een Hangfire job ID wordt ook de Hangfire-staat gecontroleerd om de ScheduledForUtc te tonen:
GET /api/workflows/executions/active
Haalt alle executions op waar IsTerminal = 0, geordend op aanmaaktijdstip.
GET /api/workflows/executions/history
Haalt alle executions op waar IsTerminal = 1, geordend op afrondingstijdstip.
Real-time updates via SignalR
Het Management Portal ontvangt real-time statusupdates via de WorkflowExecutionsHub SignalR hub. Clients subscriben op tenant-niveau:
De WorkflowNotificationService stuurt drie event types via IHubContext<WorkflowExecutionsHub>:
Event | Trigger | Payload |
|---|---|---|
| Nieuwe execution aangemaakt |
|
| Execution status gewijzigd |
|
| Job status gewijzigd |
|
Elke activity job stuurt JobUpdated events bij de overgang naar Running, Completed en Failed. Dit stelt het Management Portal in staat om per stap de voortgang te tonen zonder polling.
Toegangscontrole in de hub:
Eigen tenant: altijd toegestaan.
Cross-tenant: alleen voor MSP-tenants met de rol
Automate365.Customers.ReadWrite, en alleen voor tenants waarbijPartnerTenantIdovereenkomt.
Retry mechanisme
Een mislukte execution kan worden herstart via POST /api/workflows/executions/{id}/retry. De retry maakt een nieuwe execution aan met de originele trigger data, aangevuld met retry metadata:
Beperkingen:
Alleen executions met status
Failedkunnen worden herstart.De retry-window is 7 dagen na de fout.
De workflow moet nog actief zijn en een gepubliceerde versie hebben.
De nieuwe execution gebruikt de huidige actieve versie, niet de versie waarmee de originele execution liep.
Cancel mechanisme
Een lopende execution kan worden geannuleerd via POST /api/workflows/executions/{id}/cancel. De handler:
Zet de execution status op
Cancelled(IsTerminal = true).Zoekt alle enqueued, scheduled en processing Hangfire jobs op die bij de execution horen via argument matching op
executionId.Verwijdert alle gevonden jobs met
BackgroundJob.Delete.Stuurt een
ExecutionUpdatedSignalR event.
Jobs die al worden verwerkt (Processing) worden gevonden via monitoring.ProcessingJobs maar kunnen niet altijd worden gestopt — de Hangfire worker heeft de job al opgepakt. In dat geval voltooit de individuele job nog wel, maar de execution zelf heeft status Cancelled.