Make DynamoDBRefDatebase class implement ExtendedGlobalRefDatabase ExtendedGlobalRefDatabase provides `put` function to update item in the DynamoDB. Opposite to compareAndPut this method is not checking current global-refdb value. `put` method should be used to update value when atomicity doesn't have to be ensured. Bug: Issue 297440085 Change-Id: Ic50b07d5aac0f533fd81d019b606848a522b2ed5
diff --git a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabase.java b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabase.java index f6bdddc..933fd3f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabase.java +++ b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabase.java
@@ -18,17 +18,20 @@ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBLockClient; import com.amazonaws.services.dynamodbv2.LockItem; +import com.amazonaws.services.dynamodbv2.model.AttributeAction; import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; import com.amazonaws.services.dynamodbv2.model.GetItemResult; import com.amazonaws.services.dynamodbv2.model.LockNotGrantedException; import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase; +import com.gerritforge.gerrit.globalrefdb.ExtendedGlobalRefDatabase; import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException; import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError; import com.google.common.collect.ImmutableMap; import com.google.common.flogger.FluentLogger; import com.google.gerrit.entities.Project; +import com.google.gerrit.entities.Project.NameKey; import com.google.inject.Inject; import java.util.Optional; import javax.inject.Singleton; @@ -36,7 +39,7 @@ import org.eclipse.jgit.lib.Ref; @Singleton -public class DynamoDBRefDatabase implements GlobalRefDatabase { +public class DynamoDBRefDatabase implements ExtendedGlobalRefDatabase { public static final String REF_DB_PRIMARY_KEY = "refPath"; public static final String REF_DB_VALUE_KEY = "refValue"; @@ -146,6 +149,29 @@ } @Override + public <T> void put(NameKey project, String refName, T value) throws GlobalRefDbSystemError { + String refPath = pathFor(project, refName); + String refValue = + Optional.ofNullable(value).map(Object::toString).orElse(ObjectId.zeroId().getName()); + try { + dynamoDBClient.updateItem( + configuration.getRefsDbTableName(), + ImmutableMap.of(REF_DB_PRIMARY_KEY, new AttributeValue(refPath)), + ImmutableMap.of( + REF_DB_VALUE_KEY, + new AttributeValueUpdate(new AttributeValue(refValue), AttributeAction.PUT))); + logger.atFine().log( + "Updated path for project %s, path %s, value: %s", project.get(), refPath, refValue); + } catch (Exception e) { + throw new GlobalRefDbSystemError( + String.format( + "Error updating path for project %s, path %s. value: %s", + project.get(), refPath, refValue), + e); + } + } + + @Override public AutoCloseable lockRef(Project.NameKey project, String refName) throws GlobalRefDbLockException { String refPath = pathFor(project, refName);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabaseIT.java b/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabaseIT.java index b750c31..38b6dc8 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabaseIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/DynamoDBRefDatabaseIT.java
@@ -18,15 +18,9 @@ import static com.google.common.truth.Truth8.assertThat; import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.Configuration.DEFAULT_LOCKS_TABLE_NAME; import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.Configuration.DEFAULT_REFS_DB_TABLE_NAME; -import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.REF_DB_PRIMARY_KEY; -import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.REF_DB_VALUE_KEY; -import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.pathFor; import static org.testcontainers.containers.localstack.LocalStackContainer.Service.DYNAMODB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.google.common.collect.ImmutableMap; import com.google.gerrit.acceptance.LightweightPluginDaemonTest; import com.google.gerrit.acceptance.TestPlugin; import com.google.gerrit.acceptance.WaitUtil; @@ -167,6 +161,39 @@ } @Test + public void putShouldBeSuccessfulWhenNoPreviousValueForRefExists() { + String refName = "refs/changes/01/01/meta"; + String newRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c"; + + dynamoDBRefDatabase().put(project, refName, newRefValue); + Optional<String> result = dynamoDBRefDatabase().get(project, refName, String.class); + assertThat(result).hasValue(newRefValue); + } + + @Test + public void putShouldSuccessfullyUpdateRemovedRef() { + String refName = "refs/changes/01/01/meta"; + String newRefValue = null; + + dynamoDBRefDatabase().put(project, refName, newRefValue); + Optional<String> result = dynamoDBRefDatabase().get(project, refName, String.class); + assertThat(result).hasValue(ObjectId.zeroId().getName()); + } + + @Test + public void putShouldBeSuccessfulWhenUpdatingRef() { + String refName = "refs/changes/01/01/meta"; + String oldValue = "123"; + String newValue = "345"; + dynamoDBRefDatabase().put(project, refName, oldValue); + + dynamoDBRefDatabase().put(project, refName, newValue); + + Optional<String> result = dynamoDBRefDatabase().get(project, refName, String.class); + assertThat(result).hasValue(newValue); + } + + @Test public void compareAndPutShouldSuccessfullyUpdateRemovedRef() throws Exception { String refName = "refs/changes/01/01/meta"; String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c"; @@ -223,16 +250,7 @@ } private void createRefInDynamoDB(Project.NameKey project, String refPath, String refValue) { - dynamoDBClient() - .putItem( - new PutItemRequest() - .withTableName(DEFAULT_REFS_DB_TABLE_NAME) - .withItem( - ImmutableMap.of( - REF_DB_PRIMARY_KEY, - new AttributeValue(pathFor(project, refPath)), - REF_DB_VALUE_KEY, - new AttributeValue(refValue)))); + dynamoDBRefDatabase().put(project, refPath, refValue); } private Ref refOf(String refName, @Nullable String objectIdSha1) {