@@ -472,11 +472,11 @@ private void checkConsumers(long now) {
472
472
final List <SimpleConsumer > consumersToCancel ;
473
473
synchronized (this .consumersMonitor ) {
474
474
consumersToCancel = this .consumers .stream ()
475
- .filter (c -> {
476
- boolean open = c .getChannel ().isOpen ();
475
+ .filter (consumer -> {
476
+ boolean open = consumer .getChannel ().isOpen () && ! consumer . isAckFailed ();
477
477
if (open && this .messagesPerAck > 1 ) {
478
478
try {
479
- c .ackIfNecessary (now );
479
+ consumer .ackIfNecessary (now );
480
480
}
481
481
catch (IOException e ) {
482
482
this .logger .error ("Exception while sending delayed ack" , e );
@@ -487,18 +487,18 @@ private void checkConsumers(long now) {
487
487
.collect (Collectors .toList ());
488
488
}
489
489
consumersToCancel
490
- .forEach (c -> {
490
+ .forEach (consumer -> {
491
491
try {
492
- RabbitUtils .closeMessageConsumer (c .getChannel (),
493
- Collections .singletonList (c .getConsumerTag ()), isChannelTransacted ());
492
+ RabbitUtils .closeMessageConsumer (consumer .getChannel (),
493
+ Collections .singletonList (consumer .getConsumerTag ()), isChannelTransacted ());
494
494
}
495
495
catch (Exception e ) {
496
496
if (logger .isDebugEnabled ()) {
497
- logger .debug ("Error closing consumer " + c , e );
497
+ logger .debug ("Error closing consumer " + consumer , e );
498
498
}
499
499
}
500
- this .logger .error ("Consumer canceled - channel closed " + c );
501
- c .cancelConsumer ("Consumer " + c + " channel closed" );
500
+ this .logger .error ("Consumer canceled - channel closed " + consumer );
501
+ consumer .cancelConsumer ("Consumer " + consumer + " channel closed" );
502
502
});
503
503
}
504
504
@@ -813,7 +813,7 @@ private void cancelConsumer(SimpleConsumer consumer) {
813
813
this .logger .debug ("Canceling " + consumer );
814
814
}
815
815
synchronized (consumer ) {
816
- consumer .canceled = true ;
816
+ consumer .setCanceled ( true ) ;
817
817
if (this .messagesPerAck > 1 ) {
818
818
consumer .ackIfNecessary (0L );
819
819
}
@@ -887,6 +887,8 @@ final class SimpleConsumer extends DefaultConsumer {
887
887
888
888
private volatile boolean canceled ;
889
889
890
+ private volatile boolean ackFailed ;
891
+
890
892
private SimpleConsumer (Connection connection , Channel channel , String queue ) {
891
893
super (channel );
892
894
this .connection = connection ;
@@ -911,6 +913,23 @@ int getEpoch() {
911
913
return this .epoch ;
912
914
}
913
915
916
+ /**
917
+ * Set to true to indicate this consumer is canceled and should send any pending
918
+ * acks.
919
+ * @param canceled the canceled to set
920
+ */
921
+ void setCanceled (boolean canceled ) {
922
+ this .canceled = canceled ;
923
+ }
924
+
925
+ /**
926
+ * True if an ack/nack failed (probably due to a closed channel).
927
+ * @return the ackFailed
928
+ */
929
+ boolean isAckFailed () {
930
+ return this .ackFailed ;
931
+ }
932
+
914
933
/**
915
934
* Increment and return the current epoch for this consumer; consumersMonitor must
916
935
* be held.
@@ -1069,6 +1088,7 @@ else if (!isChannelTransacted() || isLocallyTransacted) {
1069
1088
}
1070
1089
}
1071
1090
catch (Exception e ) {
1091
+ this .ackFailed = true ;
1072
1092
this .logger .error ("Error acking" , e );
1073
1093
}
1074
1094
}
@@ -1079,7 +1099,7 @@ else if (!isChannelTransacted() || isLocallyTransacted) {
1079
1099
* @param now the current time.
1080
1100
* @throws IOException if one occurs.
1081
1101
*/
1082
- private synchronized void ackIfNecessary (long now ) throws IOException {
1102
+ synchronized void ackIfNecessary (long now ) throws IOException {
1083
1103
if (this .pendingAcks >= this .messagesPerAck || (
1084
1104
this .pendingAcks > 0 && (now - this .lastAck > this .ackTimeout || this .canceled ))) {
1085
1105
sendAck (now );
0 commit comments