48
48
import org .springframework .context .ApplicationEventPublisher ;
49
49
import org .springframework .context .ApplicationEventPublisherAware ;
50
50
import org .springframework .jmx .export .annotation .ManagedOperation ;
51
+ import org .springframework .retry .backoff .ExponentialBackOffPolicy ;
52
+ import org .springframework .retry .policy .SimpleRetryPolicy ;
53
+ import org .springframework .retry .support .RetryTemplate ;
51
54
import org .springframework .util .Assert ;
52
55
53
56
import com .rabbitmq .client .AMQP .Queue .DeclareOk ;
@@ -96,13 +99,17 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Applicat
96
99
97
100
private final RabbitTemplate rabbitTemplate ;
98
101
102
+ private RetryTemplate retryTemplate ;
103
+
104
+ private boolean retryDisabled ;
105
+
99
106
private volatile boolean running = false ;
100
107
101
- private volatile boolean autoStartup = true ;
108
+ private boolean autoStartup = true ;
102
109
103
- private volatile ApplicationContext applicationContext ;
110
+ private ApplicationContext applicationContext ;
104
111
105
- private volatile boolean ignoreDeclarationExceptions ;
112
+ private boolean ignoreDeclarationExceptions ;
106
113
107
114
private final Object lifecycleMonitor = new Object ();
108
115
@@ -367,6 +374,25 @@ public Properties getQueueProperties(final String queueName) {
367
374
});
368
375
}
369
376
377
+ /**
378
+ * Set a retry template for auto declarations. There is a race condition with
379
+ * auto-delete, exclusive queues in that the queue might still exist for a short time,
380
+ * preventing the redeclaration. The default retry configuration will try 5 times with
381
+ * an exponential backOff starting at 1 second a multiplier of 2.0 and a max interval
382
+ * of 5 seconds. To disable retry, set the argument to {@code null}. Note that this
383
+ * retry is at the macro level - all declarations will be retried within the scope of
384
+ * this template. If you supplied a {@link RabbitTemplate} that is configured with a
385
+ * {@link RetryTemplate}, its template will retry each individual declaration.
386
+ * @param retryTemplate the retry template.
387
+ * @since 1.7.8
388
+ */
389
+ public void setRetryTemplate (RetryTemplate retryTemplate ) {
390
+ this .retryTemplate = retryTemplate ;
391
+ if (retryTemplate == null ) {
392
+ this .retryDisabled = true ;
393
+ }
394
+ }
395
+
370
396
// Lifecycle implementation
371
397
372
398
public boolean isAutoStartup () {
@@ -391,6 +417,15 @@ public void afterPropertiesSet() {
391
417
return ;
392
418
}
393
419
420
+ if (this .retryTemplate == null && !this .retryDisabled ) {
421
+ this .retryTemplate = new RetryTemplate ();
422
+ this .retryTemplate .setRetryPolicy (new SimpleRetryPolicy (5 ));
423
+ ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy ();
424
+ backOffPolicy .setInitialInterval (1000 );
425
+ backOffPolicy .setMultiplier (2.0 );
426
+ backOffPolicy .setMaxInterval (5000 );
427
+ this .retryTemplate .setBackOffPolicy (backOffPolicy );
428
+ }
394
429
if (this .connectionFactory instanceof CachingConnectionFactory &&
395
430
((CachingConnectionFactory ) this .connectionFactory ).getCacheMode () == CacheMode .CONNECTION ) {
396
431
this .logger .warn ("RabbitAdmin auto declaration is not supported with CacheMode.CONNECTION" );
@@ -413,7 +448,15 @@ public void afterPropertiesSet() {
413
448
* chatter). In fact it might even be a good thing: exclusive queues only make sense if they are
414
449
* declared for every connection. If anyone has a problem with it: use auto-startup="false".
415
450
*/
416
- initialize ();
451
+ if (this .retryTemplate != null ) {
452
+ this .retryTemplate .execute (c -> {
453
+ initialize ();
454
+ return null ;
455
+ });
456
+ }
457
+ else {
458
+ initialize ();
459
+ }
417
460
}
418
461
finally {
419
462
initializing .compareAndSet (true , false );
0 commit comments