@@ -8,6 +8,7 @@ const SubscriberSession = require('./SubscriberSession');
88const SubscriberError = require ( './SubscriberError' ) ;
99const backoff = require ( '../backoff' ) ;
1010const setTimeoutUnref = require ( '../utils/setTimeoutUnref' ) ;
11+ const { EMPTY_X_DEATH } = require ( './XDeath' ) ;
1112
1213module . exports = {
1314 create ( broker , vhost , counter , config , next ) {
@@ -214,16 +215,22 @@ function Subscription(broker, vhost, subscriptionConfig, counter) {
214215 function immediateNack ( message ) {
215216 const originalQueue = message . properties . headers . rascal . originalQueue ;
216217 const xDeathRecords = message . properties . headers [ 'x-death' ] || [ ] ;
217- const currentXDeath = xDeathRecords . find ( ( { queue, reason } ) => queue === originalQueue && reason === 'rejected' ) || { count : 0 , queue : originalQueue } ;
218- const previousXDeath = _ . get ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'xDeath' ] , { count : 0 , queue : originalQueue } ) ;
218+ const currentXDeath = xDeathRecords . find ( ( { queue, reason } ) => queue === originalQueue && reason === 'rejected' ) || EMPTY_X_DEATH ;
219+ const previousXDeath = _ . get ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'xDeath' ] , EMPTY_X_DEATH ) ;
219220 const hasImmediateNackHeader = _ . has ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'immediateNack' ] ) ;
220221 if ( ! hasImmediateNackHeader ) return false ;
221222 debug ( 'Message %s has been marked for immediate nack. Previous xDeath is %o. Current xDeath is %o.' , message . properties . messageId , previousXDeath , currentXDeath ) ;
222- if ( currentXDeath . count === previousXDeath . count ) return true ;
223- debug ( 'Message %s has been replayed after being dead lettered. Removing immediate nack.' , message . properties . messageId ) ;
224- _ . unset ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'immediateNack' ] ) ;
225- _ . unset ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'xDeath' ] ) ;
226- return false ;
223+ // See https://github.com/rabbitmq/rabbitmq-server/issues/11331
224+ // RabbitMQ v3.13 stopped updating the xDeath record's count property.
225+ // RabbitMQ v3.12 does not update the xDeath record's time property.
226+ // Therefore having test them both
227+ if ( currentXDeath . count > previousXDeath . count || currentXDeath . time . value > previousXDeath . time . value ) {
228+ debug ( 'Message %s has been replayed after being dead lettered. Removing immediate nack.' , message . properties . messageId ) ;
229+ _ . unset ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'immediateNack' ] ) ;
230+ _ . unset ( message , [ 'properties' , 'headers' , 'rascal' , 'recovery' , originalQueue , 'xDeath' ] ) ;
231+ return false ;
232+ }
233+ return true ;
227234 }
228235
229236 function getAckOrNack ( session , message ) {
0 commit comments