Skip to content

Commit b9edbc7

Browse files
committed
One of our new DDB source coordination integration tests is failing on GitHub. This change attempts to fix that by 1) including a sleep between writing events to ensure that they have different timestamps; and 2) waiting for the GSI to reach eventual consistency.
Signed-off-by: David Venable <dlv@amazon.com>
1 parent 033c994 commit b9edbc7

1 file changed

Lines changed: 46 additions & 22 deletions

File tree

data-prepper-plugins/dynamodb-source-coordination-store/src/test/java/org/opensearch/dataprepper/plugins/sourcecoordinator/dynamodb/DynamoDbSourceCoordinationStoreIT.java

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,29 @@
2424
import org.opensearch.dataprepper.model.source.coordinator.SourcePartitionStatus;
2525
import org.opensearch.dataprepper.model.source.coordinator.SourcePartitionStoreItem;
2626
import org.opensearch.dataprepper.model.source.coordinator.exceptions.PartitionUpdateException;
27+
import software.amazon.awssdk.core.pagination.sync.SdkIterable;
2728
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
29+
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbIndex;
2830
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
2931
import software.amazon.awssdk.enhanced.dynamodb.Key;
3032
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
3133
import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest;
34+
import software.amazon.awssdk.enhanced.dynamodb.model.Page;
35+
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
36+
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
3237
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
3338

3439
import java.time.Duration;
3540
import java.time.Instant;
41+
import java.util.List;
3642
import java.util.Optional;
3743
import java.util.Random;
3844
import java.util.UUID;
3945
import java.util.concurrent.TimeUnit;
46+
import java.util.concurrent.TimeUnit;
47+
import java.util.stream.Collectors;
48+
import java.util.stream.IntStream;
49+
import java.util.stream.Stream;
4050

4151
import static org.awaitility.Awaitility.await;
4252
import static org.hamcrest.MatcherAssert.assertThat;
@@ -50,6 +60,8 @@
5060
import static org.hamcrest.Matchers.sameInstance;
5161
import static org.junit.jupiter.api.Assertions.assertThrows;
5262
import static org.mockito.Mockito.when;
63+
import static org.opensearch.dataprepper.plugins.sourcecoordinator.dynamodb.DynamoDbClientWrapper.SOURCE_STATUS_COMBINATION_KEY_GLOBAL_SECONDARY_INDEX;
64+
import static org.opensearch.dataprepper.plugins.sourcecoordinator.dynamodb.DynamoDbSourceCoordinationStore.SOURCE_STATUS_COMBINATION_KEY_FORMAT;
5365

