UTIL_AsyncChain.ChainBuilder
Class
global inherited sharing class UTIL_AsyncChain.ChainBuilderFluent builder for configuring and executing an async chain. Provides methods for adding steps, setting context, configuring error/completion handlers, and executing the chain.
Example
String executionId = UTIL_AsyncChain.newChain('OrderProcessing')
.then(new ValidateOrderStep())
.then(new ProcessPaymentStep())
.withInitialContext('orderId', order.Id)
.onError(new NotifyAdminStep())
.onComplete(new SendConfirmationStep())
.execute();Methods
| Method | Description |
|---|---|
| global String execute() | Executes the chain with an auto-generated correlation ID. |
| global String execute(String correlationId) | Executes the chain with a caller-supplied correlation ID for log tracing. |
| global UTIL_AsyncChain.ChainBuilder onComplete(IF_Chain.Step completionHandlerStep) | Registers a completion handler step that executes ONLY when every step in the chain completes successfully. |
| global UTIL_AsyncChain.ChainBuilder onError(IF_Chain.Step errorHandlerStep) | Registers an error handler step that executes when any step fails (unless the failing step has continueOnError set to true). |
| global UTIL_AsyncChain.ChainBuilder then(IF_Chain.Step step) | Appends a step to the end of the chain. |
| global UTIL_AsyncChain.ChainBuilder then(IF_Chain.Step step, Boolean continueOnError) | Appends a step to the chain with explicit control over error continuation. |
| global UTIL_AsyncChain.ChainBuilder withAsyncOptions(AsyncOptions options) | Sets the AsyncOptions controlling queueable stack depth. |
| global UTIL_AsyncChain.ChainBuilder withDeduplicationKey(String deduplicationKey) | Guards against two overlapping runs of the same logical chain. |
| global UTIL_AsyncChain.ChainBuilder withDelayMinutes(Integer minutes) | Defers the chain's first step by the given number of minutes. |
| global UTIL_AsyncChain.ChainBuilder withInitialContext(String key, Object value) | Seeds the chain context with an initial key-value pair before execution begins. |
| global UTIL_AsyncChain.ChainBuilder withMaxContextSize(Integer maximumSize) | Sets the maximum serialized context size in characters. |
| global UTIL_AsyncChain.ChainBuilder withMaxSteps(Integer maximumSteps) | Sets the maximum number of steps the chain is allowed to execute. |
execute
global String execute()Executes the chain with an auto-generated correlation ID. Persists the chain configuration and enqueues the first step.
Returns String — The ID of the AsyncChainExecution__c record tracking this chain.
Throws
| Exception | Description |
|---|---|
| UTIL_Exceptions.IllegalStateException | If the serialized step list exceeds the StepLog__c field capacity less the per-step runtime reserve — see the correlation-ID overload this method delegates to. |
Example
String executionId = UTIL_AsyncChain.newChain('MyChain')
.then(new MyStep())
.execute();global String execute(String correlationId)Executes the chain with a caller-supplied correlation ID for log tracing. Persists the chain configuration and enqueues the first step.
Parameters
| Parameter | Type | Description |
|---|---|---|
correlationId | String | The correlation ID to attach to all log entries for this chain. |
Returns String — The ID of the AsyncChainExecution__c record tracking this chain.
Throws
| Exception | Description |
|---|---|
| UTIL_Exceptions.IllegalStateException | If the serialized step list exceeds the StepLog__c field capacity less the per-step runtime reserve — a chain that cannot persist its step list intact for its whole life must fail at definition time, never by silently truncating the persisted JSON. |
Example
String executionId = UTIL_AsyncChain.newChain('MyChain')
.then(new MyStep())
.execute('my-correlation-id');onComplete
global UTIL_AsyncChain.ChainBuilder onComplete(IF_Chain.Step completionHandlerStep)Registers a completion handler step that executes ONLY when every step in the chain completes successfully. The completion handler does NOT run when the chain terminates in failure (i.e. when a step returns a failed StepResult OR throws and the step is not marked continueOnError).
Failure-path handler is a separate registration. To run a step on failure, register an error handler via .onError(...). The two handlers are mutually exclusive at runtime: exactly one of them fires per chain (success → onComplete, failure → onError), and neither fires if the chain is aborted by the framework kill switch. Subscribers needing "always-runs" cleanup (e.g. release a row lock, close a session) should put the cleanup inside the final step's work() body and use continueOnError = true on the step before it, so the final step runs regardless of upstream failures.
Parameters
| Parameter | Type | Description |
|---|---|---|
completionHandlerStep | IF_Chain.Step | The IF_Chain.Step to execute on successful completion. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('MyChain')
.then(new ProcessStep())
.onComplete(new SendConfirmationStep()) // success-only
.onError(new NotifyAdminStep()) // failure-only
.execute();onError
global UTIL_AsyncChain.ChainBuilder onError(IF_Chain.Step errorHandlerStep)Registers an error handler step that executes when any step fails (unless the failing step has continueOnError set to true).
Parameters
| Parameter | Type | Description |
|---|---|---|
errorHandlerStep | IF_Chain.Step | The IF_Chain.Step to execute on failure. Receives the chain context with the failure details. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('MyChain')
.then(new RiskyStep())
.onError(new NotifyAdminStep())
.execute();then
global UTIL_AsyncChain.ChainBuilder then(IF_Chain.Step step)Appends a step to the end of the chain.
Parameters
| Parameter | Type | Description |
|---|---|---|
step | IF_Chain.Step | The IF_Chain.Step implementation to add. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('MyChain')
.then(new FirstStep())
.then(new SecondStep())
.execute();global UTIL_AsyncChain.ChainBuilder then(IF_Chain.Step step, Boolean continueOnError)Appends a step to the chain with explicit control over error continuation. Use this overload for IF_Chain.Step implementations that cannot extend ChainStep.
Parameters
| Parameter | Type | Description |
|---|---|---|
step | IF_Chain.Step | The IF_Chain.Step implementation to add. |
continueOnError | Boolean | When true, the chain continues past this step's failure. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('MyChain')
.then(new CriticalStep())
.then(new OptionalStep(), true)
.then(new FinalStep())
.execute();withAsyncOptions
global UTIL_AsyncChain.ChainBuilder withAsyncOptions(AsyncOptions options)Sets the AsyncOptions controlling queueable stack depth. When provided, these options override the framework default (maximumQueueableStackDepth = steps.size() + 1). In tests, pass options with an explicit maximumQueueableStackDepth matching the expected chain depth to enable chained Queueable execution within Test.startTest/stopTest.
Parameters
| Parameter | Type | Description |
|---|---|---|
options | AsyncOptions | The AsyncOptions to use for queueable enqueuing. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
AsyncOptions options = new AsyncOptions();
options.maximumQueueableStackDepth = 4;
UTIL_AsyncChain.newChain('MyChain')
.then(new Step1()).then(new Step2()).then(new Step3())
.withAsyncOptions(options)
.execute();withDeduplicationKey
global UTIL_AsyncChain.ChainBuilder withDeduplicationKey(String deduplicationKey)Guards against two overlapping runs of the same logical chain. While a run holds the key, a second execute() with the same key returns the active run's Id instead of starting a duplicate. Any terminal status releases the key in the same update, so a sequential re-run is deliberately allowed; a Stalled run still holds its key until it is recovered or resolved. The key is stored verbatim; the platform's unique text index is case-insensitive, so keys differing only in case collide. Zero-step chains complete immediately and never hold a key. Distinct from ChainContext.idempotencyKey(), which generates replay-safe keys for your own step side effects — this method prevents a second run from starting at all.
Parameters
| Parameter | Type | Description |
|---|---|---|
deduplicationKey | String | Non-blank key, at most 255 characters — e.g. a schedule name or a template like 'nightly-sync-' + recordId. |
Returns UTIL_AsyncChain.ChainBuilder — This builder, for chaining.
Example
String runId = UTIL_AsyncChain.newChain('NightlyAccountSync')
.then(new SyncStep())
.withDeduplicationKey('nightly-account-sync')
.execute();withDelayMinutes
global UTIL_AsyncChain.ChainBuilder withDelayMinutes(Integer minutes)Defers the chain's first step by the given number of minutes. This is best-effort: the platform enqueues the first step with a Queueable delay, so the chain shows as Running with zero completed steps in the Chain Monitor until the delay elapses, and the delay degrades to immediate if the org has disabled Queueable delay. The value is clamped to the platform range of 0 to 10 minutes; a null or zero delay is a no-op. Only the first step is delayed; every later step runs as soon as its predecessor finishes.
Parameters
| Parameter | Type | Description |
|---|---|---|
minutes | Integer | The delay before the first step, in minutes (clamped to 0 to 10). Null is a no-op. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('NightlyRollup')
.then(new AggregateStep())
.withDelayMinutes(5)
.execute();withInitialContext
global UTIL_AsyncChain.ChainBuilder withInitialContext(String key, Object value)Seeds the chain context with an initial key-value pair before execution begins. This is additive — each call adds one key-value pair to the initial context map.
Parameters
| Parameter | Type | Description |
|---|---|---|
key | String | The context key. |
value | Object | The context value. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('MyChain')
.withInitialContext('recordId', record.Id)
.withInitialContext('batchSize', 200)
.then(new ProcessStep())
.execute();withMaxContextSize
global UTIL_AsyncChain.ChainBuilder withMaxContextSize(Integer maximumSize)Sets the maximum serialized context size in characters. Prevents context overflow from storing large object graphs. Default: 32768.
Parameters
| Parameter | Type | Description |
|---|---|---|
maximumSize | Integer | The maximum context size in characters. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('LargeContextChain')
.withMaxContextSize(65536)
.then(new DataHeavyStep())
.execute();withMaxSteps
global UTIL_AsyncChain.ChainBuilder withMaxSteps(Integer maximumSteps)Sets the maximum number of steps the chain is allowed to execute. Prevents runaway chains from consuming unlimited resources. Default: 50.
Parameters
| Parameter | Type | Description |
|---|---|---|
maximumSteps | Integer | The maximum number of steps permitted. |
Returns UTIL_AsyncChain.ChainBuilder — This ChainBuilder for method chaining.
Example
UTIL_AsyncChain.newChain('ShortChain')
.withMaxSteps(10)
.then(new MyStep())
.execute();