I have a scheduled job, which updates Setup and non-Setup objects. The scheduled job performs immediate changes on the non-Setup objects, and (in same run) executes a method using the @future annotation, which also reschedules the job for its next run time. This is done to prevent MIXED_DML errors and ensure the processing has fully completed (avoiding overlaps or premature abortion of current job if it requires more than 6 mins).

Here's my issue:

When the job attempts to cancel itself then reschedule for 6 minutes after it successfully completed, it encounters "Table Locked Error". As a result the job basically "Cancels" and its schedule is then set to 24 hours later. 95% of the time, the job runs as expected and doesn't encouner such error.

This is a large problem since we need this to process hundreds of updates per day.

What steps should I take, or best practices should I adhere to in order to avoid this issue? my first thought is to build a "helper" scheduled class to monitor scheduled jobs, but I feel like there must be a simpler solution.

Error Message 1:

First error: Job object is locked and currently processing.

Error Message 2:

Message could not be processed and ended up in dead message queue

Scheduled Class:

global class Team_Scheduled_QueueManager implements Schedulable{

    global void execute(SchedulableContext SC){

        //check for teams without manager to ensure "next direct manager" is accurate

        //clear out old success+cancel records...  no need to store extra data...

        //merge multiple update requests and remove redundancies...

        //attempt to update user record...
        //this class schedules the next run and is an @future method to
        //avoid mixed DML statement errors and avoid record contention...



Class to rescheduled scheduled class (executed in @future context from tryUserUpdate() method):

public static void scheduleNextJobRun() {

        Id oldJobId =  [SELECT Id, CronJobDetail.Id, CronJobDetail.Name, CronJobDetail.JobType 
             FROM CronTrigger where CronJobDetail.Name = 'Scheduled Job: Enqueued User Update' LIMIT 1].Id;

        Datetime myDateTime = Datetime.now();
        myDateTime = myDateTime.addMinutes(6);

        String hour = String.valueOf(myDateTime.hour());
        String min = String.valueOf(myDateTime.minute()); 
        String ss = String.valueOf(myDateTime.second());

        //parse to cron expression
        String nextFireTime = ss + ' ' + min + ' ' + hour + ' * * ?';

        system.debug('nextFireTime: '+ nextFireTime);

        Team_Scheduled_QueueManager s = new Team_Scheduled_QueueManager(); 

        //abort originating job...

        //create new job...
        System.schedule('Scheduled Job: Enqueued User Update', nextFireTime, s);  


Can't you just let it run in specific intervals and let the tryUserUpdate fire separately in future context? Why does tryUserUpdate need to reschedule the job? Maybe you can pass to this method a list of ids that will help it process a specific set of records so that different runs don't try to access the same records.

Seems that trying to abort and reschedule the same job is what is causing you problems.

  • I need it to run every 6 mins ( at least) and I dont want to have 10 scheduled jobs set up to run at specified intervals. My aim is to minimize our usage of # scheduled jobs since SF limits it to 100 per org. Also, tryUserUpdate already runs in future context, and it must reschedule the job AFTER it completes. If the job takes more than 6 mins. to comlete, then the scheduling will overlap istelf and cause contention on the current job runnin in the background. – James Oct 2 '15 at 15:10
  • And it is this contention that is causing the errors you have mentioned. So how about looking at a different approach like Queueable Apex? developer.salesforce.com/docs/atlas.en-us.apexcode.meta/… – AslamK Oct 2 '15 at 15:21
  • Thanks, @AslamK! I want to note the contention is not on the records being updated, instead the ChronJob itself. The rescheduling method is only run after all other processes complete, so it's as if I were to manually enter a new job. Would you happen to know a bit more of the mechanics at play here, since everything is running in series? I'll research the Quable Apex, but I'd like to really understand what's happening here since the documentatino is sparse on the Scheduled Apex's workings. – James Oct 2 '15 at 19:38

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.