Spin locks with variable time retry backoffs
I'd just requeue the job if you hit max retries:
try {
LocksServiceImpl.acquire(lock);
} catch(LocksService.MutexException e) {
System.enqueueJob(this);
return;
}
At this point, your job will retry later. There's supposed to be a built-in delay for chained jobs, so this should provide the delay you're looking for.
Although not an answer per se, I wanted to post some performance stats based on a stress test using the spin lock and spin lock fallback strategy as answered by @sfdcfox. This is not a critique of the answer which was good but more of a cautionary tale should one pursue this route. YMMV
Test:
- 50 queueable jobs (
System.enqueueJob(..)
) each launched in one stress testing transaction. - Each job enqueues on the same spin lock - that is, they all compete with each other.
- Spin lock does a
Select for Update
and tries 10 times before abandoning - Each job does the same amount of work: (deserializes 1000 custom Json and then constructs/inserts 1000
Asset
s). That is, the work is "substantive".
Result:
- 4 of the 50 queueables completed quickly and the rest were requeued by the spin lock backoff solution to another queueable. SFDC then reschedules these queueables (delaying up to 1 minute) and they (46) compete with each other again. This repeats itself over time until they all complete
- Total elapsed time to get through 50 initial threads each trying to insert 1000 assets = 26 minutes. Three hundred nine (309) queueable retry jobs (!)
Analysis