sud
sud

Reputation: 73

Trigger Magento event observer asynchronously

Is there any way to make an event observer asynchronous in Magento? I would like to use this to run a few time consuming scripts in the background after a customer has placed an order, but my understanding is that when an event gets dispatched, the code for the observer gets executed synchronously/immediately.

Upvotes: 6

Views: 2302

Answers (1)

fantasticrice
fantasticrice

Reputation: 1621

One way you could accomplish this, as @user3438533 mentioned, is to schedule a job when your observer fires which can get executed later by cron. It is safe to do this because jobs scheduled out in the future with pending status in cron_schedule will not get purged.

Since you brought up purchasing, let’s use that as an example. You will need to be able to create a simple extension in order to put this into action. A common event used to do things after an order has been placed is sales_order_place_after, so we will use that to trigger the future custom cron job.

etc/config.xml

Step 1. Set up the event observer under config/frontend/events:

<sales_order_place_after>
    <observers>
        <scheduleExampleJob>
            <class>My_Example_Model_Observer</class>
            <method>scheduleExampleJob</method>
        </scheduleExampleJob>
    </observers>
</sales_order_place_after>

Step 2. Set up the cron job handler that will listen for the new custom job created in the observer under config/crontab/jobs:

<my_example_job>
    <!-- @see My_Example_Model_Observer::scheduleExampleJob -->
    <run><model>My_Example_Model_Observer::runExampleJob</model></run>
</my_example_job>

Model/Observer.php

class My_Example_Model_Observer
{
    /**
     * Triggers my_example_job to get scheduled when it gets fired.
     * @param Varien_Event_Observer $observer
     * @return $this
     */
    public function scheduleExampleJob(Varien_Event_Observer $observer)
    {
        // Calculate your needed datestamp to schedule the future job.
        $scheduleAt = Mage::getModel('core/date')->timestamp('Y-m-d H:i:s', strtotime('30 minutes from now'));
        Mage::getModel('cron/schedule')
            ->setJobCode('my_example_job') // Needs to match config/crontab/jobs node
            ->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
            ->setScheduledAt($scheduleAt)
            ->save();
    }

    /**
     * Handler for my_example_job, executed from crontab.
     * @param $schedule
     * @return $this
     */
    public function runExampleJob($schedule)
    {
        // Do your asynchronous work!

        return $this;
    }
}

Upvotes: 7

Related Questions