Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rsoesemann/apex-chainable
Chain Asynchronous Apex in a readable and flexible way without hardcoding the successor.
https://github.com/rsoesemann/apex-chainable
apex-batches asynchronous-programming batch batch-chains clean-code fluent-api framework queueable salesforce-apex schedulable successor-batch
Last synced: 24 days ago
JSON representation
Chain Asynchronous Apex in a readable and flexible way without hardcoding the successor.
- Host: GitHub
- URL: https://github.com/rsoesemann/apex-chainable
- Owner: rsoesemann
- License: mit
- Created: 2019-01-22T08:45:02.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2024-05-16T20:28:50.000Z (6 months ago)
- Last Synced: 2024-05-20T23:34:50.551Z (6 months ago)
- Topics: apex-batches, asynchronous-programming, batch, batch-chains, clean-code, fluent-api, framework, queueable, salesforce-apex, schedulable, successor-batch
- Language: Apex
- Homepage:
- Size: 27.3 KB
- Stars: 43
- Watchers: 6
- Forks: 10
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Apex Chainable [![Codacy Badge](https://app.codacy.com/project/badge/Grade/7024ec2e01c24c03a323e565e029a5a6)](https://www.codacy.com/gh/rsoesemann/apex-chainable/dashboard?utm_source=github.com&utm_medium=referral&utm_content=rsoesemann/apex-chainable&utm_campaign=Badge_Grade)
Apex Batches can be chained by calling the successor batch from the `finish()` method of the previous batch.
But such hardcoding makes this model inflexible. It's hard to build the chain from outside, neighter from a central class
nor on runtime dependant on business logic.The same applies when the `execute()` method of `Schedulable` or `Queueable` classes call other classes.
## With `Chainable`
The `Chainable` wrapper class of this repository overcomes those drawbacks.
- No need to hardcode successor batch in `finish()` method
- Created batch chains of arbitrary length without changing existing Batch classes
- Support `Batchable`, `Queueable` and `Schedulable` classes as chain members
- Allows sharing and passing of variables between chain members```java
new FirstBatch().setShared('result', new Money(0))
.then(AnotherBatch())
.then(QueueableJob())
.then(ScheduledJob())
...
.execute();
```## Without `Chainable`
```java
class FirstBatch implements Batchable {
Iterator start(BatchableContext ctx) { ... }void execute(BatchableContext ctx, List scope) { ... }
void finish(BatchableContext ctx) {
Database.enqueueBatch(new SecondBatch());
}
}
``````java
class AnotherBatch implements Batchable {
Iterator start(BatchableContext ctx) { ... }void execute(BatchableContext ctx, List scope) { ... }
void finish(BatchableContext ctx) {
System.schedule('name', cron, new ScheduledJob());
}
}
```## Deferring
When all the "links" in the chain cannot be completely identified beforehand in order to assemble them in a single chain and trigger its execution, the chain execution can be *deferred* until the end of the transaction. All chainable processes that have been *deferred* will be automatically chained together in a **single** chain and executed sequentually.
```java
// automation 1
new FirstBatch()
.then(AnotherBatch())
.setShared('result', new Money(0)) // shared variables will be available across other following deferred chainables
.executeDeferred();// automation 2
new QueueableJob()
.then(ScheduledJob())
...
.executeDeferred();// the framework would internally build the chain in a separate transaction with a definition like this
new FirstBatch()
.then(AnotherBatch())
.setShared('result', new Money(0))
.then(QueueableJob())
.then(ScheduledJob())
.execute();```
### Considerations
In order to leverage the deferring of the Chainable instances there are some nuances compared to its direct execution.
* Override the `getDeferArgs` and `setDeferredArgs` if the class receives external input before its execution via constructor parameters or setters to serialize and deserialize them (See the `SampleDeferArgQueueable`).
* Must have a no-arg constructor (if no explicit constructor exists, the default implicit one will be used)
* Must not be an inner class (due to difficulty on dynamic name inferring)