Symfony how to use Mercure with Messenger + RabbitMQ? - symfony

I am looking to use Mercury with RabbitMQ. This is the first time that I have used Mercury as well as RabbitMQ so I am not yet good.
Here is where I am:
I've installed Mercure, and Messenger.
Messenger.yaml
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async: '%env(MESSENGER_TRANSPORT_DSN)%'
failed: '%env(MESSENGER_TRANSPORT_FAILED_DSN)%'
# sync: 'sync://'
routing:
# Route your messages to the transports
# 'App\Message\YourMessage': async
.env:
MERCURE_PUBLISH_URL=http://localhost:3000/.well-known/mercure
MERCURE_JWT_TOKEN=aVerySecretKey
MESSENGER_TRANSPORT_DSN=amqp://bastien:mypassword#localhost:5672/%2f/messages
MESSENGER_TRANSPORT_FAILED_DSN=amqp://bastien:mypassword#localhost:5672/%2f/failed
And in my controller I simulated 50 pings on a URL of my local app:
/**
* #Route("/ping", name="ping", methods={"POST"})
*/
public function ping(MessageBusInterface $bus)
{
for($i=0;$i<=50;$i++)
{
$update = new Update("http://monsite.com/ping", "[]");
$bus->dispatch($update);
}
return $this->redirectToRoute('home');
}
I have successfully started my instance of Mercury as well as that of Messenger which is therefore well connected to my RabbitMQ.
But when I test sending the pings, it works, but without going through my RabbitMQ. Did I miss something? I think of my Messenger.yaml in the routing part but I don't know what to put if it is the case

By default, messages are executed synchronously in messenger.
You will need to configure the Update message in the messenger.yaml to use the async transport:
Symfony\Component\Mercure\Update: async

Related

Command "symfony console messenger:failed:show" not working

I am working the Symfony Fast Track Chapter 18.3
Configuring the Messenger Configuration (config/packages/messenger.yaml):
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
auto_setup: false
use_notify: true
check_delayed_interval: 60000
retry_strategy:
max_retries: 3
multiplier: 2
failed:
dsn: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
routing:
# Route your messages to the transports
# 'App\Message\YourMessage': async
App\Message\CommentMessage: async
The Messenger daemon is started
But when I run the following command I get the error Message below:
jpmena#jpmena-300E4A-300E5A-300E7A-3430EA-3530EA:~/CONSULTANT/FASTTRACK/DEV/guestbook$ symfony console messenger:failed:show
There are no commands defined in the "messenger:failed" namespace.
Did you mean this?
messenger
What is wrong in my configuration?
I think your forget to remove comment on "failure_transport" line
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
failure_transport: failed <-- remove comment here

Can you define a consumer command that only consumes a specific queue of a multi-queue transport?

I have the impression to miss something while implementing AMQP services with RabbitMQ and Symfony Messenger.
From a RabbitMQ perspective, consumers (also known as workers) consume from queues.
From the Symfony Messenger documentation, one "transport" is linked to one consumer. This is by design as shown by the command bin/console messenger:consume transport. So, for each "handler", you have to configure a dedicated transport in messenger.yaml to be able to allocate a specific number of processes (via Supervisor for instance in configuring the numprocs variable).
As stated, I found a way to configure that use case using 2 different transports. Yet, that looks a bit too complicated to me:
framework:
messenger:
transports:
one_transport:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: my_exchange
type: direct
queues:
one_queue:
binding_keys:
- one_binding_key
another_transport:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: my_exchange
type: direct
queues:
another_queue:
binding_keys:
- another_binding_key
routing:
'App\MessageBroker\Message\OneNotification': one_transport
'App\MessageBroker\Message\AnotherNotification': another_transport
# In action 1
$this->dispatchMessage(
new OneNotification(), [new AmqpStamp('one_binding_key')]
);
# Action 2
$this->dispatchMessage(
new AnotherNotification(), [new AmqpStamp('another_binding_key')]
);
# SF consumer 1
[program:messenger-consume]
command=php bin/console messenger:consume one_transport
numprocs=4
# SF consumer 2
[program:messenger-consume]
command=php bin/console messenger:consume another_transport
numprocs=1
No other way to achieve this?

Messenger symfony : worker has no effect

