6

It is more of a conceptual question. I have to write a batch process to do some operation on Leads. It is very important that i first take the oldest lead (created date should be oldest)

Let's assume there are 1000 records (there are actually over 300,000 records in my org).

In Query locator if i retrieve them and sort by their created date, then keep a batch size of 200 ... will the execute statement's first chunk be oldest 200 records? If not, how do i address my problem here (to operate on leads from oldest to newest)?

3

tl;dr: yes.

There's a few peculiarities when sorting by Created Date, partly due to the fact that the system assigns Id values and time stamps in a way that may cause them to be out of order when queried back, and because the audit fields are truncated to the nearest second. However, if you want to ignore those idiosyncrasies and just go with a "good enough" answer, you might consider the following query:

return Database.getQueryLocator([SELECT Id FROM Lead ORDER BY CreatedDate, Id]);

While this isn't perfect, it does get leads in same order every time, so it's at least reproducible, but there's no guarantee that the records were literally created in that order (e.g. because of creatable audit field permissions, database race conditions/locks, etc).

The "scope" of Batchable's execute method will return the records in the same order in which they appear in the query results. In that sense, if the query above produces the results you expect, then the scope of each execute call will honor that same order. In other words, execute's scope will contain records from oldest to newest as defined by the query.

4
  • Quick question, if records are added to the DB while the batch is in progress will they be picked up by the batch? Say in this case the newest records are last, batch is started and not on the last chunk, user inserts a record that meets criteria, will the batch pick it up on this run even though the query locator as already been created? IIRC it will but thought I would ask
    – Eric
    Jan 2 '17 at 5:38
  • 1
    @Eric No, records not created before the cursor is created will be missed, as a matter of atomicity. In fact, a record may even be deleted before its turn in the batch as well. No assumptions should be made about the validity of the records when execute starts, which is why I usually re-query the records before I use them.
    – sfdcfox
    Jan 2 '17 at 5:42
  • @sfdcfox help me understand how you are certain that process order (execute) will be based on query sort order? The documentation says "Batches of records tend to execute in the order in which they’re received from the start method. However, the order in which batches of records execute depends on various factors. The order of execution isn’t guaranteed." developer.salesforce.com/docs/atlas.en-us.apexcode.meta/…
    – krigi
    Jul 12 '18 at 23:47
  • @DasUberDanger Oh. I'd actually never knew that before. I've always seen them occur in order (at least, as far as I've paid attention). That being the case, I still think that sorting by Id is likely the best way to get ordered results most of the time. Any algorithm that explicitly depends on the order of the records, though, might be in trouble if it happens to not honor the order. At that point, there's really not much left that can be done, except perhaps use Queueable instead.
    – sfdcfox
    Jul 13 '18 at 0:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.