Skip to content

[Messenger] Implement an ExecuteAfterDateStamp #38459

Closed
@Aerendir

Description

@Aerendir

Description
Currently the component has a DelayStamp().

It accepts the amount of seconds to wait before to process the message.

It is really helpful.

However, there are situations where I need to set the execution on a defined future date.

In this case, I need to do the calculations on my own, to calculate the diff and transform it in seconds, then set those seconds in the DelayStamp: nothing complex, but this is a use case I have often.

So, it would be useful to have a ExecuteAfterDateTimeStamp that automatically does all the calculations: we only need to pass it a future DateTimeInterface object.

Current workaround

I currently use a factory method ExecuteAfterDateStamp::executeAfter() that basically returns the calculated DelayStamp.

The code is below.

Example

use Symfony\Component\Messenger\Stamp\DelayStamp;

/**
 * Creates a DelayStamp starting from a date in the future.
 */
final class ExecuteAfterDateStamp
{
    /**
     * Disable instantiation.
     */
    private function __construct()
    {
    }

    public static function executeAfter(\DateTimeInterface $executeAfter): DelayStamp
    {
        $now  = (new \DateTimeImmutable())->format('U');
        $diff = \abs($executeAfter->format('U') - $now) * 1_000;

        return new DelayStamp($diff);
    }
}

Other context

I'm just starting understanding the mechanics of the Messenger Component.

From what I've seen reading the code, the DelayStamp is used by transports directly (ex.: https://github.com/symfony/doctrine-messenger/blob/master/Transport/DoctrineSender.php#L46).

So I think that implementing a new ExecuteAfterDateTimeStamp requires rewriting also all the senders to understand the new stamp.

Possible solutions

Solution 1: static facttory method

Maybe a better and easier solution is to create implement the static method I provided directly in the DelayStamp class, so we will be able to do something like this:

$delayStamp = DelayStamp::executeAfter($futureDate);

A solution that doesn't require much effort, is practical and, maybe, also more logic.

ExecuteAfterDateTimeStamp extends DelayedStam

Not so complex to understand: simply the new stamp extends the already present DelayedStamp and passes it the calculated value.

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