You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
From experimenting with [email protected] I noticed some undocumented behavior observing channel vs connection events. I don't know if I can rely on this behavior remaining consistent in future patch versions of amqplib, because it's currently undocumented.
It appears that observing channel.on('error', ...) changes the behavior of connection.on('error', ...), which also interacts with channel.on('close', ...)/connection.on('close', ...).
If this is an implementation detail, I'd like clarification in this issue. If it's intended as stable behavior, I believe this should be documented in the amqplib docs.
Observations:
Given connection.on('error', ...) and connection.on('close', ...)
(and no observers on channel)
Making a "soft" error (as defined by RabbitMQ docs) triggers both connection.on('error', ...) and connection.on('close', ...)
Given connection.on('error', ...), connection.on('close', ...), and channel.on('error', ...)
Making a "soft" error triggers channel.on('error', ...), but neither connection.on('error', ...) or connection.on('close', ...)
Given connection.on('error', ...), connection.on('close', ...), and channel.on('close', ...)
Making a "soft" error triggers connection.on('error', ...), channel.on('close', ...), and connection.on('close', ...)
Given connection.on('error', ...), connection.on('close', ...), channel.on('error', ...), and channel.on('close', ...)
Making a "soft" error triggers channel.on('error', ...), channel.on('close', ...), but neither connection.on('error', ...) or connection.on('close', ...)
In tabular form:
This undocumented nuance is a problem in the following example situation:
So when a "soft" error occurs, it's logged, the connection is closed, and re-acquired. The system self-heals.
Later the user wants more granular logging, so the user adds also:
channel.on('error', logChannelError)
Now when a "soft" error occurs, it's logged, the channel closes, but the connection remains open. Re-acquire isn't run, so the system is in a pathologic state.
The text was updated successfully, but these errors were encountered:
Thank you for putting this all together so clearly. I agree the the behaviour should be documented. I'll take some time to reproduce what you've done and confirm the behaviour.
This undocumented nuance is a problem in the following example situation:
Listen for channel both error & close events, then attempt recovery using the existing connection.
Listen for connection error & close events, then attempt recovery using a new connection.
There are some complications though - it was at one point possible to get both an error and close event, and even multiple error events (I'm not 100% this is still the case), so the code should only recover once. However, you can't simply use or unbind the listeners because an unhandled error event will crash the node application.
My preferred approach since writing rascal is to add error and close event handlers which publish a third lost event. I bind the recovery handler to the lost event using emitter.once so it is only triggered once, no matter how many close or error events are triggered. I never unbind the error and close event handlers so a repeat error event won't crash the application.
From experimenting with
[email protected]
I noticed some undocumented behavior observing channel vs connection events. I don't know if I can rely on this behavior remaining consistent in future patch versions ofamqplib
, because it's currently undocumented.It appears that observing
channel.on('error', ...)
changes the behavior ofconnection.on('error', ...)
, which also interacts withchannel.on('close', ...)
/connection.on('close', ...)
.If this is an implementation detail, I'd like clarification in this issue. If it's intended as stable behavior, I believe this should be documented in the amqplib docs.
Observations:
Given
connection.on('error', ...)
andconnection.on('close', ...)
(and no observers on channel)
Making a "soft" error (as defined by RabbitMQ docs) triggers both
connection.on('error', ...)
andconnection.on('close', ...)
Given
connection.on('error', ...)
,connection.on('close', ...)
, andchannel.on('error', ...)
Making a "soft" error triggers
channel.on('error', ...)
, but neitherconnection.on('error', ...)
orconnection.on('close', ...)
Given
connection.on('error', ...)
,connection.on('close', ...)
, andchannel.on('close', ...)
Making a "soft" error triggers
connection.on('error', ...)
,channel.on('close', ...)
, andconnection.on('close', ...)
Given
connection.on('error', ...)
,connection.on('close', ...)
,channel.on('error', ...)
, andchannel.on('close', ...)
Making a "soft" error triggers
channel.on('error', ...)
,channel.on('close', ...)
, but neitherconnection.on('error', ...)
orconnection.on('close', ...)
In tabular form:
This undocumented nuance is a problem in the following example situation:
Suppose the user has:
connection.on('error', logConnectionError)
connection.on('close', reconnectAndAcquireChannel)
So when a "soft" error occurs, it's logged, the connection is closed, and re-acquired. The system self-heals.
Later the user wants more granular logging, so the user adds also:
channel.on('error', logChannelError)
Now when a "soft" error occurs, it's logged, the channel closes, but the connection remains open. Re-acquire isn't run, so the system is in a pathologic state.
The text was updated successfully, but these errors were encountered: