Skip to main content
Version: v2

Transactions

TransactGet​

DynamoDB-Toolbox exposes the GetTransaction actions to perform TransactGetItems operations.

TransactWrite​

DynamoDB-Toolbox exposes the following actions to perform TransactWriteItems operations:

TransactWriteItems operations can affect multiple items, so transactions do not have a .send(...) method. Instead, they should be performed via the dedicated execute function:

import { execute } from 'dynamodb-toolbox/entity/actions/transactWrite'

const put = PokemonEntity.build(PutTransaction).item(...)
const update = PokemonEntity.build(UpdateTransaction).item(...)
const del = PokemonEntity.build(DeleteTransaction).key(...)
const check = PokemonEntity.build(ConditionCheck).key(...).condition(...)

await execute(put, update, del, check, ...otherTransactions)

// Using the `as const` statement also works
const transactions = [put, update, del, ...] as const
await execute(...transactions)
warning

Only one transaction per item is supported. For instance, you cannot run a ConditionCheck and an UpdateTransaction on the same item: You can, however, condition the UpdateTransaction itself.

Options​

The execute function accepts an additional object as a first argument for operation-level options, as well as DocumentClient options such as abortSignal:

await execute(options, ...writeTransactions)

Available options (see the DynamoDB documentation for more details):

OptionTypeDefaultDescription
capacityCapacityOption"NONE"Determines the level of detail about provisioned or on-demand throughput consumption that is returned in the response.

Possible values are "NONE", "TOTAL" and "INDEXES".
metricsMetricsOption"NONE"Determines whether item collection metrics are returned.

Possible values are "NONE" and "SIZE".
clientRequestTokenstring-Providing a clientRequestToken makes the execution idempotent, meaning that multiple identical calls have the same effect as one single call.
documentClientDocumentClient-By default, the documentClient attached to the Table of the first WriteTransaction is used to execute the operation.

Use this option to override this behavior.
Examples
const { ConsumedCapacity } = await execute(
{ capacity: 'TOTAL' },
...writeTransactions
)

Response​

The data is returned using the same response syntax as the DynamoDB TransactWriteItems API, with an additional ToolboxItems property, which allows you to retrieve the items generated by DynamoDB-Toolbox in PutTransactions and UpdateTransactions:

const { ToolboxItems } = await execute(
putTransaction,
deleteTransaction,
conditionCheck,
updateTransaction
)

const [
putPokemon,
// πŸ‘‡ Both undefined
_,
__,
updatedPokemon
] = ToolboxItems

// πŸ‘‡ Great for auto-generated attributes
const createdTimestamp = putPokemon.created
const modifiedTimestamp = updatedPokemon.modified

Error handling​

If a transaction is rejected because one of its conditions failed, DynamoDB throws a TransactionCanceledException with a CancellationReasons array, positionally aligned with the transactions you provided. Any reason whose transaction was set with returnValuesOnConditionFalse: 'ALL_OLD' carries the offending item.

DynamoDB-Toolbox can enrich each such reason with a FormattedItem property, containing the formatted item of the transaction's entity. Use the assertTransactionCancelled assertion or the isTransactionCancelled type guard to read them in a type-safe way:

import {
execute,
isTransactionCancelled,
assertTransactionCancelled
} from 'dynamodb-toolbox/entity/actions/transactWrite'

const transactions = [
PokemonEntity.build(PutTransaction)
.item(pikachu)
.options({
condition: { attr: 'pokemonId', exists: false },
returnValuesOnConditionFalse: 'ALL_OLD'
}),
TrainerEntity.build(UpdateTransaction).item(ash)
] as const // πŸ‘ˆ Type transactions as tuples

try {
await execute(...transactions)
} catch (error) {
// πŸ‘‡ Rethrow other error classes + narrow `error` type
assertTransactionCancelled(error, ...transactions)
const reasons = error.CancellationReasons
const prevPikachu = reasons?.[0]?.FormattedItem // πŸ™Œ Correctly typed

// ...OR use a type guard
if (isTransactionCancelled(error, ...transactions)) {
const reasons = error.CancellationReasons
const prevPikachu = reasons?.[0]?.FormattedItem // πŸ™Œ Correctly typed
}
}
warning

CancellationReasons are matched to transactions by position. Make sure to pass assertTransactionCancelled or isTransactionCancelled the same array/tuple you passed to execute, otherwise the positional typing will be incorrect.

note

FormattedItem is always optional: Formatting is best-effort and applied per-reason, so a reason whose item cannot be formatted by its entity (e.g. an invalid item) is left with no FormattedItem property.