From 27e9181184b8eebc26ecdcad534562a9bf1c5095 Mon Sep 17 00:00:00 2001 From: Kodai Doki <52027276+KodaiD@users.noreply.github.com> Date: Wed, 18 Jun 2025 07:44:54 +0000 Subject: [PATCH 1/2] Empty commit [skip ci] From 2a5d12559f65e0b0337ef19fbf59ead4fbcfdd5d Mon Sep 17 00:00:00 2001 From: Kodai Doki <52027276+KodaiD@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:44:39 +0900 Subject: [PATCH 2/2] Resolve conflicts --- .../scalar/db/storage/dynamo/DynamoAdmin.java | 32 +++++++++++---- .../storage/dynamo/DynamoAdminTestBase.java | 41 +++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java b/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java index ecab14993c..93b5015009 100644 --- a/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java +++ b/core/src/main/java/com/scalar/db/storage/dynamo/DynamoAdmin.java @@ -95,6 +95,7 @@ public class DynamoAdmin implements DistributedStorageAdmin { public static final String DEFAULT_NO_BACKUP = "false"; public static final String DEFAULT_REQUEST_UNIT = "10"; private static final int DEFAULT_WAITING_DURATION_SECS = 3; + @VisibleForTesting static final int MAX_RETRY_COUNT = 10; @VisibleForTesting static final String PARTITION_KEY = "concatenatedPartitionKey"; @VisibleForTesting static final String CLUSTERING_KEY = "concatenatedClusteringKey"; @@ -418,15 +419,28 @@ private void putTableMetadata(Namespace namespace, String table, TableMetadata m METADATA_ATTR_SECONDARY_INDEX, AttributeValue.builder().ss(metadata.getSecondaryIndexNames()).build()); } - try { - client.putItem( - PutItemRequest.builder() - .tableName(ScalarDbUtils.getFullTableName(metadataNamespace, METADATA_TABLE)) - .item(itemValues) - .build()); - } catch (Exception e) { - throw new ExecutionException( - "Adding the meta data for table " + getFullTableName(namespace, table) + " failed", e); + int retryCount = 0; + while (true) { + try { + client.putItem( + PutItemRequest.builder() + .tableName(ScalarDbUtils.getFullTableName(metadataNamespace, METADATA_TABLE)) + .item(itemValues) + .build()); + return; + } catch (ResourceNotFoundException e) { + if (retryCount >= MAX_RETRY_COUNT) { + throw new ExecutionException( + "Adding the metadata for the " + getFullTableName(namespace, table) + " table failed", + e); + } + Uninterruptibles.sleepUninterruptibly(waitingDurationSecs, TimeUnit.SECONDS); + retryCount++; + } catch (Exception e) { + throw new ExecutionException( + "Adding the metadata for the " + getFullTableName(namespace, table) + " table failed", + e); + } } } diff --git a/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java b/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java index 6ff8b97cb9..e3686de97e 100644 --- a/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java +++ b/core/src/test/java/com/scalar/db/storage/dynamo/DynamoAdminTestBase.java @@ -640,6 +640,47 @@ public void createTable_WhenMetadataTableExists_ShouldCreateOnlyTable() .isInstanceOf(IllegalArgumentException.class); } + @Test + public void createTable_WhenActualMetadataTableCreationIsDelayed_ShouldFailAfterRetries() { + // Arrange + // prepare tableIsActiveResponse + TableDescription tableDescription = mock(TableDescription.class); + when(tableIsActiveResponse.table()).thenReturn(tableDescription); + when(tableDescription.tableStatus()).thenReturn(TableStatus.ACTIVE); + when(client.describeTable(any(DescribeTableRequest.class))).thenReturn(tableIsActiveResponse); + // prepare backupIsEnabledResponse + DescribeContinuousBackupsResponse backupIsEnabledResponse = + mock(DescribeContinuousBackupsResponse.class); + when(client.describeContinuousBackups(any(DescribeContinuousBackupsRequest.class))) + .thenReturn(backupIsEnabledResponse); + ContinuousBackupsDescription continuousBackupsDescription = + mock(ContinuousBackupsDescription.class); + when(backupIsEnabledResponse.continuousBackupsDescription()) + .thenReturn(continuousBackupsDescription); + when(continuousBackupsDescription.continuousBackupsStatus()) + .thenReturn(ContinuousBackupsStatus.ENABLED); + when(client.putItem(any(PutItemRequest.class))).thenThrow(ResourceNotFoundException.class); + TableMetadata metadata = + TableMetadata.newBuilder() + .addPartitionKey("c1") + .addClusteringKey("c2", Order.DESC) + .addClusteringKey("c3", Order.ASC) + .addColumn("c1", DataType.TEXT) + .addColumn("c2", DataType.BIGINT) + .addColumn("c3", DataType.BOOLEAN) + .addColumn("c4", DataType.INT) + .addColumn("c5", DataType.BLOB) + .addColumn("c6", DataType.DOUBLE) + .addColumn("c7", DataType.FLOAT) + .addSecondaryIndex("c4") + .build(); + + // Act Assert + assertThatThrownBy(() -> admin.createTable(NAMESPACE, TABLE, metadata)) + .isInstanceOf(ExecutionException.class); + verify(client, times(DynamoAdmin.MAX_RETRY_COUNT + 1)).putItem(any(PutItemRequest.class)); + } + @Test public void dropTable_WithNoMetadataLeft_ShouldDropTableAndDeleteMetadata() throws ExecutionException {