1

I have the below hypothetical and simplified code that updates accounts 10 at a time. The process will query for 10 account records during each queueable job. After the queueable job completes, the Finalizer execute method is called and will enqueue an additional job if there are still records remaining, therefore chaining queueable jobs until no more accounts need to be updated.

I am hoping to get thoughts around this use of the [System.Finalizer interface][1] and the principles behind Finalizer. Not necessarily in need of a coding solution or enhancements.

Is this a valid way to chain queueable jobs? Is chaining queueable jobs a 'best practice' use case for System.Finalizer interface?

public with sharing class ReparentAccts implements Queueable, Finalizer {
List<Account> accts = new List<Account>();
List<Account> acctsToUpdate = new List<Account>();

public void execute(QueueableContext qc){
    System.attachFinalizer(this);
    getAcctsToUpdate();
    if(accts.size() == 0){ return; }
    updateAccts(); //performs DML
}

public void getAcctsToUpdate(){
    accts = [
        SELECT Id
        FROM Account
        WHERE
            Update_Account__c = true
        LIMIT 10
    ];
}

public void updateAccts(){
    for (Account acct : accts) {
            acct.Update_Account__c = false;
            acctsToUpdate.add(acctToClone);
        }
    update acctsToUpdate;
}

public void execute(FinalizerContext fc){
    if(!Test.isRunningTest() && this.accts.size() > 0){
        System.enqueueJob(new ReparentAccts());
    }
}
}

2 Answers 2

2

I asked a related question a year ago. Using Finalizers to Work Around Too many queueable jobs added to the queue: 2?

Finalizer was not designed for this, but can be used to chain 2 queueable job from 1 queueable job. Overcoming the limit of Queueable job which can be fired from a Queueable class.

In the above case a batch would be certainly a better approach, as you can query 50 million records at once, and then execute in Child sub batches.

Scenario where chaining can be used in Finalize :

As execute of a Queueable and finalize method of the queueable works in a separate transactions, perfect use case is if you want to update Account and send the information to the external system, you can then use execute to do DML and finalize to make the callout and then again chain the batch in finalize.

But be very careful for calling queueable again from finalizer, as it may enter into infinite loop and may exhaust Async limits.

2

You can do this, nothing's stopping you, but that wasn't the design goal of the Finalizer interface. It's meant as a way for a Queueable to recover from fatal exceptions, perhaps by examining the state of the process or attempting to retry due to transient errors. If you just want to process 10 records at a time, consider a normal Database.Batchable class, which would be more efficient. Or, you can directly chain one Queueable to another (but only 1). You'd only want to use Finalizer if you ran into a scenario where it wasn't possible to work around the problem, such as trying to chain a Queueable while also trying to do a callout with a Queueable.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .