Использование DynamoDBSaveExpression для проверки существования другого ключа - PullRequest
0 голосов
/ 24 ноября 2018

В качестве простого примера у меня есть класс, который выглядит следующим образом:

public class DbData {
    @DynamoDBAutoGeneratedKey
    @DynamoDBHashKey(attributeName = "id")
    private UUID id;
    private UUID parent;
    // other fields ...
}

Этот класс хранится в таблице DynamoDB.Когда в таблицу добавляется новая запись, я хочу убедиться, что родитель уже существует (если родитель установлен).

Можно ли это сделать с помощью выражения DynamoDBSaveExpression?

Например,Я могу убедиться, что текущий идентификатор не существует:

new DynamoDBSaveExpression()
    .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));

Я думал, что это может работать, но это не так:

    ExpectedAttributeValue expectedAttributeValue = new ExpectedAttributeValue(new AttributeValue(parent.toString()));
    dynamoDBSaveExpression = new DynamoDBSaveExpression()
            .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));
            .withExpectedEntry("id", expectedAttributeValue.withExists(true))
            .withConditionalOperator(ConditionalOperator.AND);

Редактировать

Существует RESTful API, который определяет POST для создания ресурса, и ресурс сохраняется как запись в таблице DynamoDB.

Ресурс допускает иерархию, которая указывается с помощью родительского элементаидентификатор.

Если родительский ресурс не найден, возвращается 404:

a. if parent identifier is set
b.     get parent resource from DynamoDB
c.     if parent not found
d.         return 404
e. persist resource in DynamoDB

Псевдокод не является атомарным.«b» может вернуть родителя, но другой поток / процесс может удалить его до «e».

Я надеялся, что выражение условия здесь поможет.Является ли библиотека транзакций единственным способом сделать это?Или данные должны быть смоделированы по-другому?

1 Ответ

0 голосов
/ 24 ноября 2018

Ответ ниже в основном устарел, но я оставляю его для потомков.DynamoDB теперь поддерживает транзакции , которые позволяют предоставлять выражение условия для другого значения ключа в той же или другой таблице.


Нет, выражение ConditionExpression не может просматривать любые элементы, крометекущий элемент, который сохраняется / обновляется / удаляется.

Обновление

Если возможно, можете ли вы спроектировать свои данные таким образом, чтобы что-либо не могло быть удалено?(Может быть, вы можете пометить его как устаревший.) Это полностью устраняет проблему, потому что если что-то существует, оно всегда будет существовать.

Если это невозможно, вы можете посмотреть на DynamoDBLockClient .Он предоставляет универсальный API распределенной блокировки, поддерживаемый DynamoDB.

Ваш новый псевдокод будет иметь вид

a. if parent identifier is set
b.     Acquire lock for parent identifier
c.     get parent resource from DynamoDB
d.     if parent not found
e.         Release lock
f.         return 404
g. persist resource in DynamoDB
h. Release lock

Кроме того, в любой операции, в которой вы удаляете что-либо, являющееся родительским идентификатором, вы должны получить блокировку этого родительского идентификатора перед его удалением.Если вы сделаете это, вы можете быть уверены, что родитель не будет удален в процессе создания дочернего элемента.

...