Add Scheduled Task
Overview
Quite often one might want to run any type of code on a regular basis, e.g. to clean up very old entries every once in a while, automatically. Usually known as "Cronjobs", Shopware 6 supports a ScheduledTask
for this.
Prerequisites
This guide is built upon our plugin base guide, but that one is not mandatory. Knowing how the services.xml
file in a plugin works is also helpful, which will be taught in our guides about Dependency Injection and Creating a service. It is shortly explained here as well though, so no worries!
INFO
Refer to this video on Adding scheduled tasks. Also available on our free online training "Shopware 6 Backend Development".
Registering scheduled task in the DI container
A ScheduledTask
and its respective ScheduledTaskHandler
are registered in a plugin's services.xml
. For it to be found by Shopware 6 automatically, you need to place the services.xml
file in a Resources/config/
directory, relative to the location of your plugin's base class. The path could look like this: <plugin root>/src/Resources/config/services.xml
.
Here's an example services.xml
containing a new ScheduledTask
as well as a new ScheduledTaskHandler
:
// <plugin root>/src/Resources/config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="Swag\BasicExample\Service\ScheduledTask\ExampleTask">
<tag name="shopware.scheduled.task" />
</service>
<service id="Swag\BasicExample\Service\ScheduledTask\ExampleTaskHandler">
<argument type="service" id="scheduled_task.repository" />
<tag name="messenger.message_handler" />
</service>
</services>
</container>
Note the tags required for both the task and its respective handler, shopware.scheduled.task
and messenger.message_handler
. Your custom task will now be saved into the database once your plugin is activated.
ScheduledTask and its handler
As you might have noticed, the services.xml
file tries to find both the task itself as well as the new task handler in a directory called Service/ScheduledTask
. This naming is up to you, Shopware 6 decided to use this name though.
Here's the an example ScheduledTask
:
// <plugin root>/src/Service/ScheduledTask/ExampleTask.php
<?php declare(strict_types=1);
namespace Swag\BasicExample\Service\ScheduledTask;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTask;
class ExampleTask extends ScheduledTask
{
public static function getTaskName(): string
{
return 'swag.example_task';
}
public static function getDefaultInterval(): int
{
return 300; // 5 minutes
}
}
Your ExampleTask
class has to extend from the Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTask
class, which will force you to implement two methods:
getTaskName
: The technical name of your task. Make sure to add a vendor prefix to your custom task, to prevent collisions with other plugin's scheduled tasks. In this example this isswag
.getDefaultInterval
: The interval in seconds at which your scheduled task should be executed.
And that's it for the ExampleTask
class.
Following will be the respective task handler:
// <plugin root>/src/Service/ScheduledTask/ExampleTaskHandler.php
<?php declare(strict_types=1);
namespace Swag\BasicExample\Service\ScheduledTask;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler(handles: ExampleTask::class)]
class ExampleTaskHandler extends ScheduledTaskHandler
{
public function run(): void
{
// ...
}
}
The respective task handler, ExampleTaskHandler
as defined previously in your services.xml
, has to extend from the class Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler
. This also comes with two methods, that you need to implement first:
getHandledMessages
: An iterable, or an array, of the scheduled tasks, that this handler will take care of. In this case this is only theExampleTask
class.run
: This method is executed once your scheduled task is executed. Do everything, that your task is supposed to do here. In this example, it will just create a new file.
Now every five minutes, your task will be executed and it will print an output every time now.
Executing the scheduled task
Usually scheduled tasks are registered when installing or updating your plugin. If you don't want to reinstall your plugin in order to register your scheduled task, you can also use the following command to achieve this: bin/console scheduled-task:register
In order to properly test your scheduled task, you first have to run the command bin/console scheduled-task:run
. This will start the ScheduledTaskRunner
, which takes care of your scheduled tasks and their respective timings. It will dispatch a message to the message bus once your scheduled task's interval is due.
Now you still need to run the command bin/console messenger:consume
to actually execute the dispatched messages. Make sure, that the status
of your scheduled task is set to scheduled
in the scheduled_task
table, otherwise it won't be executed. This is not necessary, when you're using the admin worker.