1

I have a trigger that does some verification steps running before insert and before update. Often in our organization, we use bulk file loading to import users quickly, so I tested this code out to see if it would work with an import of 1000 users. I've changed the variable and class names but here's the idea:

if (contactsToProcess.size() > 0) {
    System.scheduleBatch(new VerifyContactsBatch(contactsToProcess), 
        'Batch Verification Job',10, MAX_SIZE);
} // schedules a batchjob to run in ten minutes

However, when importing many contacts at once, I found that the trigger fires in chunks - so a batch job would be scheduled with 200 users, and then it would try to schedule another 200 but fail since the jobs shared names. I came up with this workaround:

if (contactsToProcess.size() > 0) {
    DateTime runTime = DateTime.now().addMinutes(10);
    System.scheduleBatch(new VerifyContactsBatch(contactsToProcess), 
        'Batch Verification Job - ' + runTime.format('M/d h:m:s:S a'),10, MAX_SIZE);
} // schedules a batchjob to run in ten minutes

Now, this is clever and all, but it does look a little sloppy since importing 1000 users would schedule 5 batch jobs that are doing the same thing. Is there a way that I can take an existing batch job and add more users to it easily?

8
  • I am a bit puzzled. A batch job would tackle all the users, not just the 200 as I understand it. It would do this in batches of 200.
    – abhi
    Jun 30 '17 at 13:48
  • Why not processes those 200 records, without using Batch. A trigger is already sort-of batching those 10.000 records. Or if the logic is taking to long, I would consider firing a Future method..
    – Wim
    Jun 30 '17 at 13:59
  • @abhi: It should do them all at once, but the trigger doesn't fire with all 1000 users at once. It fires 5 times with 200 users each. Jun 30 '17 at 14:00
  • @Sfdcfox, There's other batch jobs that the organization has that run immediately. I have mine wait ten minutes so that there's no issue with locking each other out. Jun 30 '17 at 14:01
  • 1
    By the way, shameless plug: vote for this idea. It's a perfect feature for your use case.
    – sfdcfox
    Jun 30 '17 at 14:05
2

You can't modify the batch object once System.scheduleBatch is called; it is serialized at that point in time and cannot be modified later. What you'd probably want to do is just have a logger object that tracks records that need to be queried, and set up 6 scheduled jobs that run 10 minutes apart (hourly) that check for logger objects at least 10 minutes old and processes them. Something like this:

public class VerifyContactScheduler implements Schedulable {
  public void execute(SchedulableContext context) {
    DateTime TenMinutesAgo = DateTime.now().addMinutes(-10);
    Contact_Log__c[] logs = [SELECT Contact__c FROM Contact_Log__c WHERE CreatedDate <= :TenMinutesAgo];
    // process logs;
    delete logs;
  }
}

Which would be scheduled as such:

System.schedule('VerifyContacts :00', '0 0 * * * ?', new VerifyContactsScheduler());
System.schedule('VerifyContacts :10', '0 10 * * * ?', new VerifyContactsScheduler());
System.schedule('VerifyContacts :20', '0 20 * * * ?', new VerifyContactsScheduler());
System.schedule('VerifyContacts :30', '0 30 * * * ?', new VerifyContactsScheduler());
System.schedule('VerifyContacts :40', '0 40 * * * ?', new VerifyContactsScheduler());
System.schedule('VerifyContacts :50', '0 50 * * * ?', new VerifyContactsScheduler());

This would let your scheduler run every ten minutes and catch all records at at least 10 minutes since their last modification. Then you can simplify your trigger to just storing Contact_Log__c records.

1
  • I love the smell of a great answer in the morning - thank you! Jun 30 '17 at 15:01

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.