Skip to content

Add Support for Immediate Message Handling within the Same Consumer in Symfony Messenger #58635

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

Open
rodion-k opened this issue Oct 22, 2024 · 6 comments

Comments

@rodion-k
Copy link

Description

Add the ability to handle messages immediately within the same consumer without sending them to the queue, while preserving the current functionality when messages are dispatched from external contexts.

Current Behavior: When a message A is handled by a consumer and dispatches a message B, both messages are sent to their respective queues as configured, regardless of their context.

Proposed Behavior:

Message B should be handled immediately if it is dispatched during the handling of message A within the same consumer.

If message B is dispatched from an external context (e.g., a web process), it should still be sent to its configured queue.

This feature would improve efficiency by reducing latency for message chains that are handled within the same consumer, without affecting external dispatches. It ensures that synchronous handling happens only when appropriate, maintaining the reliability and scalability benefits of the queue system for other contexts.

Example

No response

@rodion-k
Copy link
Author

rodion-k commented Oct 23, 2024

IIUC you can dispatch using the sync transport from your handler.

It won't work if the message is dispatched from a component that is used in different contexts.

@yuukikuno
Copy link

yuukikuno commented Oct 23, 2024

If I understand your issue correctly, this should be possible using the TransportNamesStamp as per the Messenger documentation.

Something like:

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            sync: sync://
            async:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
        routing:
            App\Message\AMessage: async
            App\Message\BMessage: async
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;

#[AsMessageHandler]
class AMessageHandler
{
    public function __construct(MessageBusInterface $bus)
    {
    }

    public function __invoke(AMessage $message)
    {
        $this->bus->dispatch(
            new BMessage(),
            [new TransportNamesStamp(['sync'])]
        );
    }
}

Would this solve your issue?

@rodion-k
Copy link
Author

Hi @yuukikuno

As I said before it would work only if you call dispatch directly in your handler, but if you have a reusable component that is called from different contexts it won't work:

class HardWorkService
{
    public function __construct(MessageBusInterface $bus)
    {
    }

    public function doHardWork()
    {
        $this->bus->dispatch(new BMessage());
    }
}
class SomeController
{
    public function someAction(HardWorkService $service)
    {
        $service->doHardWork();
    }
}
#[AsMessageHandler]
class AMessageHandler
{
    public function __construct(private HardWorkService $service)
    {
    }

    public function __invoke(AMessage $message)
    {
        $this->service->doHardWork();
    }
}

In this simplified case, it's easy to pass some parameter and rely on it to pass TramsportNamesStamp or not, but if the dispatching happens deep in the function call stack, this will be problematic.

@faizanakram99
Copy link
Contributor

Fwiw symfony scheduler works like this, the dispatched messages are handled immediately instead of sending them to respective queues (read transport), you need to use Redispatch stamp to send them to proper queue, which is kinda meh tbh.

I'd rather have consistency, that is, messages should always go into queue unless specified otherwise (even with scheduler)

@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?
Every feature is developed by the community.
Perhaps someone would like to try?
You can read how to contribute to get started.

@carsonbot
Copy link

Could I get a reply or should I close this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants