Open
Description
Symfony version(s) affected
7.1.8
Description
We are setting up a Scheduler with worker processes managed by supervisor as per the documentation.
When you setup supervisor with a numprocs > 1, the scheduled message is handled as many times as the number of procs.
How to reproduce
First, install supervisor and the scheduler component.
Create a message :
<?php
namespace App\Messenger\Message\Scheduled;
final class CloseEvent
{
}
Create a schedule :
<?php
namespace App\Messenger\Schedule;
use App\Messenger\Message\Scheduled\CloseEvent;
use Symfony\Component\Scheduler\Attribute\AsSchedule;
use Symfony\Component\Scheduler\RecurringMessage;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\ScheduleProviderInterface;
#[AsSchedule]
class DefaultScheduleProvider implements ScheduleProviderInterface
{
public function getSchedule(): Schedule
{
return (new Schedule())->add(
RecurringMessage::every('10 seconds', new CloseEvent()),
);
}
}
Create a handler:
<?php
declare(strict_types=1);
namespace App\Messenger\Handler\Scheduled;
use App\Messenger\Message\Scheduled\CloseEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
final class CloseEventHandler
{
public function __construct(
private readonly LoggerInterface $logger,
) {}
public function __invoke(CloseEvent $closeEvent): void
{
$this->logger->info("Handling " . $closeEvent::class);
}
}
Setup supervisor with numprocs > 1 :
;/etc/supervisor/conf.d/messenger-worker.conf
[program:messenger-consume]
command=php /path/to/your/app/bin/console messenger:consume scheduler_default --limit=12 -vv
user=www-data
numprocs=5
startsecs=0
autostart=true
autorestart=true
startretries=10
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
Check your logs:
13:13:31 INFO [messenger] Received message App\Messenger\Message\Scheduled\CloseEvent ["class" => "App\Messenger\Message\Scheduled\CloseEvent"]
2024-11-20T13:13:31.444240549Z 13:13:31 INFO [app] Handling App\Messenger\Message\Scheduled\CloseEvent
2024-11-20T13:13:31.444423433Z 13:13:31 INFO [messenger] Message App\Messenger\Message\Scheduled\CloseEvent handled by App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke ["class" => "App\Messenger\Message\Scheduled\CloseEvent","handler" => "App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke"]
2024-11-20T13:13:31.444969771Z 13:13:31 INFO [messenger] App\Messenger\Message\Scheduled\CloseEvent was handled successfully (acknowledging to transport). ["class" => "App\Messenger\Message\Scheduled\CloseEvent","message_id" => null]
2024-11-20T13:13:31.448093269Z 13:13:31 INFO [messenger] Received message App\Messenger\Message\Scheduled\CloseEvent ["class" => "App\Messenger\Message\Scheduled\CloseEvent"]
2024-11-20T13:13:31.448810268Z 13:13:31 INFO [app] Handling App\Messenger\Message\Scheduled\CloseEvent
2024-11-20T13:13:31.448997009Z 13:13:31 INFO [messenger] Message App\Messenger\Message\Scheduled\CloseEvent handled by App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke ["class" => "App\Messenger\Message\Scheduled\CloseEvent","handler" => "App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke"]
2024-11-20T13:13:31.449545622Z 13:13:31 INFO [messenger] App\Messenger\Message\Scheduled\CloseEvent was handled successfully (acknowledging to transport). ["class" => "App\Messenger\Message\Scheduled\CloseEvent","message_id" => null]
2024-11-20T13:13:31.450240329Z 13:13:31 INFO [messenger] Received message App\Messenger\Message\Scheduled\CloseEvent ["class" => "App\Messenger\Message\Scheduled\CloseEvent"]
2024-11-20T13:13:31.450951608Z 13:13:31 INFO [app] Handling App\Messenger\Message\Scheduled\CloseEvent
2024-11-20T13:13:31.451188864Z 13:13:31 INFO [messenger] Message App\Messenger\Message\Scheduled\CloseEvent handled by App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke ["class" => "App\Messenger\Message\Scheduled\CloseEvent","handler" => "App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke"]
2024-11-20T13:13:31.451895003Z 13:13:31 INFO [messenger] App\Messenger\Message\Scheduled\CloseEvent was handled successfully (acknowledging to transport). ["class" => "App\Messenger\Message\Scheduled\CloseEvent","message_id" => null]
2024-11-20T13:13:32.442359552Z 13:13:32 INFO [messenger] Received message App\Messenger\Message\Scheduled\CloseEvent ["class" => "App\Messenger\Message\Scheduled\CloseEvent"]
2024-11-20T13:13:32.443020997Z 13:13:32 INFO [app] Handling App\Messenger\Message\Scheduled\CloseEvent
2024-11-20T13:13:32.443246231Z 13:13:32 INFO [messenger] Message App\Messenger\Message\Scheduled\CloseEvent handled by App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke ["class" => "App\Messenger\Message\Scheduled\CloseEvent","handler" => "App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke"]
2024-11-20T13:13:32.443762502Z 13:13:32 INFO [messenger] App\Messenger\Message\Scheduled\CloseEvent was handled successfully (acknowledging to transport). ["class" => "App\Messenger\Message\Scheduled\CloseEvent","message_id" => null]
2024-11-20T13:13:32.451876171Z 13:13:32 INFO [messenger] Received message App\Messenger\Message\Scheduled\CloseEvent ["class" => "App\Messenger\Message\Scheduled\CloseEvent"]
2024-11-20T13:13:32.452449379Z 13:13:32 INFO [app] Handling App\Messenger\Message\Scheduled\CloseEvent
2024-11-20T13:13:32.452608359Z 13:13:32 INFO [messenger] Message App\Messenger\Message\Scheduled\CloseEvent handled by App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke ["class" => "App\Messenger\Message\Scheduled\CloseEvent","handler" => "App\Messenger\Handler\Scheduled\CloseEventHandler::__invoke"]
2024-11-20T13:13:32.453045421Z 13:13:32 INFO [messenger] App\Messenger\Message\Scheduled\CloseEvent was handled successfully (acknowledging to transport). ["class" => "App\Messenger\Message\Scheduled\CloseEvent","message_id" => null]
Possible Solution
Set numprocs=1, this will ensure the message is handled only once but, I guess, this can be problematic in some cases.
Additional Context
No response