|
1 | 1 | /* |
2 | | - * Copyright 2013-2023 the original author or authors. |
| 2 | + * Copyright 2013-2025 the original author or authors. |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
@@ -418,6 +418,47 @@ else if (currentPoll.compareAndSet(2, 3)) { |
418 | 418 | } |
419 | 419 | } |
420 | 420 |
|
| 421 | + @Test |
| 422 | + void shouldRemovePollingFutureOnException() throws InterruptedException { |
| 423 | + String testName = "shouldClearPollingFuturesOnException"; |
| 424 | + |
| 425 | + SemaphoreBackPressureHandler backPressureHandler = SemaphoreBackPressureHandler.builder() |
| 426 | + .acquireTimeout(Duration.ofMillis(100)).batchSize(10).totalPermits(10) |
| 427 | + .throughputConfiguration(BackPressureMode.ALWAYS_POLL_MAX_MESSAGES).build(); |
| 428 | + |
| 429 | + AbstractPollingMessageSource<Object, Message> source = new AbstractPollingMessageSource<>() { |
| 430 | + @Override |
| 431 | + protected CompletableFuture<Collection<Message>> doPollForMessages(int messagesToRequest) { |
| 432 | + return CompletableFuture.failedFuture(new RuntimeException("Simulating a polling error")); |
| 433 | + } |
| 434 | + }; |
| 435 | + |
| 436 | + BackOffPolicy policy = mock(BackOffPolicy.class); |
| 437 | + BackOffContext ctx = mock(BackOffContext.class); |
| 438 | + given(policy.start(null)).willReturn(ctx); |
| 439 | + |
| 440 | + source.setBackPressureHandler(backPressureHandler); |
| 441 | + source.setMessageSink((msgs, context) -> CompletableFuture.completedFuture(null)); |
| 442 | + source.setId(testName + " source"); |
| 443 | + source.setPollingEndpointName("test-queue"); |
| 444 | + source.configure(SqsContainerOptions.builder().pollBackOffPolicy(policy).build()); |
| 445 | + source.setTaskExecutor(createTaskExecutor(testName)); |
| 446 | + source.setAcknowledgementProcessor(getNoOpsAcknowledgementProcessor()); |
| 447 | + |
| 448 | + @SuppressWarnings("unchecked") |
| 449 | + Collection<CompletableFuture<?>> futures = (Collection<CompletableFuture<?>>) ReflectionTestUtils |
| 450 | + .getField(source, "pollingFutures"); |
| 451 | + // Verify that the pollingFutures collection is initially empty |
| 452 | + assertThat(futures).isEmpty(); |
| 453 | + |
| 454 | + source.start(); |
| 455 | + |
| 456 | + // Verify that the pollingFutures collection is empty after the exceptional completion |
| 457 | + assertThat(futures).isEmpty(); |
| 458 | + |
| 459 | + source.stop(); |
| 460 | + } |
| 461 | + |
421 | 462 | private static boolean doAwait(CountDownLatch processingLatch) { |
422 | 463 | try { |
423 | 464 | return processingLatch.await(4, TimeUnit.SECONDS); |
|
0 commit comments