Skip to content

Instantly share code, notes, and snippets.

@busticated
Last active November 12, 2023 01:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save busticated/c90f099c9b5a12c9111ce1d34afed466 to your computer and use it in GitHub Desktop.
Save busticated/c90f099c9b5a12c9111ce1d34afed466 to your computer and use it in GitHub Desktop.
How to use ARC's / AWS' `client._doc.transactWrite()` method?
// Trying to implement field uniqueness as described in:
// https://aws.amazon.com/blogs/database/simulating-amazon-dynamodb-unique-constraints-using-transactions/
// Using:
// mocha: v10.2.0
// node: v18.18.2
// macOS: Sonoma v14.1 (23B74)
import sinon from 'sinon'; // sinon@17.0.1
import { expect } from 'chai'; // chai@4.3.10
import sandbox from '@architect/sandbox'; // @architect/sandbox@5.9.2
import arc from '@architect/functions'; // @architect/functions@7.0.0
describe('DynamoDB: UnknownOperationException: UnknownError', () => {
let tables; // b/c describe() doesn't support `async` callbacks :(
before(async () => {
await sandbox.start({ quiet: true });
tables = await arc.tables();
});
afterEach(() => {
sinon.restore();
});
after(async () => {
await sandbox.end();
});
describe('Using `.transactWrite()`', () => {
it('Starts with empty db', async () => {
const records = await tables.chocotaco.scan({});
expect(records.Count).to.equal(0);
expect(records.Items).to.eql([]);
expect(records['$metadata'].httpStatusCode).to.equal(200);
});
it('Creates new record', async () => {
const client = await arc.tables();
const TableName = 'chocotaco';
await client._doc.transactWrite({
TransactItems: [
{
Put: {
TableName,
ConditionExpression: 'attribute_not_exists(pk)',
Item: {
pk: 'my-fake-pk',
sk: 'my-fake-sk',
username: 'fake-username',
email: 'fake@example.com'
}
}
},
{
Put: {
TableName,
ConditionExpression: 'attribute_not_exists(pk)',
Item: {
pk: 'unique-username:fake-username',
sk: 'unique-username'
}
}
},
{
Put: {
TableName,
ConditionExpression: 'attribute_not_exists(pk)',
Item: {
pk: 'unique-email:fake@example.com',
sk: 'unique-email'
}
}
}
]
});
});
});
it('Delete record', async () => {
const client = await arc.tables();
const TableName = 'chocotaco';
await client._doc.transactWrite({
TransactItems: [
{ Delete: { TableName, Key: { email: 'fake@example.com' } } },
{ Delete: { TableName, Key: { email: 'alsofake@example.com' } } },
]
});
});
});
>>eval $(cat .env) npm run test:unit
> knuckles@0.0.0 test:unit
> mocha './src/**/*.test.?(m)js'
DynamoDB: UnknownOperationException: UnknownError
Using `.transactWrite()`
✔ Starts with empty db (509ms)
1) Creates new record
2) Delete record
1 passing (1s)
2 failing
1) DynamoDB: UnknownOperationException: UnknownError
Using `.transactWrite()`
Creates new record:
UnknownOperationException: UnknownError
at throwDefaultError (node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22)
at /Users/me/code/bust/knuckles/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39
at de_TransactWriteItemsCommandError (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:2239:20)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /Users/me/code/bust/knuckles/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/lib-dynamodb/dist-cjs/baseCommand/DynamoDBDocumentClientCommand.js:29:34
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20
at async /Users/me/code/bust/knuckles/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:7:26
at async Context.<anonymous> (file:///Users/me/code/bust/knuckles/src/shared/db/client/example.test.mjs:39:4)
2) DynamoDB: UnknownOperationException: UnknownError
Using `.transactWrite()`
Delete record:
UnknownOperationException: UnknownError
at throwDefaultError (node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22)
at /Users/me/code/bust/knuckles/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39
at de_TransactWriteItemsCommandError (node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:2239:20)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /Users/me/code/bust/knuckles/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/lib-dynamodb/dist-cjs/baseCommand/DynamoDBDocumentClientCommand.js:29:34
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20
at async /Users/me/code/bust/knuckles/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46
at async /Users/me/code/bust/knuckles/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:7:26
at async Context.<anonymous> (file:///Users/me/code/bust/knuckles/src/shared/db/client/example.test.mjs:80:4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment