We have a project that partially uses DDD. When changing / creating an entity, we throw an event inside the entity. Next, the Doctrine Event Subscriber takes all the events and forwards them to the EventBus.
Let's say we have a MissionCreatedEvent event. I want to make routing key mission.event.created for it and tie it into 2 queues: new_mission_notification_to_part_time_employee and new_mission_area_notification_to_manager.
This is what the config looks like:
transports:
async_new_mission_notification_to_part_time_employee:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: mission
type: topic
queues:
new_mission_notification_to_part_time_employee:
binding_keys: ['mission.event.created']
retry_strategy:
max_retries: 0
async_new_mission_area_notification_to_manager:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
exchange:
name: mission
type: topic
queues:
new_mission_area_notification_to_manager:
binding_keys: ['mission.event.created']
retry_strategy:
max_retries: 0
routing:
'App\Domain\Mission\Event\MissionCreatedEvent':
- async_new_mission_notification_to_part_time_employee
- async_new_mission_area_notification_to_manager
The problem is that Symfony Messenger first runs on transports and only then pushes the message into exchange. Since we have 2 transports, it turns out that the event with routing key mission.event.created is triggered twice. Because of this, my Message handlers run 2 times.
There is an option not to use routing key mission.event.created. But use similar to mission.cmd.notify_part_time_employee_about_new_mission
and mission.cmd.notify_manager_about_new_mission_in_area for each transport with direct exchange.
This will help solve duplication problems, but I can’t use all the features that RabbitMQ gives me :(
Related
I want to submit a form with async method using messenger component and rabbitmq. After submitting this form, an email is sent to me. But when i implement rabbitmq it does not work. I have surely a problem with configuration. Maybe i have to add something in services.yml ? I dont want to use docker.
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
# failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
routing:
# Route your messages to the transports
'App\Message\MailNotification': async
.env file with amqp because i want to use rabbitmq
MESSENGER_TRANSPORT_DSN=amqp://guest:guest#localhost:5672/%2f/messages
Output give me this result when i submit form
Could not connect to the AMQP server. Please verify the provided DSN. ({"host":"localhost","port":5672,"vhost":"/","auto_setup":false,"use_notify":true,"check_delayed_interval":60000,"login":"guest","password":"********"}).
In addition, Rabbitmq UI appears on webprofiler DOWN, it does not turn to UP. I can't figure out. Help me please.
Do you have an example configuration to send logs by email with the Mailer component of Symfony 5.1.
In the Symfony blog we announce this feature, but I can't put the right config in monolog.yaml
https://symfony.com/blog/new-in-symfony-5-1-misc-improvements-part-3 :
That's why in Symfony 5.1 we added a new Monolog log handler which uses the Mailer component to send the logs via email.
Unfortunately this addition only covers the actuall MailerHandler class in the monolog-bridge. This does not cover the possibility to configure it in the monolog-bundle (that's the drawback if those components are distributed over multiple packages).
The PR for the change in the monolog-bundle is still open, and can be found here: Add Symfony Mailer support #354.
If you don't want to wait for the change in the monolog-bundle you could already use it by defining the handler as a service and then using it with the service type in the monolog configuration.
So define your service:
services:
# this configures the "mail" as a prototype, so you can
# define the sender and recipient mail addresses here
symfony_mailer_service_template:
class: Symfony\Component\Mime\Email
calls:
- ['from', ['webapp#example.com']]
- ['to', ['ops#example.com']]
- ['subject', ['Logs']]
symfony_mailer_service:
class: Symfony\Bridge\Monolog\Handler\MailerHandler
arguments:
- '#mailer.mailer'
- '#symfony_mailer_service_template'
- !php/const Monolog\Logger::DEBUG # log level
- true # bubble
And then in your mailer configuration you could use it like this:
monolog:
handlers:
main:
type: fingers_crossed
handler: deduplicated
deduplicated:
type: deduplication
handler: symfony_mailer
symfony_mailer:
type: service
id: symfony_mailer_service
On Symfony 5.1, I created two very basic message classes.
The first updates the database and then it calls the other to send a mail via SwiftMailer.
Both of them arrive to the consumer command as they are logged by the bin/console messenger:consume async -vv command, but while the class that updates the database is handled, the other remains suspended.
The fact is that if I stop and restart the consume command, this message becomes handled by the consumer and so the mail is sent.
I have tried with Redis and RabbitMQ transports, with the very same results.
This is the messenger configuration:
framework:
messenger:
transports:
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'App\Message\FollowRequestMessage': async
'App\Message\EmailMessage': async
This is the MESSENGER_TRANSPORT_DSN in .env:
MESSENGER_TRANSPORT_DSN=amqp://guest:guest#127.0.0.1:5672/%2f/messages
UPDATE
I defined another transport to handle the FollowRequest and Email messages separately, by duplicating the "async" transport config in the yaml messenger configuration.
This has fixed the issue, but I don't know if it the right way to handle the case.
So, it is correct to create a different transport for each kind of message? Or is it a workaround because of an error in something else?
I'm using spring-cloud-stream-kafka and I don't understand how is possible to change key.serializer property when using transactions. This is my configuration:
spring:
cloud:
stream:
bindings:
accountSource:
contentType: application/*+avro
destination: account
kafka:
binder:
brokers: ${KAFKA_BOOTSTRAP_ADDRESSES}
transaction:
transaction-id-prefix: tx-
producer:
configuration:
retries: 1
acks: all
bindings:
accountSource:
producer:
configuration:
key.serializer: org.apache.kafka.common.serialization.StringSerializer # Ignored!
schema:
avro:
subjectNamingStrategy: com.example.CustomSubjectNamingStrategy
schemaRegistryClient:
endpoint: ${KAFKA_SCHEMA_REGISTRY_URL}
I read here that when setting transaction properties at binder level, all other specific binding producer properties. Does this mean all producers in the applications should use the same key.serializer? It seems very restrictive to me.
The problem is the transaction has to be started by the consumer binding (so it can send the offset to the transaction and commit or rollback after success/failure).
If there are multiple producer bindings, the consumer binding has no idea which one(s) the application will send data to, so we have to use one global producer.
One solution would be to write a custom delegating serializer and set a header in the output message to tell the serializer which delegate serializer to call.
Trying to get spring cloud gateway to load balance across a couple of instances of our application, but just can't figure it out. We don't have a service registry at present (no Eureka etc).
I've been trying to use ribbon and have a configuration like so:
spring:
application:
name: gateway-service
cloud:
discovery:
locator:
enabled: true
gateway:
routes:
- id: my-service
uri: lb://my-load-balanced-service
predicates:
- Path=/
filters:
- TestFilter
ribbon:
eureka:
enabled: false
my-load-balanced-service:
ribbon:
listOfServers: localhost:8080, localhost:8081
However when I try a request to the gateway, I get a 200 response with content-length 0, and my stubs have not been hit.
I have a very basic setup, no beans defined.
How can I get ribbon to play nice / or an alternative?
You should check out whether spring-cloud-starter-netflix-ribbon dependency is on your project or not