Releases: beyond-the-cloud-dev/async-lib
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
Context Mocking for Queueable Jobs
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
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.
Fix chaining job issue
This release introduces:
- Fix for skipping chained jobs from the same context by cloning passed job.
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.
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.