|
8 | 8 | import org.mockito.junit.jupiter.MockitoExtension; |
9 | 9 | import org.opensearch.dataprepper.model.source.coordinator.enhanced.EnhancedSourceCoordinator; |
10 | 10 | import org.opensearch.dataprepper.model.source.coordinator.enhanced.EnhancedSourcePartition; |
| 11 | +import org.opensearch.dataprepper.model.source.coordinator.exceptions.PartitionUpdateException; |
11 | 12 | import org.opensearch.dataprepper.plugins.source.dynamodb.DynamoDBSourceConfig; |
12 | 13 | import org.opensearch.dataprepper.plugins.source.dynamodb.configuration.ExportConfig; |
13 | 14 | import org.opensearch.dataprepper.plugins.source.dynamodb.configuration.StreamConfig; |
|
16 | 17 | import org.opensearch.dataprepper.plugins.source.dynamodb.coordination.partition.LeaderPartition; |
17 | 18 | import org.opensearch.dataprepper.plugins.source.dynamodb.coordination.partition.StreamPartition; |
18 | 19 | import org.opensearch.dataprepper.plugins.source.dynamodb.coordination.state.StreamProgressState; |
| 20 | +import org.opensearch.dataprepper.test.helper.ReflectivelySetField; |
19 | 21 | import software.amazon.awssdk.services.dynamodb.DynamoDbClient; |
20 | 22 | import software.amazon.awssdk.services.dynamodb.model.ContinuousBackupsDescription; |
21 | 23 | import software.amazon.awssdk.services.dynamodb.model.ContinuousBackupsStatus; |
|
55 | 57 | import static org.mockito.ArgumentMatchers.isNull; |
56 | 58 | import static org.mockito.BDDMockito.given; |
57 | 59 | import static org.mockito.Mockito.atLeast; |
| 60 | +import static org.mockito.Mockito.doThrow; |
58 | 61 | import static org.mockito.Mockito.lenient; |
59 | 62 | import static org.mockito.Mockito.never; |
60 | 63 | import static org.mockito.Mockito.times; |
@@ -330,6 +333,35 @@ void run_without_acquiring_leader_partition_does_not_save_null_state() { |
330 | 333 | verify(coordinator, never()).saveProgressStateForPartition(isNull(), any(Duration.class)); |
331 | 334 | } |
332 | 335 |
|
| 336 | + @Test |
| 337 | + void test_shardDiscovery_with_failure_to_save_partition_state_reacquires_partition() throws InterruptedException, NoSuchFieldException, IllegalAccessException { |
| 338 | + leaderScheduler = new LeaderScheduler(coordinator, dynamoDbClient, shardManager, List.of(tableConfig)); |
| 339 | + leaderPartition = new LeaderPartition(); |
| 340 | + leaderPartition.getProgressState().get().setInitialized(true); |
| 341 | + leaderPartition.getProgressState().get().setStreamArns(List.of(streamArn)); |
| 342 | + given(coordinator.acquireAvailablePartition(LeaderPartition.PARTITION_TYPE)).willReturn(Optional.of(leaderPartition)); |
| 343 | + doThrow(PartitionUpdateException.class).when(coordinator).saveProgressStateForPartition(eq(leaderPartition), any(Duration.class)); |
| 344 | + |
| 345 | + ReflectivelySetField.setField(LeaderScheduler.class, leaderScheduler, "leaseInterval", Duration.ofMillis(40)); |
| 346 | + |
| 347 | + ExecutorService executorService = Executors.newSingleThreadExecutor(); |
| 348 | + executorService.submit(() -> leaderScheduler.run()); |
| 349 | + |
| 350 | + Thread.sleep(100); |
| 351 | + executorService.shutdownNow(); |
| 352 | + // Already init |
| 353 | + verifyNoInteractions(dynamoDbClient); |
| 354 | + |
| 355 | + // Should check the completed partitions |
| 356 | + verify(coordinator, atLeast(2)).queryCompletedPartitions(eq(StreamPartition.PARTITION_TYPE), any(Instant.class)); |
| 357 | + |
| 358 | + // Should create 3 stream partitions for child shards found |
| 359 | + verify(coordinator, atLeast(3)).createPartition(any(EnhancedSourcePartition.class)); |
| 360 | + |
| 361 | + verify(coordinator, atLeast(2)).saveProgressStateForPartition(eq(leaderPartition), any(Duration.class)); |
| 362 | + verify(coordinator, atLeast(2)).acquireAvailablePartition(LeaderPartition.PARTITION_TYPE); |
| 363 | + } |
| 364 | + |
333 | 365 |
|
334 | 366 | /** |
335 | 367 | * Helper function to mock DescribeContinuousBackupsResponse |
|
0 commit comments