Thanks to visit codestin.com
Credit goes to github.com

Skip to content

WIP: [Messenger] Infinite Loop Receiver #28547

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

Closed
wants to merge 2 commits into from

Conversation

ragboyjr
Copy link
Contributor

  • Add a receiver decorator for standardizing the infinite
    looping format
  • Updated the AMQP transport to utilize the infinite looping
    receiver to simply design

Signed-off-by: RJ Garcia [email protected]

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? yes
Deprecations? no
Tests pass? not yet
Fixed tickets #...
License MIT
Doc PR symfony/symfony-docs#...

The AMQP looping and pcntl_signal structure is actually pretty common among other receivers like Redis or SQS. This WIP PR abstracts out that logic into a decorator to simplify the design of the AMQP receiver and to also prevent the duplication of code across the third party receivers.

It's WIP because I haven't added or updated tests yet, I wanted to create this first to see if you guys (@sroze) even approve of this change before I make the effort to get this ready for merge.

Thanks!

- Add a receiver decorator for standardizing the infinite
  looping format
- Updated the AMQP transport to utilize the infinite looping
  receiver to simply design

Signed-off-by: RJ Garcia <[email protected]>
Copy link
Contributor

@sroze sroze left a comment

Choose a reason for hiding this comment

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

I'd be happy to merge if we don't introduce a BC break (i.e. AmqpReceiver using this abstraction) and that you have a clear use-case you can explain for this abstraction :)

@@ -58,7 +59,7 @@ public function send(Envelope $envelope): void

private function getReceiver()
{
return $this->receiver = new AmqpReceiver($this->connection, $this->serializer);
return $this->receiver = new InfiniteLoopReceiver(new AmqpReceiver($this->connection, $this->serializer));
Copy link
Contributor

Choose a reason for hiding this comment

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

That's the only issue I can see here: it's more painful to create the receiver and it's very much error-prone for whoever is using these objects directly. Can't the AmqpReceiver use the InfiniteLoopReceiver instead? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sroze I'm not sure, the only way for Amqp to utilize this would be if we provided a utility method like:

function performOnInfiniteLoop(callable $shouldStop, callable $handler) {
  while (!$shouldStop()) {
     $handler();
  }
}

Also, are we 100% sure it's a bc break? because it's an internal class that's not really exposed to the outside since the TransportFactory is responsible for creating the actual receiver.

* Stop receiving some messages.
*/
public function stop(): void {
$this->shouldStop = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you should call $this->receiver->stop() as well here.

@ragboyjr
Copy link
Contributor Author

ragboyjr commented Sep 22, 2018

Hmm, I’m not entirely sure how the AMQP receiver would use the infinite loop receiver. I it would only work as a decorator. The only other thing would be using inheritance, but I think that defeats the purpose of having a simple interface. The other option for BC is that we don’t touch the AMQP receiver, and just add the infinite loop one when that other receivers can use.

Regarding a clear use case, I’m building a redis receiver for 4.1, and the receiver follows almost exactly the same pattern as the AMQP ext one. In fact everything is about the same including the connection. It seems like there are quite a few areas we could standardize, but felt like this would be a simple least obstructive one to make.

Also, I’m trying to think of a use case for a receiver that wouldn’t want infinite looping/sleeping. The other option would be that the receiver just stops and the process ends, and you’d need to use something like supervisor or cron to keep that command running at intervals, but in that case they might be better off as a normal symfony command...

Another thought that popped into my head, was, are we sure we even need to have the stop method on the receiver interface? It seems like instead of calling stop, we could just not call receive which would effectively do the same thing.

EDIT: Actually stop is needed to let the current receiver shut down properly.

And on top of that the pcntl calls in Worker.php and InfiniteLoopReceiver could probably be better suited in their own Receiver like PcntlReceiver...

@ragboyjr
Copy link
Contributor Author

Sorry I know this is a lot, but this is the last version to get the bc breaks in, so I’m just trying to bounce ideas off to see if they make any sense

@ragboyjr
Copy link
Contributor Author

@sroze Added a test case for the InfiteLoopReceiver and also updated it to delegate stop to the inner receiver.

@roukmoute
Copy link
Contributor

up?

@ragboyjr
Copy link
Contributor Author

ragboyjr commented Dec 8, 2018

@sroze Circling back to this.

The other option with the infinite loop receiver would be that it's an abstract class that could be extended to provide the functionality.

The tradeoffs I see is that are as follows:

Inheritance:

  • Keeps the current semantics of the amqp receiver. when you instantiate it, it will always infinite loop
  • Allows for simpler instantiation since infinite looping is apart of the DNA of the amqp receiver

Decoration:

  • Breaks the semantics, amqp on its own now will execute one time if not instantiated with amqp
  • Allows the amqp listener to be called with custom loop constraints
    • allows for custom constraints on the loop that might take external data into consideration per application
  • Allows for the ability to run one off receive calls via CLI.

After thinking further, i almost wonder if the decoration should take place in the ConsumeMessages command, and we add a flag for --once which will NOT decorate with infinite looping else, it will decorate with infinite looping.

@sroze
Copy link
Contributor

sroze commented Apr 6, 2019

A very similar thing has been merged when moving most of this code to the Worker class as part of the retry work (#30557). Thank you very much @ragboyjr for pushing for this to happen, it definitely helped even if this specific PR is not merged 🙌

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