|
28 | 28 | import java.util.concurrent.Future; |
29 | 29 |
|
30 | 30 | import static org.awaitility.Awaitility.await; |
| 31 | +import static org.junit.jupiter.api.Assertions.assertFalse; |
31 | 32 | import static org.junit.jupiter.api.Assertions.assertThrows; |
32 | 33 | import static org.mockito.ArgumentMatchers.any; |
33 | 34 | import static org.mockito.ArgumentMatchers.eq; |
34 | 35 | import static org.mockito.BDDMockito.given; |
| 36 | +import static org.mockito.Mockito.doThrow; |
35 | 37 | import static org.mockito.Mockito.lenient; |
36 | 38 | import static org.mockito.Mockito.mockStatic; |
37 | 39 | import static org.mockito.Mockito.never; |
@@ -150,6 +152,40 @@ void test_stream_runThrowsException() { |
150 | 152 |
|
151 | 153 | } |
152 | 154 |
|
| 155 | + @Test |
| 156 | + void test_stream_giveUpPartitionThrowsException_schedulerContinuesRunning() { |
| 157 | + final String collection = UUID.randomUUID().toString(); |
| 158 | + final StreamPartition streamPartition = new StreamPartition(collection, null); |
| 159 | + given(sourceCoordinator.acquireAvailablePartition(StreamPartition.PARTITION_TYPE)).willReturn(Optional.of(streamPartition)); |
| 160 | + given(collectionConfig.getCollection()).willReturn(collection); |
| 161 | + final int streamBatchSize = 1000; |
| 162 | + given(collectionConfig.getStreamBatchSize()).willReturn(streamBatchSize); |
| 163 | + doThrow(new RuntimeException("giveUpPartition failed")) |
| 164 | + .when(sourceCoordinator).giveUpPartition(any(StreamPartition.class)); |
| 165 | + |
| 166 | + final ExecutorService executorService = Executors.newSingleThreadExecutor(); |
| 167 | + final Future<?> future = executorService.submit(() -> { |
| 168 | + try (MockedStatic<StreamWorker> streamWorkerMockedStatic = mockStatic(StreamWorker.class)) { |
| 169 | + streamWorkerMockedStatic.when(() -> StreamWorker.create(any(RecordBufferWriter.class), any(PartitionKeyRecordConverter.class), eq(sourceConfig), |
| 170 | + any(StreamAcknowledgementManager.class), any(DataStreamPartitionCheckpoint.class), eq(pluginMetrics), eq(DEFAULT_RECORD_FLUSH_BATCH_SIZE), |
| 171 | + eq(DEFAULT_CHECKPOINT_INTERVAL_MILLS), eq(DEFAULT_BUFFER_WRITE_INTERVAL_MILLS), eq(streamBatchSize), any(DocumentDBSourceAggregateMetrics.class))) |
| 172 | + .thenThrow(RuntimeException.class); |
| 173 | + streamScheduler.run(); |
| 174 | + } |
| 175 | + }); |
| 176 | + |
| 177 | + await() |
| 178 | + .atMost(Duration.ofSeconds(5)) |
| 179 | + .untilAsserted(() -> verify(sourceCoordinator).giveUpPartition(streamPartition)); |
| 180 | + |
| 181 | + // Scheduler is still running — didn't crash from the giveUpPartition exception. |
| 182 | + // streamPartition is reset to null, enabling clean reacquisition on the next iteration. |
| 183 | + assertFalse(future.isDone()); |
| 184 | + |
| 185 | + future.cancel(true); |
| 186 | + executorService.shutdownNow(); |
| 187 | + } |
| 188 | + |
153 | 189 | @Test |
154 | 190 | void test_stream_sourceCoordinatorThrowsException() { |
155 | 191 | final StreamPartition streamPartition = new StreamPartition(UUID.randomUUID().toString(), null); |
|
0 commit comments