Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Scheduler/Lock] Lock (flock) do not work when using scheduler with cron #60357

Copy link
Copy link
Open
@secit-pl

Description

@secit-pl
Issue body actions

Symfony version(s) affected

7.x.x

Description

If we use the Symfony scheduler to generate cyclic messages and we run the scheduler within CRON, the lock (flock) mechanism will not work

How to reproduce

Use default flock lock component DSN in .env

LOCK_DSN=flock

Create message:

<?php

namespace App\Message;

final readonly class EmailTestMessage
{
}

Create message handler

<?php

namespace App\MessageHandler;

use App\Message\EmailTestMessage;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Mime\Email;

#[AsMessageHandler]
final readonly class EmailTestMessageHandler
{
    public function __construct(
        private MailerInterface $mailer,
    ) {
    }

    public function __invoke(EmailTestMessage $message)
    {
        $this->mailer->send(
            (new Email())
                ->to('mail@example.com')
                ->subject(sprintf('[EmailTest] %s (pid: %d)', (new \DateTime())->format('H:i:s'), getmypid()))
                ->text('')
        );
    }
}

create scheduler

<?php

namespace App\Scheduler;

use App\Message\EmailTestMessage;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Scheduler\Attribute\AsSchedule;
use Symfony\Component\Scheduler\RecurringMessage;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\ScheduleProviderInterface;

#[AsSchedule('default')]
final readonly class DefaultScheduleProvider implements ScheduleProviderInterface
{
    public function __construct(
        private LockFactory $lockFactory,
    ) {
    }

    public function getSchedule(): Schedule
    {
        $from = new \DateTimeImmutable('00:00:00', new \DateTimeZone('UTC'));

        return (new Schedule())->add(
                RecurringMessage::every('30 seconds', new EmailTestMessage(), $from),
            )
            ->lock($this->lockFactory->createLock('default-scheduler'))
        ;
    }
}

Now run 2 schedulers in the same time:

1> symfony console messenger:consume async failed scheduler_default --time-limit=120
2> symfony console messenger:consume async failed scheduler_default --time-limit=120

The lock will work, and you'll get one mail per 30 seconds.

Now configure cron as follows:

* * * * *       ...      php /patch/to/bin/console messenger:consume async failed scheduler_default --time-limit=120 --quiet

This should run 2 concurrent consumers after one minute. When the second scheduler will start you'll start receiving doubled emails every 30 seconds:

Image

Possible Solution

The problem is related to the way how the default configuration of the flock is working if the code is executed by cron. If I change the LOCK_DSN in .env to:

LOCK_DSN=flock://var/lock

the problem will disappear and from now in all cases the scheduler will produce only one message and in the result I'll get only one email.

Image

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.