Intermediário3 min de leitura

DynamoDB ReturnValues: Obtenha o Item Antigo ou Novo de uma Escrita

Por padrão, uma escrita no DynamoDB não retorna nada além do sucesso. Mas muitas vezes você precisa dos dados ao redor da escrita — o valor antes de você mudá-lo, ou o valor novo depois. A solução ingênua é um segundo GetItem, que é uma ida e volta extra e uma condição de corrida: outra pessoa pode escrever no meio. O DynamoDB evita os dois com o parâmetro ReturnValues, que devolve o item antigo ou novo atomicamente como parte da própria escrita.

O que o ReturnValues faz no DynamoDB?

O ReturnValues instrui uma escrita no DynamoDB a devolver o item como parte da mesma chamada, dispensando um segundo GetItem e a condição de corrida que ele cria. PutItem e DeleteItem aceitam NONE ou ALL_OLD; o UpdateItem aceita todos os cinco (NONE, ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW), retornando os valores antigos ou novos de forma atômica.

  • ReturnValues retorna o item como parte da escrita — sem segunda leitura, sem corrida.
  • NONE (padrão) — não retorna nada.
  • ALL_OLD — o item inteiro como estava antes da escrita.
  • UPDATED_OLD — apenas os atributos que a atualização mudou, os valores de antes.
  • ALL_NEW — o item inteiro depois da escrita.
  • UPDATED_NEW — apenas os atributos alterados, os valores de depois.
  • PutItem/DeleteItem aceitam apenas NONE ou ALL_OLD; o UpdateItem aceita todos os cinco.

O problema: você precisa do valor que acabou de sobrescrever

Digamos que você opere um suporte e um atendente mude o status de um chamado de open para pending. Seu log de auditoria precisa registrar qual era o status antes da mudança. Sem ReturnValues, você faria:

  1. GetItem para ler o status atual,
  2. UpdateItem para definir o novo.

Entre os passos 1 e 2, outro atendente poderia mudar o status — agora seu log de auditoria registra um valor "de antes" desatualizado. Pior, são duas chamadas para uma operação lógica. O ReturnValues reduz isso a um único UpdateItem atômico que retorna o status antigo exatamente como ele estava no momento da escrita.

As cinco opções, e quando usar cada uma

O UpdateItem suporta o conjunto completo; a escolha é qual fatia do item e qual lado da escrita você precisa:

ReturnValuesRetornaUse quando
NONEnadavocê não precisa do item de volta (padrão)
ALL_OLDitem inteiro, pré-escritaauditoria / "o que eu acabei de substituir?"
UPDATED_OLDatributos alterados, pré-escritavocê só se importa com os campos que tocou
ALL_NEWitem inteiro, pós-escritavocê precisa do item completo e atualizado para devolver a quem chamou
UPDATED_NEWatributos alterados, pós-escritareler um contador/valor que você acabou de incrementar

UPDATED_NEW é o herói do dia a dia: incremente um contador com uma update expression e releia o novo total na mesma chamada, sem corrida. Para a auditoria do chamado de suporte, ALL_OLD (ou UPDATED_OLD se você só registra o campo de status) captura o estado pré-mudança atomicamente.

Note a assimetria: PutItem e DeleteItem só suportam NONE e ALL_OLD — não há valor "novo" a retornar num delete, e o valor novo de um put é só o que você enviou. Apenas o UpdateItem, que muta no lugar, oferece os cinco. A AWS documenta a matriz exata.

Escrevendo a atualização no DynoTable

Monte o UpdateItem e sua update expression visualmente com o construtor de expressões do DynamoDB — ele emite a cláusula SET/ADD mais os mapas de nomes e valores de atributos. No app, o DynoTable mostra o item resultante depois que uma escrita preparada recebe commit, então você vê o novo estado diretamente.

Revisando a alteração preparada de um item no DynoTable — os valores antigo e novo antes de o update ser confirmado.
Revisando a alteração preparada de um item no DynoTable — os valores antigo e novo antes de o update ser confirmado.

Armadilhas e próximos passos

  • Não faça GetItem-depois-escrita para ler em torno de uma mudança — é uma ida e volta e uma corrida; use ReturnValues.
  • UPDATED_* retorna apenas os atributos tocados — se você precisa do item inteiro, use ALL_*.
  • PutItem/DeleteItem não conseguem retornar valores novos — apenas NONE/ALL_OLD.
  • ReturnValues não substitui uma condição — para proteger uma escrita, adicione uma condition expression; para reler o efeito dela, use ReturnValues. Eles se combinam.
  • Relacionado: update expressions, contadores atômicos.

Quer fazer edições e ver o antes/depois sem programar duas chamadas? Baixe o DynoTable e edite seus itens diretamente.

Atualizado