Bloqueio positivo com número de versão - Amazon DynamoDB

Bloqueio positivo com número de versão

O bloqueio positivo é uma estratégia para garantir que o item no lado do cliente que você está atualizando (ou excluindo) seja o mesmo que o item no Amazon DynamoDB. Se você usar essa estratégia, suas gravações de banco de dados serão protegidas contra substituição pelas gravações de outros e vice-versa.

Com o bloqueio positivo, cada item tem um atributo que serve como um número de versão. Se você recuperar um item de uma tabela, o aplicativo registrará o número da versão desse item. Você poderá atualizar o item somente se o número de versão no lado do servidor não tiver sido alterado. Se há uma incompatibilidade de versão, isso significa que alguém modificou o item antes de você. A tentativa de atualização falha, porque você tem uma versão obsoleta do item. Se isso acontecer, basta tentar novamente ao recuperar o item e tentar atualizá-lo. O bloqueio positivo impede que você substitua acidentalmente as alterações que foram feitas por outros. Também impede que outros substituam acidentalmente suas alterações.

Embora seja possível implementar a própria estratégia de bloqueio positivo, o AWS SDK for Java oferece a anotação @DynamoDBVersionAttribute. Na classe de mapeamento da sua tabela, você designa uma propriedade para armazenar o número da versão e a marca usando essa anotação. Quando um objeto é salvo, o item correspondente na tabela do DynamoDB terá um atributo que armazena o número da versão. O DynamoDBMapper atribui um número de versão quando você salvar o objeto pela primeira vez e incrementa automaticamente o número da versão sempre que você atualiza o item. Suas solicitações de atualização ou exclusão só serão bem-sucedidas se a versão do objeto no lado do cliente corresponder ao número de versão correspondente do item na tabela do DynamoDB.

ConditionalCheckFailedException será lançada se:

  • Você usar bloqueio positivo com @DynamoDBVersionAttribute e o valor de versão no servidor for diferente do valor no lado do cliente.

  • Você especificar suas próprias restrições condicionais ao salvar dados usando DynamoDBMapper com DynamoDBSaveExpression e ocorrer falha nessas restrições.

nota
  • As tabelas globais do DynamoDB usam uma reconciliação “último gravador ganha” entre as atualizações simultâneas. Se você usa tabelas globais, a política de último gravador ganha. Portanto, neste caso, a estratégia de bloqueio não funciona como esperado.

  • As operações de gravação transacional DynamoDBMapper não são compatíveis com expressões de condição e anotação @DynamoDBVersionAttribute no mesmo objeto. Se um objeto em uma gravação transacional for anotado com @DynamoDBVersionAttribute e também tiver uma expressão de condição, a SdkClientException será lançada.

Por exemplo, o código Java a seguir define uma classe CatalogItem que tem várias propriedades. A propriedade Version está marcada com a anotação @DynamoDBVersionAttribute.

exemplo
@DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private Integer id; private String title; private String ISBN; private Set<String> bookAuthors; private String someProp; private Long version; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer Id) { this.id = Id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBIgnore public String getSomeProp() { return someProp;} public void setSomeProp(String someProp) {this.someProp = someProp;} @DynamoDBVersionAttribute public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version;} }

Você pode aplicar a anotação @DynamoDBVersionAttribute a tipos anuláveis fornecidos pelas classes wrapper primitivas que fornecem um tipo que permite valor nulo, como Long e Integer.

O bloqueio positivo tem o seguinte impacto sobre estes métodos DynamoDBMapper:

  • save: para um novo item, DynamoDBMapper atribui um número de versão inicial 1. Se você recuperar um item, atualizar uma ou mais das suas propriedades e tentar salvar as alterações, a operação de salvamento será bem-sucedida somente se o número de versão no lado do cliente e no lado do servidor corresponderem. A classe DynamoDBMapper incrementa o número de versão automaticamente.

  • delete: o método delete usa um objeto como parâmetro, e DynamoDBMapper realiza uma verificação de versão antes de excluir o item. A verificação da versão pode ser desabilitada se DynamoDBMapperConfig.SaveBehavior.CLOBBER for especificado na solicitação.

    A implementação interna do bloqueio positivo em DynamoDBMapper usa o suporte a atualizações e exclusões condicionais fornecido pelo DynamoDB.

  • transactionWrite

    • Put: para um novo item, DynamoDBMapper atribui um número de versão inicial 1. Se você recuperar um item, atualizar uma ou mais das suas propriedades e tentar salvar as alterações, a operação Put será bem-sucedida somente se o número de versão no lado do cliente e no lado do servidor corresponder. A classe DynamoDBMapper incrementa o número de versão automaticamente.

    • Update: para um novo item, DynamoDBMapper atribui um número de versão inicial 1. Se você recuperar um item, atualizar uma ou mais das suas propriedades e tentar salvar as alterações, a operação Update será bem-sucedida somente se o número de versão no lado do cliente e no lado do servidor corresponder. A classe DynamoDBMapper incrementa o número de versão automaticamente.

    • Delete: o DynamoDBMapper realiza uma verificação de versão antes de excluir o item. A operação Delete só será bem-sucedida se o número de versão no lado do cliente e no lado do servidor corresponder.

    • ConditionCheck: a anotação @DynamoDBVersionAttribute não é compatível com operações ConditionCheck. Uma SdkClientException será lançada quando um item ConditionCheck for anotado com @DynamoDBVersionAttribute.

Desabilitar o bloqueio positivo

Para desabilitar o bloqueio positivo, você pode alterar o valor de enumeração DynamoDBMapperConfig.SaveBehavior de UPDATE para CLOBBER. Você pode fazer isso criando uma instância de DynamoDBMapperConfig que ignora a verificação de versão e usando essa instância para todas as suas solicitações. Para obter informações sobre DynamoDBMapperConfig.SaveBehavior e outros parâmetros DynamoDBMapper opcionais, consulte Definições de configuração opcionais para DynamoDBMapper .

Você também pode definir um comportamento de bloqueio somente para uma operação específica. Por exemplo, o seguinte trecho de código Java usa DynamoDBMapper para salvar um item de catálogo. Ele especifica DynamoDBMapperConfig.SaveBehavior adicionando o parâmetro DynamoDBMapperConfig opcional ao método save.

nota

O método transactionWrite não oferece suporte à configuração DynamoDBMapperConfig.SaveBehavior. A desabilitação do bloqueio positivo para transactionWrite é incompatível.

exemplo
DynamoDBMapper mapper = new DynamoDBMapper(client); // Load a catalog item. CatalogItem item = mapper.load(CatalogItem.class, 101); item.setTitle("This is a new title for the item"); ... // Save the item. mapper.save(item, new DynamoDBMapperConfig( DynamoDBMapperConfig.SaveBehavior.CLOBBER));