Context
When several services in one transaction each want to enqueue async work, they either enqueue separately (scattered enqueues) or thread a shared builder through every call. This coordination is already supported — QueueableManager is a transaction-scoped singleton, so .chain() calls from different services accumulate into one chain, flushed by a single final .enqueue().
The mechanism exists but is undocumented and non-obvious. This is a docs task, not a new API.
Existing pattern
// service A
Async.queueable(new SendWelcomeJob(contacts)).chain();
// service B
Async.queueable(new ReviewContactJob(contactIds)).chain();
// once, at the orchestration boundary
Async.queueable(new FinalJob()).enqueue(); // flushes all as one chain
Verified by AsyncTest.shouldReturnFirstEnqueuedJobIdAfterMultipleChainCallsBeforeEnqueue (3 accumulated jobs -> single enqueue -> one chain).
Scope / caveat to document
- Buffer is transaction-scoped: the singleton lives only within the current synchronous transaction. The pattern coordinates work inside one transaction, not across transactions.
- Overflow (>50 queueables) is already handled automatically.
Acceptance criteria
- Docs page/section showing the multi-service
chain() + final enqueue() pattern.
- Explicit note on transaction-scoped buffering.
Out of scope (previous proposal)
- No new
collect() / dispatch() API — it would duplicate .chain() / .enqueue() semantics and add a permanent global contract.
- Optional dedupe-by-key could be a separate future issue if a concrete need appears.
Context
When several services in one transaction each want to enqueue async work, they either enqueue separately (scattered enqueues) or thread a shared builder through every call. This coordination is already supported —
QueueableManageris a transaction-scoped singleton, so.chain()calls from different services accumulate into one chain, flushed by a single final.enqueue().The mechanism exists but is undocumented and non-obvious. This is a docs task, not a new API.
Existing pattern
Verified by
AsyncTest.shouldReturnFirstEnqueuedJobIdAfterMultipleChainCallsBeforeEnqueue(3 accumulated jobs -> single enqueue -> one chain).Scope / caveat to document
Acceptance criteria
chain()+ finalenqueue()pattern.Out of scope (previous proposal)
collect()/dispatch()API — it would duplicate.chain()/.enqueue()semantics and add a permanentglobalcontract.