UNPKG

@orchestrated-io/cqrs-domain

Version:

Node-cqrs-domain is a node.js module based on node-eventstore. It can be very useful as domain component if you work with (d)ddd, cqrs, eventdenormalizer, host, etc.

260 lines (234 loc) 6.47 kB
var util = require('util'), Lock = require('../base'), _ = require('lodash'), async = require('async'), aws = Lock.use('aws-sdk'); function DynamoDB(options) { var awsConf = { region: 'ap-southeast-2', endpointConf: {} }; if (process.env['AWS_DYNAMODB_ENDPOINT']) { awsConf.endpointConf = { endpoint: process.env['AWS_DYNAMODB_ENDPOINT'] }; } this.options = _.defaults(options, awsConf); var defaults = { lockTableName: 'aggregatelock', ReadCapacityUnits: 1, WriteCapacityUnits: 3 }; this.options = _.defaults(this.options, defaults); } util.inherits(DynamoDB, Lock); _.extend(DynamoDB.prototype, { connect: function(callback) { var self = this; self.client = new aws.DynamoDB(self.options.endpointConf); self.documentClient = new aws.DynamoDB.DocumentClient({ service: self.client }); self.isConnected = true; var createAggregatelockTable = function(done) { createTableIfNotExists( self.client, AggregatelockTableDefinition(self.options), done ); }; createAggregatelockTable(function(err) { if (err) { if (callback) callback(err); } else { self.emit('connect'); if (callback) callback(null, self); } }); }, disconnect: function(callback) { this.emit('disconnect'); if (callback) callback(null); }, reserve: function(workerId, aggregateId, callback) { var self = this; var params = { TableName: self.options.lockTableName, Item: { aggregateId: aggregateId, workerId: workerId, timeStamp: new Date().getTime() } }; self.documentClient.put(params, function(err, data) { if (callback) callback(err); }); }, getAll: function(aggregateId, callback) { var self = this; if (callback) { var params = { TableName: self.options.lockTableName, KeyConditionExpression: '#aggrId = :a', ExpressionAttributeNames: { '#aggrId': 'aggregateId' }, ExpressionAttributeValues: { ':a': aggregateId } }; self.documentClient.query(params, function(err, data) { var res = []; if (err) { if (callback) callback(err); return; } res = _.sortBy(data.Items, 'timeStamp'); if (callback) callback(null, _.map(res, function(r){ return r.workerId})); }); } }, resolve: function(aggregateId, callback) { var self = this; var queryParams = { TableName: self.options.lockTableName, KeyConditionExpression: '#aggrId = :a', ExpressionAttributeNames: { '#aggrId': 'aggregateId' }, ExpressionAttributeValues: { ':a': aggregateId } }; self.documentClient.query(queryParams, function(err, data) { if (err) { if (callback) callback(err); return; } async.each( data.Items, function(item, deleteCallback) { var params = { TableName: self.options.lockTableName, Key: { aggregateId: item.aggregateId, workerId: item.workerId } }; self.documentClient.delete(params, function(deleteErr, data) { if (deleteErr) { return deleteCallback(deleteErr); } deleteCallback(null, data); }); }, function(err) { if (callback) callback(err); } ); }); }, clear: function(callback) { var self = this; var query = { TableName: self.options.lockTableName }; self.documentClient.scan(query, function(err, data) { if (err) { if (callback) callback(err); return; } async.each( data.Items, function(item, callback) { var params = { TableName: self.options.lockTableName, Key: { aggregateId: item.aggregateId, workerId: item.workerId } }; self.documentClient.delete(params, function(error, response) { callback(error); }); }, function(error) { if (callback) callback(error); } ); }); } }); function AggregatelockTableDefinition(opts) { var def = { TableName: opts.lockTableName, KeySchema: [ { AttributeName: 'aggregateId', KeyType: 'HASH' }, { AttributeName: 'workerId', KeyType: 'RANGE' } ], AttributeDefinitions: [ { AttributeName: 'aggregateId', AttributeType: 'S' }, { AttributeName: 'workerId', AttributeType: 'S' } ], ProvisionedThroughput: { ReadCapacityUnits: opts.ReadCapacityUnits, WriteCapacityUnits: opts.WriteCapacityUnits } }; return def; } var createTableIfNotExists = function(client, params, callback) { var exists = function(p, cbExists) { client.describeTable({ TableName: p.TableName }, function(err, data) { if (err) { if (err.code === 'ResourceNotFoundException') { cbExists(null, { exists: false, definition: p }); } else { cbExists(err); } } else { cbExists(null, { exists: true, description: data }); } }); }; var create = function(r, cbCreate) { if (!r.exists) { client.createTable(r.definition, function(err, data) { if (err) { cbCreate(err); } else { cbCreate(null, { Table: { TableName: data.TableDescription.TableName, TableStatus: data.TableDescription.TableStatus } }); } }); } else { cbCreate(null, r.description); } }; var active = function(d, cbActive) { var status = d.Table.TableStatus; async.until( function() { return status === 'ACTIVE'; }, function(cbUntil) { client.describeTable({ TableName: d.Table.TableName }, function( err, data ) { if (err) { cbUntil(err); } else { status = data.Table.TableStatus; setTimeout(cbUntil, 1000); } }); }, function(err, r) { if (err) { return cbActive(err); } cbActive(null, r); } ); }; async.compose(active, create, exists)(params, function(err, result) { if (err) callback(err); else callback(null, result); }); }; module.exports = DynamoDB;