Creating a Shopware Scheduled Task in a Plugin
Things that might go wrong with Scheduled Tasks in Shopware.
By. Jacob
Edited: 2022-06-23 11:09
Using Shopware's Scheduled Task instead of individual cron jobs is advisable, but Shopware's message queue uses Symfony's Messenger system, so if this is not familiar to you, be prepared for a rough ride.
Personally I find this system extremely complicated. It is far more complicated than using cron jobs or designing your own system from scratch, because the documentation is lacking, and the tasks can either fail and/or just not run for a number of reasons.
I have already had too many issues causing tasks not to run, so it has made me think the system is risky and difficult to use, possibly even unreliable for the same reason.
Creating a Shopware plugin that runs a specific task using the Messenger system is not easy. It does not matter what the task is doing, but for simplicity I suggest you just write a message to a file somewhere. E.g.:
file_put_contents('/srv/shopware/var/log/plugin-dev.log', time(). ":it is working\n", FILE_APPEND);
If you make a mistake doing the development process, your scheduled task might fail silently, and this comes in addition to other ways your tasks may fail and/or not run.
Developing a scheduled task plugin
This one is based on Shopware's own documentation: Add scheduled task
Testing a Scheduled Task
It is important you can test and verify that your task is running doing the plugin development, and for that you need to do the following:
1. Manually run scheduled-task:run from a terminal to start the ScheduledTaskRunner; this will dispatch tasks to the messenger bus.
2. Manually run messenger:consume to start a worker that actually executes the code in the scheduled task.
Before you start, you should also be aware there could be workers running in the background, so to avoid making the system unresponsive by running multiple workers concurrently, you should make sure all workers are stopped first:
sudo -u www-data bin/console messenger:stop-workers
Debugging tasks not running
You may have done exactly as Shopware tells you to in their documentation on creating a scheduled task, but your task might still not get run.
The symptoms could be, when you look in the scheduled_task table in the database, the last_execution_time of your task shows up as null, while the task status may just show as queued. Perhaps you have noticed the status briefly showing as scheduled, only to switch back to queued. So, what might just the problem be?
The worker might not be running
On the system I inherited, whoever setup the messenger:consume call in cron did so with a time limit, meaning that the worker would stop after just 60 seconds, and only restart after half an hour; this then created another cause for scheduled tasks not to get run.
You need to make sure the worker is started frequently enough to execute the task with the lowest frequency. The idea is that you occasionally make a call to messenger:consume with a cron job. E.g:
sudo -u www-data /srv/shopware/bin/console messenger:consume default --time-limit=60 --memory-limit=256M --quiet
Finally, there is a dangerous "admin-worker" that may be enabled by default. Personally I would not even use this in a development environment, because it will run whenever someone is logged in to the shopware backend, which just adds another point of uncertainty about what is happening. Be sure to disable this crap by either creating or editing config/packages/shopware.yaml to:
shopware:
admin_worker:
enable_admin_worker: false
If this does not work, you can also try disabling the admin worker in:
vendor/shopware/core/Framework/Resources/config/packages/shopware.yaml
Or, another location I have seen mentioned:
src/Core/Framework/Resources/config/packages/shopware.yaml
Clogging of the Enqueue table
I think I may have dealt with this problem under two different circumstances, both involving the enqueue table in the database.
1. The first time was when I received the obscure error message, AclPermissionCollection not found during decoding, and of course that first error would prevent me from even running messenger:consume; the cause was apparently that the "AclPermissionCollection" class was called from an old message (task) that was stuck in the enqueue table.
This error is probably rare, and not relevant in your case, but it is still interesting, because it seems to be related.
2. The second time I ran into a problem with the enqueue table was while developing a plugin. This time I also solved it by either truncating the table or removing the bugged task from the table manually.
Tell us what you think: