Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

All other Modules /

Discuss all other Modules here.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

My 'Queued Job' job isn't stable... Unclear examples of what is best practise/should actually be done.


Go to End


1224 Views

Avatar
Peavers

Community Member, 20 Posts

27 June 2015 at 9:51am

Edited: 27/06/2015 10:01am

I'm having a bit of trouble getting a job to run reliably without getting stuck as "Paused" or "Initializing". It does however run correctly sometimes...

I found the examples (https://github.com/silverstripe-australia/silverstripe-queuedjobs/tree/master/code/jobs) to be a little confusing as they don't follow the same process in terms of where things are set. For example the DeleteObject example sets the currentStep to 0 in the constructor where the other examples don't...

My job isn't complicated but would love some help to clean it up if possible.

<?php

/**
 * Process all TwitterObjects that are ready to be built. All I'm doing is creating a short URL from a API services
 * and writing the value into the field in the each TwitterObject. On completing the job, if their are TwitterObjects
 * now ready to send to twitter, create that job. I reschedule this job to run every 15 minutes or so.
 *
 * Class BuildTwitterMessageJob
 *
 * @package: twitter-notify
 */
class BuildTwitterMessageJob extends AbstractQueuedJob implements QueuedJob
{
    private $google;
    private $twitterObject;

    /**
     * TwitterObject is a standard Silverstripe Object
     */
    public function __construct()
    {
        $this->twitterObject = TwitterObject::getToBuild();
        $this->currentStep = 0;
        $this->totalSteps = count($this->twitterObject);

        // Empty job, no point in going  further
        if ($this->totalSteps == 0) {
            $this->jobComplete();
        }
    }

    public function getJobType()
    {
        return QueuedJob::QUEUED;
    }

    public function getTitle()
    {
        return "Build tweets";
    }

    /**
     * Only allow one job of this type
     * 
     * @return string
     */
    public function getSignature()
    {
        return md5(get_class($this));
    }

    /**
     * Create a google object which handles the URL shortening
     */
    public function setup()
    {
        parent::setup();

        $baseUrl = SiteConfig::current_site_config()->GoogleApiBaseUrl;
        $api = SiteConfig::current_site_config()->GoogleShortURLServerAPI;
        $this->google = new GoogleShortUrl($baseUrl, $api);
    }

    /**
     * Merge the short URL with the body of the message on each TwitterObject. Update both the state of the object
     * and the message as appropriate. 
     */
    public function process()
    {
        $remainingChildren = $this->twitterObject;

        if (!count($remainingChildren)) {
            $this->jobComplete();
        }
        
        $tweet = array_shift($remainingChildren);

        // +++ Actual process
        $tweet->BuildStatus = TwitterConst::FLAG_PROCESSING;
        $tweet->write();

        // Update body of the message with short URL
        $tweet->Link = $this->google->getShortUrl($tweet->Link);
        $tweet->Message = $tweet->Message . " " . $tweet->Link;

        // Flag as complete
        $tweet->BuildStatus = TwitterConst::FLAG_DONE;
        $tweet->write();

        // Tidy up
        $this->twitterObject = $remainingChildren;
        $this->currentStep++;

        if (!count($remainingChildren)) {
            $this->jobComplete();
        }
    }

    /**
     * @return bool
     */
    public function jobComplete()
    {

        $this->addMessage('Complete');
        $this->createSendJob();
        $this->reschedule();
        $this->isComplete = true;

        return;
    }

    /**
     * Create a new job to send the built tweets.
     */
    private function createSendJob()
    {
        if (TwitterObject::getToSend()) {
            singleton('QueuedJobService')->queueJob(new SendTwitterMessageJob(TwitterObject::getToSend(), time()));
        }
    }

    /**
     * Rerun this task every minute from the time it is created (Google can handle a bit of spam)
     */
    private function reschedule()
    {
        $run_rate = floor(SiteConfig::current_site_config()->TwitterSendRate * 60);

        singleton('QueuedJobService')->queueJob(new BuildTwitterMessageJob(TwitterObject::getToBuild()), date('Y-m-d H:i:s', strtotime(date('Y-m-d H:i:s', time())) + $run_rate));
    }

}