UNPKG

@mcma/aws-dynamodb

Version:

Node module with code for using DynamoDB as the backing data storage for MCMA API handlers and workers.

86 lines (85 loc) 3.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamoDbMutex = void 0; const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb"); const data_1 = require("@mcma/data"); class DynamoDbMutex extends data_1.DocumentDatabaseMutex { dc; tableDescription; _versionId; constructor(dc, tableDescription, mutexName, mutexHolder, lockTimeout = 300000, logger) { super(mutexName, mutexHolder, lockTimeout, logger); this.dc = dc; this.tableDescription = tableDescription; this._versionId = (Math.random() * 2147483648 << 0).toString(); } get versionId() { return this._versionId; } generateTableKey() { const Key = {}; if (this.tableDescription.keyNames.sort) { Key[this.tableDescription.keyNames.partition] = "Mutex"; Key[this.tableDescription.keyNames.sort] = this.mutexName; } else { Key[this.tableDescription.keyNames.partition] = "Mutex-" + this.mutexName; } return Key; } generateTableItem() { const tableItem = { mutexHolder: this.mutexHolder, versionId: this.versionId, timestamp: Date.now() }; if (this.tableDescription.keyNames.sort) { tableItem[this.tableDescription.keyNames.partition] = "Mutex"; tableItem[this.tableDescription.keyNames.sort] = this.mutexName; } else { tableItem[this.tableDescription.keyNames.partition] = "Mutex-" + this.mutexName; } return tableItem; } async getLockData() { const record = await this.dc.send(new lib_dynamodb_1.GetCommand({ TableName: this.tableDescription.tableName, Key: this.generateTableKey(), ConsistentRead: true })); // sanity check which removes the record from DynamoDB in case it has incompatible structure. Only possible // if modified externally, but this could lead to a situation where the lock would never be acquired. if (record.Item && (!record.Item.mutexHolder || !record.Item.versionId || !record.Item.timestamp)) { await this.dc.send(new lib_dynamodb_1.DeleteCommand({ TableName: this.tableDescription.tableName, Key: this.generateTableKey(), })); delete record.Item; } return record.Item; } async putLockData() { const value = { TableName: this.tableDescription.tableName, Item: this.generateTableItem(), Expected: { resource_id: { Exists: false } } }; value.Expected[this.tableDescription.keyNames.partition] = { Exists: false }; await this.dc.send(new lib_dynamodb_1.PutCommand(value)); } async deleteLockData(versionId) { await this.dc.send(new lib_dynamodb_1.DeleteCommand({ TableName: this.tableDescription.tableName, Key: this.generateTableKey(), ConditionExpression: "#v = :v", ExpressionAttributeNames: { "#v": "versionId" }, ExpressionAttributeValues: { ":v": versionId } })); } } exports.DynamoDbMutex = DynamoDbMutex;