-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Scheduler] pre_run and post_run events #51805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of servic 8000 e and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hey! Thanks for your PR. You are targeting branch "6.4" but it seems your PR description refers to branch "6.4 for features". Cheers! Carsonbot |
c523449
to
70218b2
Compare
70218b2
to
c90b629
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick initial review
|
||
namespace Symfony\Component\Scheduler\Event; | ||
|
||
final class SchedulerEvents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure we don't want this class alias system anymore. We just the use event's FQCN.
@@ -99,6 +102,10 @@ public function run(array $options = []): void | |||
if ($queueNames) { | |||
$envelopes = $receiver->getFromQueues($queueNames); | |||
} else { | |||
if (method_exists($receiver, 'getMessageGenerator')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we'll want the messenger to be aware of the scheduler. Ideally, we want these events dispatched in the scheduler but can't currently think of how.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, as discussed, I will add listeners that listens to the WorkerMessageReceivedEvent and to the WorkerMessageHandledEvent and dispatch the corresponding scheduler event. Thank you for your feedback!
|
||
class PostRunEvent | ||
{ | ||
public function __construct(private readonly MessageGenerator $messageGenerator, private readonly Envelope $envelope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming we dispatch these events in the scheduler itself, we cannot use Envelope
here as it could be any object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed the standalone usage
use Symfony\Component\Scheduler\Exception\LogicException; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
final class Schedule implements ScheduleProviderInterface | ||
{ | ||
public function __construct(private readonly EventDispatcherInterface $dispatcher) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would need to be optional.
c90b629
to
0a0fe36
Compare
$schedulerTransport = $this->receiverLocator->get($event->getReceiverName()); | ||
$schedule = $schedulerTransport->getMessageGenerator()->schedule(); | ||
|
||
$this->eventDispatcher?->dispatch(new PostRunEvent($schedule, $messageContext, $envelope->getMessage())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that I would need the same info for pre_run and post_run event.
I will handle this code duplication.
99f8d96
to
c30f5f2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some CS stuff for now.
public function __construct(private readonly ?EventDispatcherInterface $dispatcher = null) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function __construct(private readonly ?EventDispatcherInterface $dispatcher = null) | |
{ | |
public function __construct( | |
private readonly ?EventDispatcherInterface $dispatcher = null, | |
) { |
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message) | |
{ | |
public function __construct( | |
private readonly ScheduleProviderInterface $schedule, | |
private readonly MessageContext $messageContext, | |
private readonly object $message, | |
) { |
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message) | |
{ | |
public function __construct( | |
private readonly ScheduleProviderInterface $schedule, | |
private readonly MessageContext $messageContext, | |
private readonly object $message, | |
) { |
{ | ||
public function __construct( | ||
private readonly ContainerInterface $receiverLocator, | ||
private readonly ?EventDispatcherInterface $eventDispatcher = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private readonly ?EventDispatcherInterface $eventDispatcher = null | |
private readonly ?EventDispatcherInterface $eventDispatcher = null, |
@@ -3,6 +3,7 @@ | |||
namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger; | |||
|
|||
use Symfony\Component\Cache\Adapter\ArrayAdapter; | |||
use Symfony\Component\EventDispatcher\EventDispatcher; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used?
->args([ | ||
service('messenger.receiver_locator'), | ||
service('event_dispatcher'), | ||
]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
]) | |
]) |
|
||
class PreRunEvent | ||
{ | ||
private bool $isCancel = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private bool $isCancel = false; | |
private bool $isCancelled = false; |
4f8417b
to
49d909f
Compare
To access the Schedule, it has been decided to inject the transports via the locator service ( |
src/Symfony/Component/Messenger/EventListener/DispatchSchedulerEventListener.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/EventListener/DispatchSchedulerEventListener.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php
Outdated
Show resolved
Hide resolved
src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php
Outdated
Show resolved
Hide resolved
49d909f
to
f2cfe76
Compare
src/Symfony/Component/Scheduler/EventListener/DispatchSchedulerEventListener.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Scheduler/EventListener/DispatchSchedulerEventListener.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Scheduler/Generator/MessageGeneratorInterface.php
Outdated
Show resolved
Hide resolved
f462be9
to
ffb8279
Compare
interface MessageGeneratorInterface | ||
{ | ||
/** | ||
* @return iterable<MessageContext, object> | ||
*/ | ||
public function getMessages(): iterable; | ||
|
||
public function getSchedule(): Schedule; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uncomfortable adding this method to the interface as a MessageGenerator implementation might not use a Schedule.
In any case, I don't see a reason to interact with the schedule before or after handling a message; it doesn't seem right (especially as we now - in 6.4 - have other ways) and again a Schedule is not a requirement to send scheduled messages.
I would recommend removing the Schedule from the events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the case when a message is scheduled to be sent every x hours until an event occurs.
It cannot be processed in the handler (messenger case), because it cannot be already processed at that time. The time at which its state (to be processed or not) can change lies within this x-hour interval. The aim, for example in pre_run, is to be able to check (before sending it to the handler) whether it is still relevant or whether, on the contrary, it should be removed from the stack of messages to be processed (since, for example, it will not have to be sent again if it has been processed in the meantime). The aim is to have access to the schedule and to be able to use the remove method, for example, which will recalculate the messages to be processed (using the setRestart introduced in 6.4).
Alternatively, I could inject the ScheduleProviderInterface directly into the event ?
what I don't understand is that on the Scheduler class side, generators will have a Schedule via ScheduleProviderInterface $scheduleProvider
.
Sorry if I misunderstood your point/comment
ffd4881
to
dc1d61e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now (just a few minor comments).
use Symfony\Component\Scheduler\Tests\Messenger\SomeScheduleProvider; | ||
use Symfony\Component\Scheduler\Trigger\TriggerInterface; | ||
|
||
class DispatchSchedulerEventListenerTest extends TestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must be moved to the Scheduler component test suite.
->args([ | ||
tagged_locator('scheduler.schedule_provider', 'name'), | ||
service('event_dispatcher'), | ||
]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
]) | |
]) |
@@ -62,8 +66,23 @@ public function run(array $options = []): void | |||
|
|||
$ran = false; | |||
foreach ($this->generators as $generator) { | |||
foreach ($generator->getMessages() as $message) { | |||
foreach ($generator->getMessages() as $context => $message) { | |||
if ($this->dispatcher) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about having testing !$this->dispatcher
to have less code in the condition?
use Symfony\Component\Scheduler\Exception\LogicException; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
final class Schedule implements ScheduleProviderInterface | ||
{ | ||
public function __construct( | ||
private readonly ?EventDispatcherInterface $dispatcher = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private readonly ?EventDispatcherInterface $dispatcher = null | |
private readonly ?EventDispatcherInterface $dispatcher = null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(when last comments from Fabien will be addressed)
edecb50
to
49f05e3
Compare
49f05e3
to
20fd21a
Compare
Thank you @alli83. |
This PR was merged into the 6.4 branch. Discussion ---------- [Scheduler] Fix dev requirements | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Follow-up of #51805 | License | MIT This should turn the CI green Commits ------- f241ed9 [Scheduler] Fix dev requirements
This PR was merged into the 6.4 branch. Discussion ---------- [Scheduler] Add `FailureEvent` | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | | License | MIT Following PR #51805, It would be interesting to add a `failureEvent` allowing you, for instance, to remove the recurring message, depending on the error caught. Commits ------- 891a404 [Scheduler] Add failureEvent
Based on #49803 @kbond and taking into account #51553
The aim of this PR is to be able to act on the accumulated messages 'if something happens' and to be able to recalculate the heap via events (currently pre_run and post_run).
The aim is to have access to
This PR would complement @Jeroeny #51553 PR by enabling action via events.