Transactions

Use db.transaction() for multi-step updates. On throw, the transaction is aborted and the error is re-thrown.

Example

async function transferFunds(
  senderId: string,
  recipientId: string,
  transferAmount: number
): Promise<TransferResult> {
  try {
    return await db.transaction(async (ctx, tx) => {
      const sender = await ctx.accounts.findActive({ id: senderId })
      const recipient = await ctx.accounts.findActive({ id: recipientId })

      if (!sender || !recipient) {
        throw TransferResult.InvalidAccount
      }

      if (sender.balance < transferAmount) {
        tx.abort()
        return TransferResult.InsufficientFunds
      }

      sender.balance -= transferAmount
      recipient.balance += transferAmount

      await sender.save()
      await recipient.save()

      tx.commit()
      return TransferResult.Success
    })
  } catch (error) {
    return isTransferResult(error) ? error : TransferResult.Error
  }
}

Use ctx (same shape as db.collections) for all reads and writes inside the transaction.