Penulisan Bersyarat DynamoDB di Node.js (AWS SDK v3)
Bagian menarik dari penulisan bersyarat di AWS SDK v3 bukanlah ConditionExpression-nya, yang bekerja sama di mana-mana dan dibahas di condition expression DynamoDB. Yang menarik adalah jalur kegagalannya: v3 menyerahkan item yang kalah kepada Anda lewat error yang dilempar — kalau Anda memintanya — dan tidak memberi apa-apa kalau Anda tidak meminta.
Kode
import {DynamoDBClient, UpdateItemCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
// Update the item only if nobody changed it since we read version 7.
const command = new UpdateItemCommand({
TableName: 'Music',
Key: {
Artist: {S: 'Arturo Sandoval'},
SongTitle: {S: 'Cubano Chant'}
},
UpdateExpression: 'SET #upd0 = :updValue0, #version = :newVersion',
ConditionExpression: 'attribute_exists(#cond0) AND #version = :expectedVersion',
ExpressionAttributeNames: {
'#upd0': 'Genre',
'#version': 'Version',
'#cond0': 'Artist'
},
ExpressionAttributeValues: {
':updValue0': {S: 'Latin Jazz'},
':expectedVersion': {N: '7'},
':newVersion': {N: '8'}
},
ReturnValuesOnConditionCheckFailure: 'ALL_OLD'
});
try {
await client.send(command);
console.log('Updated to version 8');
} catch (err) {
if (err.name === 'ConditionalCheckFailedException') {
// With ReturnValuesOnConditionCheckFailure: 'ALL_OLD', the current item
// rides back on the exception — no extra read to see what beat you.
console.log('Lost the race — item is now:', err.Item);
} else {
throw err;
}
}Penjelasan
- Pemeriksaan yang gagal adalah error yang dilempar, bukan field status. v3 menolak promise-nya, jadi jalur penulisan dan jalur kalah balapan adalah cabang yang berbeda.
err.name === 'ConditionalCheckFailedException'adalah pembedanya; apa pun selain itu harus dilempar ulang, dan untuk itulahelsedi blok kode ada. Telan seluruhcatchdan Anda diam-diam telah mengubah sebuah throttle menjadi no-op. ReturnValuesOnConditionCheckFailureadalah satu-satunya cara melihat siapa yang mendahului Anda. Tanpa itu, error-nya hanya membawa pesan dan tidak lebih, dan Anda kembali keGetItemyang sebenarnya tak perlu. Referensi API menetapkan nilai validnya sebagaiALL_OLD | NONEdan menegaskan bahwa ia tidak menghabiskan kapasitas baca.err.Itemadalah mapAttributeValuementah, bentuknya sama denganKeyyang Anda kirim, bukan JavaScript biasa. Lewatkan melaluiunmarshalldari@aws-sdk/util-dynamodbsebelum Anda membandingkanVersiondengan sebuah angka, atau Anda akan membandingkannya dengan{N: '9'}.- Penulisan yang gagal tetap ditagih. Developer Guide menyatakan dengan tegas bahwa kondisi yang bernilai false tetap menghabiskan write capacity, ditakar dari yang lebih besar antara item lama dan item baru. Loop retry pada hot key adalah baris nyata di tagihan, jadi batasi jumlah percobaannya.
- Setiap nama di blok kode di-alias (
#version→Version,#cond0→Artist) karena Expression Builder yang menghasilkannya meng-alias tanpa syarat. Itu lebih berat dari yang diperlukan di sini dan tidak pernah salah — itulah pertukaran yang ia ambil.
Membaca salinan pihak yang kalah dari exception
Setel Version tersimpan ke 9 lalu jalankan blok kode yang mengharapkan 7 itu. DynamoDB Local 3.3.0 melempar error, dan error yang tertangkap membawa:
err.name ConditionalCheckFailedException
err.message The conditional request failed
err.$metadata.httpStatusCode 400
err.Item {
Artist: { S: 'Arturo Sandoval' },
Year: { N: '1994' },
Version: { N: '9' },
SongTitle: { S: 'Cubano Chant' },
AlbumTitle: { S: 'Danzon' }
}Version: 9 itulah intinya. Percobaan ulang bisa langsung kembali ke update dengan :expectedVersion disetel ke 9, tanpa pembacaan tambahan dan tanpa celah bagi penulis ketiga untuk menyelinap di antara GetItem dan percobaan ulang Anda.
Hapus ReturnValuesOnConditionCheckFailure dari command yang sama lalu jalankan ulang. name sama, message sama, 400 sama, dan err.Item bernilai undefined. Tak ada yang memperingatkan Anda: parameternya opsional, ketiadaannya bukan error, dan kode yang membaca err.Item cuma mulai mencatat undefined di produksi.
Perhatikan juga bahwa 400 di sini tidak berarti permintaannya cacat. ValidationException dan ConditionalCheckFailedException berbagi kode status yang sama, dan hanya salah satunya yang merupakan bug — itulah sebabnya percabangannya pada err.name dan tidak pernah pada status.
Untuk menyaksikan sebuah kondisi berhasil dan gagal terhadap data Anda sendiri, dengan expression yang dituliskan untuk Anda alih-alih diketik, unduh DynoTable.
Contoh terkait
- Penulisan bersyarat DynamoDB di Python — optimistic lock yang sama dengan boto3.
- Penulisan bersyarat DynamoDB dengan AWS CLI — optimistic lock yang sama dari shell.
- DynamoDB PutItem di Node.js — put
attribute_not_existsyang hanya membuat. - Condition expression DynamoDB — setiap fungsi, lengkap dengan polanya.
- Menegakkan keunikan pada banyak atribut — kondisi + transaksi digabungkan.
- DynamoDB ConditionalCheckFailedException — ketika pemeriksaan yang gagal memang diharapkan, dan cara menanganinya dengan murah.
Referensi
- UpdateItem — Amazon DynamoDB API Reference
- Condition expressions — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.