2

I want to be able to handle api calls synchronoulsy and asynchronously easily.

So I created an empty interface with according handler and base class

interface ApiPayloadInterface
{
}

class ApiPayload implements ApiPayloadInterface
{
    /** @var array */
    public $payload;

    /** @var string */
    public $username;
}
class ApiPayloadMessageHandler implements MessageHandlerInterface
{
    public function __invoke(ApiPayloadInterface $row)
    {
        ...
    }
}

Ok, then I have empty child classes to distinguish async from sync

class ApiPayloadSync extends ApiPayload implements ApiPayloadInterface
{}
class ApiPayloadASync extends ApiPayload implements ApiPayloadInterface
{}

The selection happens in messenger.yaml

    transports:
        async: 'doctrine://default?auto_setup=false'
        sync: 
            dsn: 'sync://'
                retry_strategy:
                    max_retries: 0

        routing:
            'App\Entity\Messages\ApiPayloadSync': sync
            'App\Entity\Messages\ApiPayloadASync': async

Ok, this does work, but I get errors when dispatching sync payloads:

$this->dispatch($bSync ? new ApiPayloadSync() : new ApiPayloadASync());

in my log file I see dozens of such messages:

[2019-10-27 22:11:14] messenger.CRITICAL: Error thrown while handling message App\Entity\Messages\ApiPayloadSync. Removing from transport after 3 retries. Error: "No handler for message "App\Entity\Messages\ApiPayloadSync"." {"message":"[object] (App\Entity\Messages\ApiPayloadSync: {"payload":{"action":"mdcadd",...})","class":"App\Entity\Messages\ApiPayloadSync","retryCount":3,"error":"No handler for message "App\Entity\Messages\ApiPayloadSync".","exception":"[object] (Symfony\Component\Messenger\Exception\NoHandlerForMessageException(code: 0): No handler for message "App\Entity\Messages\ApiPayloadSync". at /var/www/xxx/vendor/symfony/messenger/Middleware/HandleMessageMiddleware.php:75)"} []

So, the framework does start retries although I configured it to not perform any (for the sync transport)

Stephan Vierkant
  • 9,674
  • 8
  • 61
  • 97
olidem
  • 1,961
  • 2
  • 20
  • 45
  • 1
    I think you can't use an Interface like that, did you check https://github.com/symfony/symfony/pull/27188 and https://github.com/symfony/symfony/issues/27076? – qdequippe Nov 18 '19 at 12:39
  • You should typehint by class not interface... – Albeis Nov 18 '19 at 14:03
  • or configure manually your messenger handler https://symfony.com/doc/current/messenger.html#manually-configuring-handlers – Fabien Salles Nov 18 '19 at 14:56
  • 1
    Hmm, these (relatively old) issues say that interfaces can't be used but it seems to be recognised: `# bin/console debug:messenger ... The following messages can be dispatched: ---------------------------------------------------------------------------- App\Entity\Messages\ApiPayloadInterface handled by App\MessageHandler\ApiPayloadMessageHandler ` – olidem Nov 18 '19 at 17:34
  • 2
    hmm... ``` A message handler is a PHP callable, the recommended way to create it is to create a class that implements MessageHandlerInterface and has an __invoke() method that's type-hinted with the message class (or a message interface): ``` taken from https://symfony.com/doc/current/messenger.html#creating-a-message-handler – olidem Nov 18 '19 at 17:43
  • Works as expected in 5.1. – msg Oct 23 '20 at 13:32

0 Answers0