XF 2.1 Need help debugging custom cron job


I have been working on porting an old VB4 forum into XenForo 2.1 and one of the things the owner called for is their custom newsletter system to be ported over. It was basically a single php file running on unix cron that did a hacky read of the VB4 database of users, grabbed their email, and used mail() to shoot off an email every 2.5 seconds until it was finished. The script was crude and I wanted it to be able to operate within the XF ecosystem anyway so that I didn't have to reinvent the wheel to grab recent post information, user info, send email via SMTP etc from XF.

With that in mind I decided to write an addon script extending \XF\Job\AbstractRebuildJob since it appears to have batch processing of user ids already figured out. I have a static cron() function within the addon script that I use for the XF Cron entry in the Admin CP. Once the cron is called the function initiates the job using:

public static function cron()
    $objInst = new Newsletter(\XF::app(), null);

The job starts chugging along just fine for about 1-2 minutes and then stops at the same user id (318) every time (I have it shooting info to the system error log so that I can track progress during debugging). I see that AbstractRebuildJob runs in batches of 100 users at a time by default, so it seems the batch system is working as expected.

Looking at the specific user that it gets caught up on doesn't reveal anything out of the ordinary and they should be processed just fine as the rest of the users are, so that leads me to believe this might be a timeout issue? Is there a max execution time for crons or XF jobs I should be taking into consideration? Am I using the wrong system for this type of job entirely?


Edit: Increasing $config['jobMaxRunTime'] had no effect on where the processing stopped.
Last edited:
So after adding a counter index to the batch script I see that it stops processing at exactly 100 entries, which is the default max size of a batch. So I guess that would point to an issue with the AbstractRebuildJob::calculateOptimalBatch() or AbstractJob::resume()?
For anyone wondering the answer, in order for your job class to actually run as a job you have to enqueue it. What I was doing was manually calling run() within the job class, which only runs the first batch and not the actual job - this is wrong. There are many different variations of enqueue functions for different situations but the one I ended up going with was


After queuing up the job it ran the batches until no more users were left as expected.
Top Bottom