8000 [Scheduler] pre_run and post_run events by alli83 · Pull Request #51805 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[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

Merged
merged 1 commit into from
Oct 16, 2023

Conversation

alli83
Copy link
Contributor
@alli83 alli83 commented Oct 2, 2023
Q A
Branch? 6.4
Bug fix? no
New feature? yes
Deprecations? no
Tickets #49803 (comment)
License MIT

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

  • the the schedule and therefore add/cancel a certain type of message.
  • MessageContexte (e.g. access the id)
  • The message itself

This PR would complement @Jeroeny #51553 PR by enabling action via events.

@carsonbot
Copy link

Hey!

Thanks for your PR. You are targeting branch "6.4" but it seems your PR description refers to branch "6.4 for features".
Could you update the PR description or change target branch? This helps core maintainers a lot.

Cheers!

Carsonbot

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 6 times, most recently from c523449 to 70218b2 Compare October 2, 2023 13:30
@alli83 alli83 changed the title [Scheduler] feat: pre_run and post_run events [Scheduler] pre_run and post_run events Oct 2, 2023
@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch from 70218b2 to c90b629 Compare October 2, 2023 14:17
Copy link
Member
@kbond kbond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick initial review

8000

namespace Symfony\Component\Scheduler\Event;

final class SchedulerEvents
Copy link
Member

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')) {
Copy link
Member

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.

Copy link
Contributor Author
@alli83 alli83 Oct 2, 2023

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)
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

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.

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch from c90b629 to 0a0fe36 Compare October 2, 2023 21:35
$schedulerTransport = $this->receiverLocator->get($event->getReceiverName());
$schedule = $schedulerTransport->getMessageGenerator()->schedule();

$this->eventDispatcher?->dispatch(new PostRunEvent($schedule, $messageContext, $envelope->getMessage()));
Copy link
Contributor Author

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.

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 3 times, most recently from 99f8d96 to c30f5f2 Compare October 2, 2023 21:53
Copy link
Member
@fabpot fabpot left a 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.

Comment on lines 23 to 24
public function __construct(private readonly ?EventDispatcherInterface $dispatcher = null)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public function __construct(private readonly ?EventDispatcherInterface $dispatcher = null)
{
public function __construct(
private readonly ?EventDispatcherInterface $dispatcher = null,
) {

Comment on lines 21 to 22
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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,
) {

Comment on lines 19 to 20
public function __construct(private readonly ScheduleProviderInterface $schedule, private readonly MessageContext $messageContext, private readonly object $message)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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;
Copy link
Member

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'),
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
])
])


class PreRunEvent
{
private bool $isCancel = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private bool $isCancel = false;
private bool $isCancelled = false;

9E88
@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 5 times, most recently from 4f8417b to 49d909f Compare October 3, 2023 10:22
@alli83
Copy link
Contributor Author
alli83 commented Oct 3, 2023

To access the Schedule, it has been decided to inject the transports via the locator service (messenger.receiver_locator). While it would have been possible to inject the schedules directly via the tagged locator scheduler.schedule_provider doing so would require memoizing the created schedule to avoid calling getSchedule() twice.

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch from 49d909f to f2cfe76 Compare October 9, 2023 05:30
@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 2 times, most recently from f462be9 to ffb8279 Compare October 10, 2023 06:58
interface MessageGeneratorInterface
{
/**
* @return iterable<MessageContext, object>
*/
public function getMessages(): iterable;

public function getSchedule(): Schedule;
Copy link
Member

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.

Copy link
Contributor Author
@alli83 alli83 Oct 11, 2023

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

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 3 times, most recently from ffd4881 to dc1d61e Compare October 12, 2023 03:03
Copy link
Member
@fabpot fabpot left a 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
Copy link
Member

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'),
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
])
])

@@ -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) {
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private readonly ?EventDispatcherInterface $dispatcher = null
private readonly ?EventDispatcherInterface $dispatcher = null,

Copy link
Member
@dunglas dunglas left a 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)

@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch 2 times, most recently from edecb50 to 49f05e3 Compare October 16, 2023 02:29
@alli83 alli83 force-pushed the scheduler-events-pre-run-post-run branch from 49f05e3 to 20fd21a Compare October 16, 2023 03:45
@fabpot
Copy link
Member
fabpot commented Oct 16, 2023

Thank you @alli83.

@fabpot fabpot merged commit 50662d0 into symfony:6.4 Oct 16, 2023
fabpot added a commit that referenced this pull request Oct 16, 2023
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
fabpot added a commit that referenced this pull request Oct 17, 2023
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
This was referenced Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0