Associate Actions With Asynchronous Apex Jobs Using Transaction Finalizers (Beta) – Spring 21

Let’s explore Finalizers in Queueable Apex by considering a scenario.


Let me present a scenario and elucidate how we handle such situations prior to Spring 21.

In Queueable Apex, when attempting a callout to an external platform, an interruption in the network might result in a callout failure. How do we ensure that the callout is retried and re-enqueued in the event of a failure?

Previously, the approach involved obtaining the JobId after the callout, checking the Job’s status, and manually re-enqueuing it if it had failed.

Salesforce has introduced Finalizers, streamlining the process of re-enqueuing failed Queueable jobs. Let’s delve into an illustrative example!

public class AsyncJobClass implements Queueable {
    
    public void execute(QueueableContext ctx) {
        
        UdpateAWSFinalizer f = new UdpateAWSFinalizer();
        System.attachFinalizer(f);
        
        //Business logic
    }
    
}
public class UdpateAWSFinalizer implements Finalizer {

   
    public void execute(FinalizerContext ctx) {
		
        //getRequestId()
        //getAsyncApexJobId()
        //getResult()
        //getException()
        
        String reqId = ctx.getRequestId();
        String jobId = Id.valueOf(ctx.getAsyncApexJobId());
        
        if (ctx.getResult() == ParentJobResult.SUCCESS) {
            System.debug('Parent Queueable (job id: ' + jobId + '): completed successfully!');

        } else { // Queueable failed
            //provide a counter & it should not exceed 5 times
            //re-enqueue the job
        }
    }

}

In the example, here’s our objective:

We have a Queueable job named SampleAsyncJob, encompassing certain business logic, such as making a callout.

To complement this, I crafted another class that implements the Finalizer interface.

The Finalizer interface has an overridden execute() method, which takes a single parameter of type FinalizerContext.

FinalizerContext, a class providing access to four methods: getRequestId(), getAsyncApexJobId(), getResult(), and getException().

In the UpdateAWSFinalizer class, our aim is to assess the status of the parent job, determining whether it was successful or encountered a failure.

if (ctx.getResult() == ParentJobResult.SUCCESS) {
        
} else { // Queueable failed
    //provide a counter
}    


Should the parent job’s status indicate a failure, it becomes necessary to re-enqueue the business logic.

However, there is a limitation in place; we are constrained from re-enqueuing the job more than 5 times.