5466
@ExtendWith(MockitoExtension.class)
5567
class DynamoDbSourceCoordinationStoreIT {
@@ -93,8 +105,8 @@ void setUp() {
93105
when(dynamoStoreSettings.getRegion()).thenReturn(region);
94106
when(dynamoStoreSettings.getStsRoleArn()).thenReturn(stsRoleArn);
95107
when(dynamoStoreSettings.getStsExternalId()).thenReturn(stsExternalId);
96-
when(dynamoStoreSettings.getProvisionedReadCapacityUnits()).thenReturn(1L);
97-
when(dynamoStoreSettings.getProvisionedWriteCapacityUnits()).thenReturn(1L);
108+
when(dynamoStoreSettings.getProvisionedReadCapacityUnits()).thenReturn(10L);
109+
when(dynamoStoreSettings.getProvisionedWriteCapacityUnits()).thenReturn(10L);
98110

99111
when(dynamoDbClientFactory.provideDynamoDbClient(region, stsRoleArn, stsExternalId)).thenReturn(dynamoDbClient);
100112

@@ -252,44 +264,56 @@ void tryCreatePartitionItem_creates_an_item() {
252264
}
253265

254266
@Test
255-
void tryAcquireAvailablePartition_gets_first_unassigned_partition() {
267+
void tryAcquireAvailablePartition_gets_first_unassigned_partition() throws InterruptedException {
256268
final DynamoDbSourceCoordinationStore objectUnderTest = createObjectUnderTest();
257269
final String partitionProgressState = UUID.randomUUID().toString();
258270

259-
final String unassignedPartitionKey1 = UUID.randomUUID().toString();
260-
final String unassignedPartitionKey2 = UUID.randomUUID().toString();
261-
final String unassignedPartitionKey3 = UUID.randomUUID().toString();
271+
final List<String> partitionKeys = IntStream.rangeClosed(1, 3)
272+
.mapToObj(i -> UUID.randomUUID() + "_" + i)
273+
.collect(Collectors.toList());
274+
275+
for (final String partitionKey : partitionKeys) {
276+
final boolean createSuccess = objectUnderTest.tryCreatePartitionItem(sourceIdentifier,
277+
partitionKey, SourcePartitionStatus.UNASSIGNED, 1L, partitionProgressState, false);
278+
assertThat(createSuccess, equalTo(true));
279+
Thread.sleep(150);
280+
}
262281

263-
objectUnderTest.tryCreatePartitionItem(sourceIdentifier,
264-
unassignedPartitionKey1, SourcePartitionStatus.UNASSIGNED, 1L, partitionProgressState, false);
265-
objectUnderTest.tryCreatePartitionItem(sourceIdentifier,
266-
unassignedPartitionKey2, SourcePartitionStatus.UNASSIGNED, 1L, partitionProgressState, false);
267-
objectUnderTest.tryCreatePartitionItem(sourceIdentifier,
268-
unassignedPartitionKey3, SourcePartitionStatus.UNASSIGNED, 1L, partitionProgressState, false);
282+
await().atMost(10, TimeUnit.SECONDS).until(() -> {
283+
final String primaryKey = String.format(SOURCE_STATUS_COMBINATION_KEY_FORMAT, sourceIdentifier, SourcePartitionStatus.UNASSIGNED);
284+
final Stream<DynamoDbSourcePartitionItem> items = querySourceStatusIndex(primaryKey);
269285

270-
// Wait for partition to be available in DynamoDB Local before attempting to acquire
271-
final Optional<SourcePartitionStoreItem>[] maybeAcquiredHolder = new Optional[]{Optional.empty()};
272-
await().atMost(5, TimeUnit.SECONDS)
273-
.pollInterval(100, TimeUnit.MILLISECONDS)
274-
.untilAsserted(() -> {
275-
maybeAcquiredHolder[0] = objectUnderTest.tryAcquireAvailablePartition(sourceIdentifier, ownerId, Duration.ofSeconds(20));
276-
assertThat(maybeAcquiredHolder[0].isPresent(), equalTo(true));
277-
});
286+
return items.count() == partitionKeys.size();
287+
});
278288

279-
final Optional<SourcePartitionStoreItem> maybeAcquired = maybeAcquiredHolder[0];
289+
final Optional<SourcePartitionStoreItem> maybeAcquired = objectUnderTest.tryAcquireAvailablePartition(sourceIdentifier, ownerId, Duration.ofSeconds(20));
280290

281291
assertThat(maybeAcquired, notNullValue());
282292
assertThat(maybeAcquired.isPresent(), equalTo(true));
283-
284293
final SourcePartitionStoreItem acquiredItem = maybeAcquired.get();
285294

286295
assertThat(acquiredItem, notNullValue());
296+
final String unassignedPartitionKey1 = partitionKeys.get(0);
297+
287298
assertThat(acquiredItem.getSourceIdentifier(), equalTo(sourceIdentifier));
288299
assertThat(acquiredItem.getSourcePartitionKey(), equalTo(unassignedPartitionKey1));
289300
assertThat(acquiredItem.getSourcePartitionStatus(), equalTo(SourcePartitionStatus.ASSIGNED));
290301
assertThat(acquiredItem.getPartitionOwner(), equalTo(ownerId));
291302
}
292303

304+
private Stream<DynamoDbSourcePartitionItem> querySourceStatusIndex(final String partitionKey) {
305+
final DynamoDbIndex<DynamoDbSourcePartitionItem> sourceStatusIndex = table.index(SOURCE_STATUS_COMBINATION_KEY_GLOBAL_SECONDARY_INDEX);
306+
final QueryEnhancedRequest queryEnhancedRequest = QueryEnhancedRequest.builder()
307+
.limit(1)
308+
.queryConditional(QueryConditional.keyEqualTo(Key.builder().partitionValue(partitionKey).build()))
309+
.build();
310+
311+
final SdkIterable<Page<DynamoDbSourcePartitionItem>> pages = sourceStatusIndex.query(queryEnhancedRequest);
312+
313+
return pages.stream()
314+
.flatMap(page -> page.items().stream());
315+
}
316+
293317
private DynamoDbSourcePartitionItem putDynamoDbSourcePartitionItem(final SourcePartitionStatus sourcePartitionStatus) {
294318
final DynamoDbSourcePartitionItem putItem = createUnsavedPartitionItem(sourcePartitionStatus);
295319
table.putItem(putItem);

0 commit comments

Comments
 (0)