I'm building an app with symfony 4.4. I use messenger to send emails asynchronously. everything works like a charm on my computer in dev. But on my server (debian VPS) something goes wrong.
When i try to send an email, my message is handled and stored by doctrine (select * from messenger_messages returns 1 line with the message I just sent). But when i run php bin/console messenger:consume async nothing's happens. The worker starts and stay waiting as if there were no message in database.
If someone could help ...
messenger.yaml
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async: '%env(MESSENGER_TRANSPORT_DSN)%'
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
async_priority_high:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
# default configuration
retry_strategy:
max_retries: 3
# milliseconds delay
delay: 1000
# causes the delay to be higher before each retry
# e.g. 1 second delay, 2 seconds, 4 seconds
multiplier: 2
max_delay: 0
# override all of this with a service that
# implements Symfony\Component\Messenger\Retry\RetryStrategyInterface
# service: null
routing:
# Route your messages to the transports
'App\Service\Email\EmailMessage': async
.env
MESSENGER_TRANSPORT_DSN=doctrine://default
Resolved
In fact, everything was working fine but with a 1 hour delay ... Mysql and system timezone xwere different :-( !

Shutdown Hook Corda integration testing

I have the following Corda service. It starts up a Jetty Server
#CordaService
class IOUService(private val serviceHub: AppServiceHub): SingletonSerializeAsToken() {
init {
val port = serviceHub.myInfo.addresses.first().port - 1002
log.println("IOUService init was called...")
log.println("Port: $port")
val jettyServer = JettyServer()
jettyServer.start(port)
}
}
My problem is how to release the stared Jetty port when running integration tests. Here are two example test (basically the same test twice to illustrate the problem):
#Test
fun `node test`() = withDriver {
val (partyAHandle, partyBHandle) = startNodes(bankA, bankB)
assertEquals(bankB.name, partyAHandle.resolveName(bankB.name))
assertEquals(bankA.name, partyBHandle.resolveName(bankA.name))
}
#Test
fun `node test2`() = withDriver {
val (partyAHandle, partyBHandle) = startNodes(bankA, bankB)
assertEquals(bankB.name, partyAHandle.resolveName(bankB.name))
assertEquals(bankA.name, partyBHandle.resolveName(bankA.name))
}
The first test will start up 3 nodes: one notary, BankA and BankB nodes with the following details:
Notary:
Advertised P2P messaging addresses : localhost:10000
RPC connection address : localhost:10001
RPC admin connection address : localhost:10002
Jetty Port: 8998
BankA:
Advertised P2P messaging addresses : localhost:10004
RPC connection address : localhost:10005
RPC admin connection address : localhost:10006
Jetty Port: 9002
BankB:
Advertised P2P messaging addresses : localhost:10008
RPC connection address : localhost:10009
RPC admin connection address : localhost:10010
Jetty Port: 9006
Unfortunately the second test will fails since the Jetty ports are still bound:
[ERROR] 14:22:04,825 [driver-pool-thread-0] internal.Node.installCordaServices - Corda service com.example.flows.IOUService failed to instantiate. Reason was: Address already in use [errorCode=1pryyp4, moreInformationAt=https://errors.corda.net/OS/4.1/1pryyp4]
java.io.IOException: Failed to bind to 0.0.0.0/0.0.0.0:9006
How to register a shutdown hook during integration testing in order to shut down the Jetty servers?
The example code can be found here:
https://github.com/altfatterz/learning-corda
A proper lifecycle for corda services is currently being looked at. Hopefully, you can do this in the future.
For now, there is not a simple way to do this from within the node.

Symfony2 and RabbitMqBundle. Can't publish a message

I am trying to use syfmony2 framework with RabbitMqBundle from here
I am sure that my rabbitmq server is up and running and I am doing the configuration and publishers code accordingly to the docs delivered on github. Unfortunately I can`t add any message to the queue.
I am sure that my rabbitmq server is up and running. I have queue named accordingly to the symfony configuration file.
Have anyone got any clue what is wrong?
Thanks in advance for any suggestions.
well... try this simple example
# app/config.yml
old_sound_rabbit_mq:
connections: %rabbitmq_connections%
producers: %rabbitmq_producers%
consumers: %rabbitmq_consumers%
parameters:
# connection parameters
rabbitmq_connections:
default: { host: 'localhost', port: 5672, user: 'guest', password: 'guest', vhost: '/' }
# define producers
rabbitmq_producers:
sample:
connection: default
exchange_options: {name: 'exchange_name', type: direct, auto_delete: false, durable: true}
# define consumers
rabbitmq_consumers:
sample:
connection: default
exchange_options: {name: 'exchange_name', type: direct, auto_delete: false, durable: true}
queue_options: {name: 'sample', auto_delete: false}
callback: rabbitmq.callback.service
then you should define your callback service. feel free to put it in app/config.yml
services:
rabbitmq.callback.service:
class: RabbitMQ\Callback\Service
and yes. you should write this callback service. here is simple implementation. should be enough for understanding and check is it works for you.
namespace RabbitMQ\Callback;
use OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface;
use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Message\AMQPMessage;
class Service implements ConsumerInterface
{
public function execute(AMQPMessage $msg)
{
var_dump(unserialize($msg->body));
}
}
then you should start rabbitmq server, run consumer and check was new exchange and queue added.
to run test consumer you should run
app/console rabbitmq:consumer sample --route="sample"
in your controller (where you want to send message to rabbitMQ put next code
# get producer service
$producer = $this->get('old_sound_rabbit_mq.sample_producer');
# publish message
$producer->publish(serialize(array('foo'=>'bar','_FOO'=>'_BAR')), 'sample');
Hope it's more or less clear and will help you with rabbitmq.
PS: it's easier to debug if you have rabbitmq management plugin. if you have no, use console commands like rabbitmqctl to check queues/exchanges/consumers and so on...
and also would be nice to see your configuration for producers/consumers. callback services code as well.
I also had some issue to send messages with this bundle, i recommend you to try SonataNotificationBundle instead.
You can also install the RabbitMq management plugin to see the queued messages.

Resources