Skip to content

Commit 44ca031

Browse files
feeblefakieKodaiD
andauthored
Backport to branch(3.14) : Fix the DynamoDB metadata table upsert operation (#2789)
Co-authored-by: Kodai Doki <[email protected]>
1 parent 8ee76b2 commit 44ca031

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public class DynamoAdmin implements DistributedStorageAdmin {
9595
public static final String DEFAULT_NO_BACKUP = "false";
9696
public static final String DEFAULT_REQUEST_UNIT = "10";
9797
private static final int DEFAULT_WAITING_DURATION_SECS = 3;
98+
@VisibleForTesting static final int MAX_RETRY_COUNT = 10;
9899

99100
@VisibleForTesting static final String PARTITION_KEY = "concatenatedPartitionKey";
100101
@VisibleForTesting static final String CLUSTERING_KEY = "concatenatedClusteringKey";
@@ -418,15 +419,28 @@ private void putTableMetadata(Namespace namespace, String table, TableMetadata m
418419
METADATA_ATTR_SECONDARY_INDEX,
419420
AttributeValue.builder().ss(metadata.getSecondaryIndexNames()).build());
420421
}
421-
try {
422-
client.putItem(
423-
PutItemRequest.builder()
424-
.tableName(ScalarDbUtils.getFullTableName(metadataNamespace, METADATA_TABLE))
425-
.item(itemValues)
426-
.build());
427-
} catch (Exception e) {
428-
throw new ExecutionException(
429-
"Adding the meta data for table " + getFullTableName(namespace, table) + " failed", e);
422+
int retryCount = 0;
423+
while (true) {
424+
try {
425+
client.putItem(
426+
PutItemRequest.builder()
427+
.tableName(ScalarDbUtils.getFullTableName(metadataNamespace, METADATA_TABLE))
428+
.item(itemValues)
429+
.build());
430+
return;
431+
} catch (ResourceNotFoundException e) {
432+
if (retryCount >= MAX_RETRY_COUNT) {
433+
throw new ExecutionException(
434+
"Adding the metadata for the " + getFullTableName(namespace, table) + " table failed",
435+
e);
436+
}
437+
Uninterruptibles.sleepUninterruptibly(waitingDurationSecs, TimeUnit.SECONDS);
438+
retryCount++;
439+
} catch (Exception e) {
440+
throw new ExecutionException(
441+
"Adding the metadata for the " + getFullTableName(namespace, table) + " table failed",
442+
e);
443+
}
430444
}
431445
}
432446

core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,47 @@ public void createTable_WhenMetadataTableExists_ShouldCreateOnlyTable()
640640
.isInstanceOf(IllegalArgumentException.class);
641641
}
642642

643+
@Test
644+
public void createTable_WhenActualMetadataTableCreationIsDelayed_ShouldFailAfterRetries() {
645+
// Arrange
646+
// prepare tableIsActiveResponse
647+
TableDescription tableDescription = mock(TableDescription.class);
648+
when(tableIsActiveResponse.table()).thenReturn(tableDescription);
649+
when(tableDescription.tableStatus()).thenReturn(TableStatus.ACTIVE);
650+
when(client.describeTable(any(DescribeTableRequest.class))).thenReturn(tableIsActiveResponse);
651+
// prepare backupIsEnabledResponse
652+
DescribeContinuousBackupsResponse backupIsEnabledResponse =
653+
mock(DescribeContinuousBackupsResponse.class);
654+
when(client.describeContinuousBackups(any(DescribeContinuousBackupsRequest.class)))
655+
.thenReturn(backupIsEnabledResponse);
656+
ContinuousBackupsDescription continuousBackupsDescription =
657+
mock(ContinuousBackupsDescription.class);
658+
when(backupIsEnabledResponse.continuousBackupsDescription())
659+
.thenReturn(continuousBackupsDescription);
660+
when(continuousBackupsDescription.continuousBackupsStatus())
661+
.thenReturn(ContinuousBackupsStatus.ENABLED);
662+
when(client.putItem(any(PutItemRequest.class))).thenThrow(ResourceNotFoundException.class);
663+
TableMetadata metadata =
664+
TableMetadata.newBuilder()
665+
.addPartitionKey("c1")
666+
.addClusteringKey("c2", Order.DESC)
667+
.addClusteringKey("c3", Order.ASC)
668+
.addColumn("c1", DataType.TEXT)
669+
.addColumn("c2", DataType.BIGINT)
670+
.addColumn("c3", DataType.BOOLEAN)
671+
.addColumn("c4", DataType.INT)
672+
.addColumn("c5", DataType.BLOB)
673+
.addColumn("c6", DataType.DOUBLE)
674+
.addColumn("c7", DataType.FLOAT)
675+
.addSecondaryIndex("c4")
676+
.build();
677+
678+
// Act Assert
679+
assertThatThrownBy(() -> admin.createTable(NAMESPACE, TABLE, metadata))
680+
.isInstanceOf(ExecutionException.class);
681+
verify(client, times(DynamoAdmin.MAX_RETRY_COUNT + 1)).putItem(any(PutItemRequest.class));
682+
}
683+
643684
@Test
644685
public void dropTable_WithNoMetadataLeft_ShouldDropTableAndDeleteMetadata()
645686
throws ExecutionException {

0 commit comments

Comments
 (0)