1818import com .rabbitmq .client .AMQP ;
1919import com .rabbitmq .client .ShutdownSignalException ;
2020
21+ import static com .rabbitmq .client .impl .recovery .TopologyRecoveryRetryHandlerBuilder .builder ;
22+
2123/**
2224 * Useful ready-to-use conditions and operations for {@link DefaultRetryHandler}.
2325 * They're composed and used with the {@link TopologyRecoveryRetryHandlerBuilder}.
2931 */
3032public abstract class TopologyRecoveryRetryLogic {
3133
34+ /**
35+ * Channel has been closed because of a resource that doesn't exist.
36+ */
3237 public static final DefaultRetryHandler .RetryCondition <RecordedEntity > CHANNEL_CLOSED_NOT_FOUND = new DefaultRetryHandler .RetryCondition <RecordedEntity >() {
3338
3439 @ Override
@@ -43,6 +48,9 @@ public boolean test(RecordedEntity entity, Exception e) {
4348 }
4449 };
4550
51+ /**
52+ * Recover a channel.
53+ */
4654 public static final DefaultRetryHandler .RetryOperation <Void > RECOVER_CHANNEL = new DefaultRetryHandler .RetryOperation <Void >() {
4755
4856 @ Override
@@ -54,6 +62,9 @@ public Void call(RetryContext context) throws Exception {
5462 }
5563 };
5664
65+ /**
66+ * Recover the destination queue of a binding.
67+ */
5768 public static final DefaultRetryHandler .RetryOperation <Void > RECOVER_BINDING_QUEUE = new DefaultRetryHandler .RetryOperation <Void >() {
5869
5970 @ Override
@@ -72,6 +83,9 @@ public Void call(RetryContext context) {
7283 }
7384 };
7485
86+ /**
87+ * Recover a binding.
88+ */
7589 public static final DefaultRetryHandler .RetryOperation <Void > RECOVER_BINDING = new DefaultRetryHandler .RetryOperation <Void >() {
7690
7791 @ Override
@@ -81,6 +95,9 @@ public Void call(RetryContext context) throws Exception {
8195 }
8296 };
8397
98+ /**
99+ * Recover the queue of a consumer.
100+ */
84101 public static final DefaultRetryHandler .RetryOperation <Void > RECOVER_CONSUMER_QUEUE = new DefaultRetryHandler .RetryOperation <Void >() {
85102
86103 @ Override
@@ -99,11 +116,47 @@ public Void call(RetryContext context) {
99116 }
100117 };
101118
119+ /**
120+ * Recover a consumer.
121+ */
102122 public static final DefaultRetryHandler .RetryOperation <String > RECOVER_CONSUMER = new DefaultRetryHandler .RetryOperation <String >() {
103123
104124 @ Override
105125 public String call (RetryContext context ) throws Exception {
106126 return context .consumer ().recover ();
107127 }
108128 };
129+
130+ /**
131+ * Recover all the bindings of the queue of a consumer.
132+ */
133+ public static final DefaultRetryHandler .RetryOperation <Void > RECOVER_CONSUMER_QUEUE_BINDINGS = new DefaultRetryHandler .RetryOperation <Void >() {
134+
135+ @ Override
136+ public Void call (RetryContext context ) throws Exception {
137+ if (context .entity () instanceof RecordedConsumer ) {
138+ String queue = context .consumer ().getQueue ();
139+ for (RecordedBinding recordedBinding : context .connection ().getRecordedBindings ()) {
140+ if (recordedBinding instanceof RecordedQueueBinding && queue .equals (recordedBinding .getDestination ())) {
141+ recordedBinding .recover ();
142+ }
143+ }
144+ }
145+ return null ;
146+ }
147+ };
148+
149+ /**
150+ * Pre-configured {@link DefaultRetryHandler} that retries recovery of bindings and consumers
151+ * when their respective queue is not found.
152+ * This retry handler can be useful for long recovery processes, whereby auto-delete queues
153+ * can be deleted between queue recovery and binding/consumer recovery.
154+ */
155+ public static final RetryHandler RETRY_ON_QUEUE_NOT_FOUND_RETRY_HANDLER = builder ()
156+ .bindingRecoveryRetryCondition (CHANNEL_CLOSED_NOT_FOUND )
157+ .consumerRecoveryRetryCondition (CHANNEL_CLOSED_NOT_FOUND )
158+ .bindingRecoveryRetryOperation (RECOVER_CHANNEL .andThen (RECOVER_BINDING_QUEUE ).andThen (RECOVER_BINDING ))
159+ .consumerRecoveryRetryOperation (RECOVER_CHANNEL .andThen (RECOVER_CONSUMER_QUEUE .andThen (RECOVER_CONSUMER )
160+ .andThen (RECOVER_CONSUMER_QUEUE_BINDINGS )))
161+ .build ();
109162}
0 commit comments