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 :-( !
Related
How can I call a task that temporarily interrupts network connectivity to the target when it runs.
I wrote a PowerShell ansible module that modifies the target windows network settings causing it to lose connectivity for around 30 seconds. The connection is to a windows 2019 server via winrm I need to know if the task succeeded or reports errors.
If I call the task normally, it will fail with host unreachable if the network is gone for more than read timeout (30) seconds. The operation may have succeeded, but I don't have access to its return values.
- win_vswitch:
Name: "SomeSwitch"
VLAN: 123
state: present
Seems like a good use of async:
- name: Configure VSwitch
win_vswitch:
Name: "SomeSwitch"
VLAN: 123
state: present
async: 600
poll: 0
register: async_result
- name: vswitch - wait for the async task to finish
async_status:
jid: "{{ async_result.ansible_job_id }}"
register: task_result
until: task_result.finished
# ignore_unreachable: yes
retries: 60
delay: 5
# failed_when: False
The problem is that if the async_status poll is unable to get a network connection to the target for more than read_timeout seconds, it fails with host unreachable error. Even if the async_status's timeouts haven't expired.
Seems to me that I just need to set the read timeout to a higher value. And that's where I'm stuck.
Things I've tried:
timeout in ansible.cfg
ansible_winrm_read_timeout_sec & ansible_winrm_operation_timeout_sec in the inventory host item
ignore_unreachable & failed_when in the async_status module
rescue clause around the async_status
Suggestions?
TIA, Jeff
You can define ansible_winrm_connection_timeout (and other ansible_winrm_* values as well), by defining vars on the task itself:
- name: vswitch - wait for the async task to finish
async_status:
jid: "{{ async_result.ansible_job_id }}"
register: task_result
until: task_result.finished
retries: 60
delay: 5
vars:
ansible_winrm_connection_timeout: 300
This may be preferable to using the win_wait_for task depending upon the use case. win_wait_for might be good for a task when the network connectivity will immediately drop; however, if you have a task that will cause a drop at a random time (like a task installing network drivers).
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
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?
I'm trying to configure my consumer to work with an exponential backoff where the message will be processed a fixed number of attempts, applying among them the backoff period. But I don't get the expected behaviour.
This is my Java code:
#EnableBinding({
MessagingConfiguration.EventTopic.class
})
public class MessagingConfiguration {
public interface EventTopic {
String INPUT = "events-channel";
#Input(INPUT)
#Nonnull
SubscribableChannel input();
}
}
#StreamListener(MessagingConfiguration.EventTopic.INPUT))
void handle(#Nonnull Message<Event> event) {
throw new RuntimeException("FAILING!");
}
If I try the next configuration:
spring.cloud.stream:
bindings:
events-channel:
content-type: application/json
destination: event-develop
group: group-event-service
consumer:
max-attempts: 2
After all retries (20*) I get this message:
Backoff FixedBackOff{interval=0, currentAttempts=10, maxAttempts=9} exhausted for ConsumerRecord(...
2 (consumer.max-attempts) * 10 (FixedBackOff.currentAttempts) = 20* retries
All these retries occur with 1 second of delay (default backoff period)
If I change the configuration to:
spring.cloud.stream:
bindings:
events-channel:
content-type: application/json
destination: event-develop
group: group-event-service
consumer:
max-attempts: 8
#Times in milliseconds
back-off-initial-interval: 1000
back-off-max-interval: 60000
back-off-multiplier: 2
The backoff period is well applied during the 8 retries (max-attempts) BUT when the 8 retries finish a new cycle of retries is started indefinitely blocking the topic.
In the next versions, maybe I will implement a more sophisticated system of error handling but now I only need to discard the message after the retries and get the next one.
What am I doing wrong?
I read a lot of questions/answers here, the official documentation and some tutorials on the internet but I didn't find a solution to avoid the infinite loop of retries.
P.S.: I'm working with spring-cloud-stream (3.1.1) and spring-kafka (2.6.6)
This is because the listener container is now configured, by default, with a SeekToCurrentErrorHandler with 10 attempts.
This means you are compounding retries.
You can inject a suitably configured SeekToCurrentErrorHandler using a ListenerContainerCustomizer #Bean.
It is recommended to not have retries configured in both places; either remove the binding configuration and replace it with a suitably configured error handler, or change the error handler to have no retries.
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