-
Notifications
You must be signed in to change notification settings - Fork 5
Releases: beyond-the-cloud-dev/async-lib
v2.6.0
What's Changed
This release adds opt-in retry with backoff for failed Queueable jobs, dependency gating between chained jobs, imperative chain control, and a much richer AsyncResult__c audit trail. (#23, #34)
🚀 New Features
-
Retry & backoff for Queueable jobs. Opt in per job with
retry(n)(capped at 10), choose abackoff(...)strategy, and narrow which failures retry withretryOn(...). Defaults can also come fromQueueableJobSetting__mdt(MaxRetries,BackoffStrategy,BackoffBaseMinutes,RetryableExceptions). (#23, #34)Async.queueable(new MyJob()) .retry(3) .backoff(Backoff.exponential(2)) .retryOn(CalloutException.class) .enqueue();
-
Backoff strategies. New top-level
Backoffclass:Backoff.fixed(min),Backoff.exponential(base),Backoff.exponentialWithJitter(base)(all capped at the 10-minute platform limit). -
Per-job retry hooks. Override
isRetryable(Exception)to veto a retry, andresetForRetry()to reset mutable state before the job runs again. -
Dependency gating. Gate a job on the outcome of an earlier one:
dependsOn(Async.after(result).succeeded()),Async.afterPrevious().failed(),Async.after(customJobId).finished(). A job whose dependency doesn't match is skipped, and the skip cascades to its dependents — handy for compensation jobs. -
Imperative chain control. From a finalizer, call
Async.stopChain()to halt the rest of the chain, orAsync.skipJob(customJobId)to skip a specific job. -
Richer result tracking. An
AsyncResult__crow per job (ran or skipped) now records status, chain id, class name, exception type/message, retry attempts and history, skip reason, required/actual outcome, and a self-lookup to the dependency's result. The newAsyncResultAccesspermission set grants read access to these fields.
✨ Improvements
rollbackOnJobExecuteFailnow actually rolls back the failed job's DML and lets the chain continue. Previously, set on its own, it was effectively a no-op and the chain halted. See upgrade notes.- API version raised to 66.0 across all classes and the project source API.
📚 Documentation
website/api/queueable.mddocumentsretry,backoff,retryOn,dependsOn, the dependency builders, chain control, and theAsyncResult__cfields.website/getting-started.mdcovers the retry and dependency entry points.
⚠️ Upgrade notes from v2.5.0
rollbackOnJobExecuteFailbehavior change. If you set onlyrollbackOnJobExecuteFailand relied on the chain halting, it now rolls back and continues. To stop on failure, do not set the continue/rollback flags.
Install
https://login.salesforce.com/packaging/installPackage.apexp?p0=04tP6000003Hg17IAC
Assets 2
v2.5.0
What's Changed
This release adds incremental queueable chain composition, fixes a set of chain-result and inner-class deep-clone bugs, and is the first time Async Lib is distributed as a btcdev-namespaced unlocked package.
🚀 New Features
-
Async.queueable()(no-arg) builder. Compose a queueable chain when the set of jobs depends on runtime conditions. Callingenqueue()on a builder with zero jobs is a safe no-op. (#28)QueueableBuilder builder = Async.queueable(); if (needsJob1) { builder.chain(new Job1()); } if (needsJob2) { builder.chain(new Job2()); } if (needsJob3) { builder.chain(new Job3()); } builder.enqueue();
-
First packaged release. Async Lib is now distributed as a
btcdev-namespaced unlocked package. See Installation.
✨ Improvements
cloneForDeepCopyoverride signature refined — see Deep Clone in Packages.
🐛 Bug Fixes
Result.salesforceJobIdnow reports the actually-enqueued first-chain job id (previously the last builder-supplied job, which was never enqueued).SchedulableManager.schedule()+skipWhenAlreadyScheduled()returns an emptyList<Async.Result>on duplicate (previouslynull).QueueableJob.cloneForDeepCopy()resolves inner job classes correctly (previously NPE'd because outer-class names were mistaken for namespaces).- Documented
cloneForDeepCopyoverride pattern for namespaced consumers, fixing the JSONException seen when calling.deepClone()from a package install.
📚 Documentation
- NEW Deep Clone in Packages — when and how to override
cloneForDeepCopyfor namespaced consumers. - Installation page covers the unlocked-package path and the
btcdevnamespace prefix callout. Async.Resulttable documents theResult.jobfield and the correctedsalesforceJobIdsemantics.- Documentation · Installation
⚠️ Upgrade notes from v2.4.0
Result.salesforceJobIdis no longernullfor chained-then-enqueued flows. If your code branched onresult.salesforceJobId == nullto detect that, switch to inspectingresult.queueableChainState.jobs.SchedulableBuilder.schedule()withskipWhenAlreadyScheduled()returns an empty list, notnull. Replaceresult == nullguards withresult.isEmpty().- If you previously source-deployed the library and switch to the package install, replace
Async.*/QueueableJob/ etc. withbtcdev.Async.*/btcdev.QueueableJob.
Install
https://login.salesforce.com/packaging/installPackage.apexp?p0=04tP60000038pYHIAY
Assets 2
Context Mocking for Queueable Jobs
13fdb95 New Features
Context Mocking with AsyncMock
Test your async jobs with full control over QueueableContext and FinalizerContext. No more limitations when testing error handling paths or finalizer behavior.
@IsTest static void shouldHandleJobFailure() { AsyncMock.whenFinalizer('error-handler') .thenThrow(new DmlException('Parent job failed')); Test.startTest(); Async.queueable(new MyJob()).mockId('error-handler').enqueue(); Test.stopTest(); }
Key capabilities:
whenQueueable()/whenFinalizer()- Setup mocks by mockIdwhenQueueableDefault()/whenFinalizerDefault()- Default fallback mocksthenReturn()/thenThrow()- Configure success or exception responses- Queue-based mock consumption for testing multiple invocations
- Direct unit testing without
Test.startTest()/stopTest()
mockId Builder Method
New mockId(String) method on QueueableBuilder to identify jobs for mocking.
Improvements
- Renamed
QueueableChainBatchtoQueueableChainSchedulable - Added namespace checks when adding
QueueableJobSettingmetadata - Improved API documentation with structured tables for result properties
Documentation
AsyncMock API - Complete reference
Testing Async Jobs - Patterns and best practices
Assets 2
Soft and deep job cloning.
This release introduces:
- Soft and deep Clone of the Job - Enhanced QueueableBuilder with .deepClone() method for complete object isolation when working with complex object relationships. Learn more here.
Assets 2
Fix chaining job issue
This release introduces:
- Fix for skipping chained jobs from the same context by cloning passed job.
Assets 2
On demand Queueable Job chaining and result enhancements
This release introduces:
- New
QueueableBuilder.chain()methods -chain()andchain(QueueableJob job), which allowing you to manually add jobs to an existing chain. You can now decide when to chain jobs — not just rely on the automatic chaining mechanism triggered when platform limits are hit. - Enhanced Results from QueueableBuilder
enqueue(),chain(), andchain(QueueableJob job)now return the Queueable Chain State. Additionally,enqueue()indicates whether the action created a new chain, continued an existing chain, or scheduled an initial job.
→ Learn more here. - Access Queueable Chain State On-Demand
UseAsync.getCurrentQueueableChainState()to inspect the current chain — including all chained jobs, next job IDs, and chain type.
Assets 2
v2.0.0
This release introduces:
- Change of initial job start, from 'Database.executeBatch()' to scheduling it in 1 minute in the future, due to issues related when using Queueable Jobs in Batches. Full explanation can be found here.
- New ScheduleableBuilder method
skipWhenAlreadyScheduled()that allows scheduling only if the job with the same name is not already scheduled. More info here. - Minor enhancements.
Assets 2
v1.0.0
documentation