Reputation: 73
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
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.
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>
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