Documentation

What Is a Process?

In the data model, a Process is a database entity that owns a ProcessDefinition — a tree of configuration that describes what threads exist and what nodes each thread contains.

At runtime, a ProcessExecutionContext is created to track the live state of a single execution run. This context is separate from the definition — the same process definition can be running as many parallel execution contexts simultaneously.

ProcessDefinition

The static, versioned blueprint. Loaded once from the database and cached. Contains all thread definitions, element definitions, and connector bindings.

ProcessExecutionContext

The live execution state. Created fresh per run. Holds ExecutorID, start time, current state, and accumulated output from all threads.

Execution Flow

flowchart TD A["Clean up stale pause signals\nRemove orphaned signals from previous runs"] B["Start the execution context\nSet state Running · Stamp start time"] C["Load the ProcessDefinition\nCached blueprint of threads and nodes"] D["Raise ProcessStarting event\nTelemetry · Logging · UI notification"] E{"Any threads?"} F["Execute threads — sequentially\nCheck: cancellation · webhook filter · pause signal"] G["Accumulate thread output\nPrefix keys with thread_threadID_"] H{"All threads passed?"} I["Mark Failed · Stop\nDownstream threads may depend on this output"] J["Raise ProcessCompleted event\nTransition state · Clean up resources"] K(["ProcessExecutionResult"]) A-->B-->C-->D-->E E-- Yes -->F-->G-->H E-- No -->J H-- Yes -->J-->K H-- No -->I style A fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style B fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style C fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style D fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style E fill:#2d2616,stroke:#fbbf24,color:#e2e8f0 style F fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style G fill:#1e2640,stroke:#6c8cff,color:#e2e8f0 style H fill:#2d2616,stroke:#fbbf24,color:#e2e8f0 style I fill:#2d1616,stroke:#f87171,color:#e2e8f0 style J fill:#162d22,stroke:#34d399,color:#e2e8f0 style K fill:#162d22,stroke:#34d399,color:#c8ffd8

Step-by-Step

1

Clean up stale pause signals

Before anything else, any orphaned pause signal from a previous failed execution is removed. Stale signals can cause a healthy new execution to immediately pause — cleaning them first prevents this.

2

Start the execution context

processExecutionContext.Start(executorID) stamps the start time, sets state to Running, and initializes output tracking. The ExecutorID encodes ProcessID and AppID so every piece of execution data knows what it belongs to.

3

Load the ProcessDefinition

The definition is loaded via IProcessDefinitionService.LoadProcessAsync. If already loaded and attached to the operating context (as happens in resume scenarios), the cached copy is used.

4

Raise ProcessStarting event

The event system fires ProcessStarting. Any registered IExecutionEventHandler implementations receive this notification. Typical uses: logging, telemetry, audit trails, signaling the UI.

5

Check: are there any threads?

If the process has no active threads, execution ends immediately with state Completed. This protects against empty process definitions being silently stuck.

6

Execute threads — sequentially

Each thread is executed one at a time, in definition order. Before each thread, three checks are made:

  • Cancellation — if the cancellation token is signalled, the process stops with state Cancelled.
  • Webhook filter — if triggered by a webhook targeting a specific thread, all other threads are skipped.
  • Pause signal — if a pause was requested externally, the process pauses after the current thread. The pause signal is then reset.
7

Accumulate thread output

After each thread completes, its output data is merged into the process context. To avoid key collisions when multiple threads produce data, each thread's output key is prefixed with thread_{threadID}_.

8

Fail-fast on thread failure

If any thread finishes with a non-Completed status, the process stops processing further threads and marks itself Failed. This is intentional — downstream threads may depend on the failed thread's outputs.

9

Raise ProcessCompleted event & finalize

The ProcessCompleted event fires. State transitions to Completed. Execution state is cleaned up. ProcessExecutionResultHelper.CloneFromContext snapshots the final context into an immutable result which is returned to the caller.

Process State Machine

stateDiagram-v2 direction LR [*] --> Running : Start Running --> Completed : All threads done Running --> Failed : Thread failed Running --> Cancelled : Token cancelled Running --> Paused : Pause signal received Paused --> Running : ContinueAsync Completed --> [*] Failed --> [*] Cancelled --> [*]
StateMeaningCan transition to
RunningActively executing threadsCompleted, Failed, Cancelled, Paused
CompletedAll threads finished successfully
FailedA thread failed or threw an unhandled exception
CancelledCancellationToken was signalled
PausedPause signal was received mid-executionRunning (on resume)

Webhook Filter

When a process is triggered by an incoming webhook, only the thread that owns the webhook trigger node should activate. The WebhookFilter on the execution context carries a ProcessThreadID and a StartFromProcessElementID.

Threads are sequential, not parallel At the process level, threads run one after another. Parallelism within a single thread is managed by the parallel fork/join node pattern described in the Thread page.