8000 [Messenger] Negative delay with Doctrine bridge can't be used · Issue #50833 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[Messenger] Negative delay with Doctrine bridge can't be used #50833
Closed
@Sinjonathan

Description

@Sinjonathan

Symfony version(s) affected

5.4.25

Description

When we send envelop with negative delay with messenger configured with Redis bridge, messages are immediately processed.

But it's not the case with Doctrine bridge because here, available_at column of the database queue table is wrongly set.

How to reproduce

First we calc a $delayStamp that is representing the delay between the expected execution time (x day in the past) and the current time when we create the envelop (now).

Because of the expected execution time is in the past, we want it to be executed with no delay.

$negativeDelayStamp = (($expectedExecuteAt->getTimestamp() - (new DateTime('now'))->getTimestamp()) * 1000);

Here we dispatch a simple envelop with a negative DelayStamp

$this->messageBus->dispatch(
            new Envelope(new MyMessage(), [
                new DelayStamp($negativeDelayStamp),
            ]));

Next in Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection $availableAt is calculated using the delay sent :

    public function send(string $body, array $headers, int $delay = 0): string
    {
        $now = new \DateTimeImmutable();
        $availableAt = $now->modify(sprintf('+%d seconds', $delay / 1000));

        $queryBuilder = $this->driverConnection->createQueryBuilder()
            ->insert($this->configuration['table_name'])
            ->values([
                'body' => '?',
                'headers' => '?',
                'queue_name' => '?',
                'created_at' => '?',
                'available_at' => '?',
            ]);
            
            ...

Because of the + in sprintf('+%d seconds', $delay / 1000) , the negative delay will be interpreted positively (ex: -1000 will be interpreted as +1000).

So instead of set availableAt at the expected execution time, x second in the past, it will set availableAt at the x second in the future.

Possible Solution

I see multiple solution here :

  • remove the + in $availableAt = $now->modify(sprintf('+%d seconds', $delay / 1000));

  • throw an exception if negative delay is not a wanted feature

  • do nothing and let the devs verify the delay value before they sent the envelop

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

      0