Prevent Concurrent Scheduled Executions¶
Goal¶
Ensure that only one scheduled execution enters a critical section at a time when a previous run is still active.
What You Will Learn¶
- protect scheduled work with a cache lock
- release a lock reliably with
try/finally - distinguish mutual exclusion from retry-safe business writes
Difficulty and Estimated Time¶
- Difficulty: Advanced
- Estimated time: 20 minutes
Assumed Knowledge¶
You should understand scheduled tasks, automation scripts, exceptions, and idempotency.
Required Reading¶
Prerequisites¶
- permission to import and schedule process definitions
- a clean test domain where a short schedule interval is safe
Example Overview¶
The definition contains one scheduled automation task. Its prework obtains a named lock, performs the protected work, and releases the lock in finally.
Steps¶
Configure the Schedule¶
Create a scheduled task and use a short interval only while testing. Confirm the target environment's time zone.
Protect the Critical Section¶
1 2 3 4 5 6 7 | |
Keep the protected section short. Always release the exact token returned by the lock operation.
Record Correlation and Failure State¶
Create one runId before the critical section and attach it to every durable record, outbound request, and diagnostic message produced by that run. Record coarse states such as Started, Completed, or Failed; do not log secrets or full business payloads. If a later step fails, rethrow the error after recording failure and use the same run ID to decide whether a retry should resume, compensate, or skip already-completed effects.
For a multi-step operation, define the boundary explicitly:
- validate all inputs before the first side effect
- commit related database changes in one transaction where supported
- record a stable idempotency/correlation key before calling an external service
- compensate only effects that can be reversed safely
- surface a failed state for manual recovery when automatic compensation is unsafe
How It Works¶
Executions using the same cache key serialize access to the protected section. The finally block runs when the body succeeds or throws, avoiding a lock that is retained by a normal script failure. The lock does not make database writes idempotent; repeated sequential runs can still create duplicate data.
Verify the Result¶
- Import the definition and enable its test schedule.
- Temporarily make the protected body run longer than the schedule interval.
- Confirm from diagnostics that two executions do not enter the critical section together.
- Force an error and confirm that a later execution can acquire the lock.
Failure and Edge Cases¶
- Use different lock keys and confirm that they do not protect the same operation.
- Confirm that a failed business write can be retried without producing a duplicate.
- Force a failure after the first side effect and confirm that the run ID identifies the partial execution and the retry does not repeat the completed effect.
- Restore the production interval after testing.
Security and Portability Notes¶
- Choose a key unique to the operation; never derive it from untrusted input.
- Do not hold a distributed lock while waiting on user input or a slow external service.
- Add a separate idempotency key or upsert strategy for retryable writes.
- Correlation makes a failure traceable; it does not by itself provide atomicity or authorization.
Download and Try It Yourself¶
Download the scheduled lock definition.
Troubleshooting¶
- Later runs never enter: Confirm that release is in
finallyand uses the matching key and token. - Duplicates still occur: A lock prevents overlap, not repeated sequential writes; add idempotency.