Skip to content

[Messenger] Add WorkerMetadata to Worker class. #42335

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 service 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
Sep 22, 2021

Conversation

okwinza
Copy link
Contributor

@okwinza okwinza commented Jul 31, 2021

Q A
Branch? 5.4
Bug fix? no
New feature? yes
Deprecations? no
Tickets Fixes #37736
License MIT
Doc PR -

At the moment, there is no clean way to access the values of transportNames or recently introduced queueNames that the worker was configured with, although such data might be quite useful for logging/monitoring or other tasks.

This PR attempts to fix that by adding a new and extensible way to provide additional information about a particular Worker object.

So far, the following PRs could benefit from this change:

Use case example:

  • As I developer
  • When a message was consumed from transport with name async.
  • And the worker state is idle.
  • Then I want to reset services.

Before this PR, the only solution not relying on using Reflection API would look like this:

    private $servicesResetter;
    private $receiversName;
    private $actualReceiverName = null;

    public function __construct(ServicesResetter $servicesResetter, array $receiversName)
    {
        $this->servicesResetter = $servicesResetter;
        $this->receiversName = $receiversName;
    }

    public function saveReceiverName(AbstractWorkerMessageEvent $event): void
    {
        $this->actualReceiverName = $event->getReceiverName();
    }

    public function resetServices(WorkerRunningEvent $event): void
    {
        if (!$event->isWorkerIdle() && \in_array($this->actualReceiverName, $this->receiversName, true)) {
            $this->servicesResetter->reset();
        }

        $this->actualReceiverName = null;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            WorkerMessageHandledEvent::class => ['saveReceiverName'],
            WorkerMessageFailedEvent::class => ['saveReceiverName'],
            WorkerRunningEvent::class => ['resetServices'],
        ];
    }

With this PR, one could simply use this to retrieve the transport name.

$event->getWorker()->getWorkerMetadata()->getTransportName() === $this->transportName;

So the whole solution would look like this:

    private $servicesResetter;
    private $receiversName;

    public function __construct(ServicesResetter $servicesResetter, array $receiversName)
    {
        $this->servicesResetter = $servicesResetter;
        $this->receiversName = $receiversName;
    }

    public function resetServices(WorkerRunningEvent $event): void
    {
        $actualTransportName = $event->getWorker()->getWorkerMetadata()->getTransportName();
        if (!$event->isWorkerIdle() || !in_array($actualTransportName, $this->receiversName, true)) {
            return;
        }

        $this->servicesResetter->reset();
    }

    public static function getSubscribedEvents(): array
    {
        return [
            WorkerRunningEvent::class => ['resetServices'],
        ];
    }

@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 5.4 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@okwinza okwinza force-pushed the feature/messenger-worker-metadata branch 2 times, most recently from c267c7c to 25902aa Compare July 31, 2021 17:34
@carsonbot
Copy link

Hey!

I think @alexander-schranz has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@OskarStark OskarStark changed the title [Messenger] Add WorkerMetadata to worker lifecycle events [Messenger] Add WorkerMetadata to worker lifecycle events Aug 1, 2021
@OskarStark OskarStark added this to the 5.4 milestone Aug 1, 2021
@alexander-schranz
Copy link
Contributor

@carsonbot find another a reviewer please.

@carsonbot
Copy link

@tienvx could maybe review this PR?

@okwinza
Copy link
Contributor Author

okwinza commented Aug 3, 2021

Friendly ping @Nyholm.
Could you see any value in such a feature? :)

@Guikingone
Copy link
Contributor

Guikingone commented Aug 9, 2021

Hi 👋🏻

I may ask a strange question but what's the benefits compared to using a getWorkerMetadata(): array?

As an event already receive the Worker, any benefits from using a dedicated class? 🤔

@okwinza
Copy link
Contributor Author

okwinza commented Aug 9, 2021

Hi 👋🏻

I may ask a strange question but what's the benefits compared to using a getWorkerMetadata(): array?

As an event already receive the Worker, any benefits from using a dedicated class? 🤔

Hi, indeed, the whole PR might be replaced with one or a couple getters but:

  1. IMO bloating Worker class with getters sounds more like a hack and doesn't seem like a good idea overall, it's better to keep the concerns separated here.
  2. I considered going with getWorkerMetadata(): array but the DX looked much worse to me since it wasn't clear what's being returned without first looking through the code/docs, etc. Not to mention that IDE autocomplete wont work and you won't be able to enforce return types on the language level that way. I know we have psalm for this, but still.

@chalasr
Copy link
Member

chalasr commented Aug 9, 2021

I like the idea of using an object but I think it's fine to make it accessible from the Worker instead of passing it to all worker-aware events.

@okwinza okwinza changed the title [Messenger] Add WorkerMetadata to worker lifecycle events [Messenger] Add WorkerMetadata to Worker class. Aug 31, 2021
@okwinza okwinza force-pushed the feature/messenger-worker-metadata branch from 3c10761 to afeaf60 Compare August 31, 2021 13:04
@okwinza
Copy link
Contributor Author

okwinza commented Aug 31, 2021

@chalasr I've refactored the PR according to your suggestions. Should be good to go once the CI is green.

@okwinza okwinza force-pushed the feature/messenger-worker-metadata branch from 53caaa0 to 20b3222 Compare August 31, 2021 14:31
@okwinza okwinza force-pushed the feature/messenger-worker-metadata branch 2 times, most recently from 20b3222 to 9260aa6 Compare September 10, 2021 12:21
@okwinza
Copy link
Contributor Author

okwinza commented Sep 13, 2021

Ping @chalasr @derrabus.
Is there anything I could do to make the review easier for you guys? :)

Copy link
Member

@lyrixx lyrixx left a comment

Choose a reason for hiding this comment

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

It looks cool.

But one question:

from where you gonna call $worker->getWorkerMetadata() ?

@okwinza
Copy link
Contributor Author

okwinza commented Sep 22, 2021

It looks cool.

But one question:

from where you gonna call $worker->getWorkerMetadata() ?

Much thanks for the review @lyrixx, appreciate it!
The primary use case is to call it from any worker event subscriber, mostly via WorkerRunningEvent::getWorker() or any other event that contains a reference to a Worker object.

Add tests for WorkerMetadata class


Fix WorkerMetadataTest header


Access WorkerMetadata directly via getter and make it mutable.


Fix CS


Refactor WorkerMetadata::set() method to accept array


Use null as default value for queueNames instead of false


Add missing return type


Make fabbot happy
@okwinza
Copy link
Contributor Author

okwinza commented Sep 22, 2021

Rebased, squashed & updated the PR description. Should be good to go now 🥳 .

@lyrixx
Copy link
Member

lyrixx commented Sep 22, 2021

Thanks for your work on this new feature!

@lyrixx lyrixx merged commit 99ebc69 into symfony:5.4 Sep 22, 2021
@okwinza okwinza deleted the feature/messenger-worker-metadata branch September 22, 2021 15:12
This was referenced Nov 5, 2021
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.

Missing transporter name on messenger events
7 participants