This issue threw me for a loop for some time.
Suppose you have a Schedulable
class and when it runs, the behavior of the execute()
method doesn’t match what you expect. It looks like there’s memory of previous execute()
s
Here is a specific example that distills the issue
public class MySchedulable implements Schedulable { Account[] accts = new List<Account>(); public void execute(SchedulableContext sc) { accts.addAll([select id, name from Account where YTD_Total__c < 1000.0]); // do something interesting with this }
You run the job weekly. You observe on week n, where n > 1, that Accounts are being processed that currently don’t have a YTD_Total__c
< 1000. Accounts with YTD_Total__c
> 1000 are being processed (?!?)
Explanation
- When the job is scheduled, the class constructor is called (here, the implicit constructor) and the object variable
accts
is initialized empty. - On week 1, when
execute()
is called, the accounts withYTD_Total__c
< 1000 as of week 1 are added to listaccts
. - On week 2, when
execute()
is called, the accounts withYTD_Total__c
< 1000 as of week 2 are added to listaccts
.
Note that the class constructor is not reinvoked for each execute(). Hence, the accts
list grows and grows.
Solution
Reinitialize all object variables within the execute().
public class MySchedulable implements Schedulable { public void execute(SchedulableContext sc) { Account[] accts = new List<Account>(); accts.addAll([select id, name from Account where YTD_Total__c < 1000.0]); // do something interesting with this }