sqs-to-lambda-async
Version:
SQS To Lambda (Async)
191 lines (156 loc) • 6.29 kB
JavaScript
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _awsSdk = require('aws-sdk');
var _awsSdk2 = _interopRequireDefault(_awsSdk);
var _pForever = require('p-forever');
var _pForever2 = _interopRequireDefault(_pForever);
var _pSettle = require('p-settle');
var _pSettle2 = _interopRequireDefault(_pSettle);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var debug = require('debug')('sqs-to-lambda-async');
var sqs = undefined;
var lambda = undefined;
function handleMessage() {
var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var kwargs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return new Promise(function (resolve, reject) {
debug(`Incoming message: ${JSON.stringify(message)}`);
var MessageFormatter = kwargs.MessageFormatter,
FunctionName = kwargs.FunctionName,
DeleteMessage = kwargs.DeleteMessage,
QueueUrl = kwargs.QueueUrl;
if (_lodash2.default.isEmpty(message)) {
return resolve('Message is empty');
}
if (typeof MessageFormatter !== 'function') {
return reject('Message formatter is not a function.');
}
if (typeof FunctionName !== 'string') {
return reject('Function ARN not valid.');
}
var Payload = JSON.stringify(MessageFormatter(message));
debug(`Invoking lambda ${FunctionName}`);
return lambda.invoke({
InvocationType: 'Event',
FunctionName,
Payload
}, function (err, res) {
if (err) {
return reject(err);
}
if (DeleteMessage) {
return sqs.deleteMessage({
QueueUrl,
ReceiptHandle: message.ReceiptHandle
}, function (deleteMessageErr) {
return deleteMessageErr ? reject(deleteMessageErr) : resolve(res);
});
}
return resolve(res);
});
});
}
function receiveMessages() {
var kwargs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return new Promise(function (resolve) {
var recieveArgs = _lodash2.default.chain(kwargs).pick(['MaxNumberOfMessages', 'QueueUrl', 'WaitTimeSeconds', 'VisibilityTimeout']).pickBy().value();
sqs.receiveMessage(recieveArgs, function (err, data) {
var messages = _lodash2.default.isArray(data.Messages) ? data.Messages : [];
(0, _pSettle2.default)(messages.map(function (msg) {
return handleMessage(msg, kwargs);
})).then(resolve);
});
});
}
function handleLambdaCallback(kwargs) {
var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var PostInvoke = kwargs.PostInvoke;
if (_lodash2.default.isArray(values) && _lodash2.default.isFunction(PostInvoke)) {
try {
values.forEach(function () {
var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return obj.isFulfilled ? PostInvoke(undefined, obj.value) : PostInvoke(obj.reason || new Error('Unknown lambda error.'));
});
} catch (err) {
_lodash2.default.noop();
}
}
}
function createReader(kwargs) {
debug(`Creating reader with args: ${JSON.stringify(kwargs)}`);
var readerIndex = -1;
return (0, _pForever2.default)(function (previousVal) {
handleLambdaCallback(kwargs, previousVal);
readerIndex++;
return readerIndex < kwargs.NumberOfRuns ? receiveMessages(kwargs) : _pForever2.default.end;
}, []);
}
function setupServices() {
debug('Setting up AWS services');
sqs = new _awsSdk2.default.SQS();
lambda = new _awsSdk2.default.Lambda();
}
module.exports = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
var mapping = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var mappingIsValid, readers;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
debug(`Initializing with mapping ${JSON.stringify(mapping)}`);
_context.prev = 1;
mappingIsValid = _lodash2.default.chain(mapping).map(function () {
var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return _lodash2.default.every([obj.functionName, obj.queueUrl]);
}).every().value();
if (!(!_lodash2.default.isArray(mapping) || !mapping.length || !mappingIsValid)) {
_context.next = 5;
break;
}
throw new Error(`Your sqs/lambda mapping object must be an array of objects like {functionName: foo, queueUrl: bar}, got ${JSON.stringify(mapping)}`);
case 5:
setupServices();
readers = mapping.map(function (obj) {
var msgArgs = _lodash2.default.chain(obj).mapKeys(function (val, key) {
return _lodash2.default.camelCase(key);
}).defaults({
maxNumberOfMessages: 5,
waitTimeSeconds: 5,
messageFormatter: function messageFormatter(a) {
return a;
},
numberOfRuns: Infinity,
deleteMessage: false,
postInvoke: _lodash2.default.noop
}).mapKeys(function (val, key) {
return _lodash2.default.upperFirst(key);
}).value();
return createReader(msgArgs);
});
_context.next = 9;
return Promise.all(readers);
case 9:
_context.next = 14;
break;
case 11:
_context.prev = 11;
_context.t0 = _context['catch'](1);
throw _context.t0;
case 14:
case 'end':
return _context.stop();
}
}
}, _callee, this, [[1, 11]]);
}));
function run() {
return _ref.apply(this, arguments);
}
return run;
}();
;