@comicrelief/lambda-wrapper 1.10.1 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -47
- package/dist/core/DependencyAwareClass.d.ts +15 -0
- package/dist/core/DependencyAwareClass.d.ts.map +1 -0
- package/dist/core/DependencyAwareClass.js +20 -0
- package/dist/core/DependencyAwareClass.js.map +1 -0
- package/dist/core/DependencyInjection.d.ts +62 -0
- package/dist/core/DependencyInjection.d.ts.map +1 -0
- package/dist/core/DependencyInjection.js +83 -0
- package/dist/core/DependencyInjection.js.map +1 -0
- package/dist/core/LambdaWrapper.d.ts +61 -0
- package/dist/core/LambdaWrapper.d.ts.map +1 -0
- package/dist/core/LambdaWrapper.js +126 -0
- package/dist/core/LambdaWrapper.js.map +1 -0
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +21 -0
- package/dist/core/config.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -162
- package/dist/index.js.map +1 -0
- package/dist/models/ResponseModel.d.ts +91 -0
- package/dist/models/ResponseModel.d.ts.map +1 -0
- package/dist/models/ResponseModel.js +100 -0
- package/dist/models/ResponseModel.js.map +1 -0
- package/dist/models/SQSMessageModel.d.ts +46 -0
- package/dist/models/SQSMessageModel.d.ts.map +1 -0
- package/dist/models/SQSMessageModel.js +65 -0
- package/dist/models/SQSMessageModel.js.map +1 -0
- package/dist/models/StatusModel.d.ts +40 -0
- package/dist/models/StatusModel.d.ts.map +1 -0
- package/dist/models/StatusModel.js +50 -0
- package/dist/models/StatusModel.js.map +1 -0
- package/dist/services/BaseConfigService.d.ts +101 -0
- package/dist/services/BaseConfigService.d.ts.map +1 -0
- package/dist/services/BaseConfigService.js +180 -0
- package/dist/services/BaseConfigService.js.map +1 -0
- package/dist/services/HTTPService.d.ts +29 -0
- package/dist/services/HTTPService.d.ts.map +1 -0
- package/dist/services/HTTPService.js +55 -0
- package/dist/services/HTTPService.js.map +1 -0
- package/dist/services/LoggerService.d.ts +102 -0
- package/dist/services/LoggerService.d.ts.map +1 -0
- package/dist/services/LoggerService.js +258 -0
- package/dist/services/LoggerService.js.map +1 -0
- package/dist/services/RequestService.d.ts +119 -0
- package/dist/services/RequestService.d.ts.map +1 -0
- package/dist/services/RequestService.js +293 -0
- package/dist/services/RequestService.js.map +1 -0
- package/dist/services/SQSService.d.ts +181 -0
- package/dist/services/SQSService.d.ts.map +1 -0
- package/dist/services/SQSService.js +366 -0
- package/dist/services/SQSService.js.map +1 -0
- package/dist/services/TimerService.d.ts +22 -0
- package/dist/services/TimerService.d.ts.map +1 -0
- package/dist/services/TimerService.js +40 -0
- package/dist/services/TimerService.js.map +1 -0
- package/dist/utils/LambdaTermination.d.ts +14 -0
- package/dist/utils/LambdaTermination.d.ts.map +1 -0
- package/dist/utils/LambdaTermination.js +23 -0
- package/dist/utils/LambdaTermination.js.map +1 -0
- package/dist/utils/PromisifiedDelay.d.ts +17 -0
- package/dist/utils/PromisifiedDelay.d.ts.map +1 -0
- package/dist/utils/PromisifiedDelay.js +48 -0
- package/dist/utils/PromisifiedDelay.js.map +1 -0
- package/package.json +29 -19
- package/.eslintrc.yml +0 -16
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/main.yml +0 -74
- package/babel.config.js +0 -13
- package/dist/Config/Dependencies.js +0 -40
- package/dist/DependencyInjection/DependencyAware.class.js +0 -47
- package/dist/DependencyInjection/DependencyInjection.class.js +0 -131
- package/dist/Model/CloudEvent.model.js +0 -156
- package/dist/Model/Model.model.js +0 -45
- package/dist/Model/Response.model.js +0 -150
- package/dist/Model/SQS/MarketingPreference.constraints.json +0 -28
- package/dist/Model/SQS/MarketingPreference.model.js +0 -641
- package/dist/Model/SQS/Message.model.js +0 -104
- package/dist/Model/Status.model.js +0 -82
- package/dist/Service/BaseConfig.service.js +0 -225
- package/dist/Service/HTTP.service.js +0 -70
- package/dist/Service/Logger.service.js +0 -293
- package/dist/Service/Request.service.js +0 -341
- package/dist/Service/SQS.service.js +0 -420
- package/dist/Service/Timer.service.js +0 -55
- package/dist/Wrapper/LambdaTermination.js +0 -39
- package/dist/Wrapper/LambdaWrapper.js +0 -164
- package/dist/Wrapper/PromisifiedDelay.js +0 -59
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = exports.SQS_PUBLISH_FAILURE_MODES = exports.SQS_OFFLINE_MODES = void 0;
|
|
7
|
-
|
|
8
|
-
var _alai = _interopRequireDefault(require("alai"));
|
|
9
|
-
|
|
10
|
-
var _each = _interopRequireDefault(require("async/each"));
|
|
11
|
-
|
|
12
|
-
var _awsSdk = _interopRequireDefault(require("aws-sdk"));
|
|
13
|
-
|
|
14
|
-
var _uuid = require("uuid");
|
|
15
|
-
|
|
16
|
-
var _Dependencies = require("../Config/Dependencies");
|
|
17
|
-
|
|
18
|
-
var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
|
|
19
|
-
|
|
20
|
-
var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
|
|
21
|
-
|
|
22
|
-
var _Message = _interopRequireDefault(require("../Model/SQS/Message.model"));
|
|
23
|
-
|
|
24
|
-
var _Status = _interopRequireWildcard(require("../Model/Status.model"));
|
|
25
|
-
|
|
26
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
27
|
-
|
|
28
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
|
-
|
|
30
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Allowed values for `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`.
|
|
34
|
-
*/
|
|
35
|
-
const SQS_OFFLINE_MODES = {
|
|
36
|
-
/**
|
|
37
|
-
* When running offline, messages will trigger the consumer function directly
|
|
38
|
-
* via a Lambda endpoint, set using `process.env.SERVICE_LAMBDA_URL`. This is
|
|
39
|
-
* the default.
|
|
40
|
-
*/
|
|
41
|
-
DIRECT: 'direct',
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* When running offline, send messages to an offline SQS service defined by
|
|
45
|
-
* `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_HOST`.
|
|
46
|
-
*/
|
|
47
|
-
LOCAL: 'local',
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* When running offline, send messages to AWS as normal.
|
|
51
|
-
*/
|
|
52
|
-
AWS: 'aws'
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Defines the preferred behaviour
|
|
56
|
-
* for SQSService.prototype.publish
|
|
57
|
-
* should AWS SQS fail.
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
exports.SQS_OFFLINE_MODES = SQS_OFFLINE_MODES;
|
|
61
|
-
const SQS_PUBLISH_FAILURE_MODES = {
|
|
62
|
-
/**
|
|
63
|
-
* Catches the exception and logs it.
|
|
64
|
-
* This is the default behaviour
|
|
65
|
-
* for LambdaWrapper 1.8.0 and below
|
|
66
|
-
* and for LambdaWrapper 1.8.2 and above
|
|
67
|
-
*/
|
|
68
|
-
CATCH: 'catch',
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Throws the exception so that the caller
|
|
72
|
-
* can handle it directly.
|
|
73
|
-
*/
|
|
74
|
-
THROW: 'throw'
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* SQSService class
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
exports.SQS_PUBLISH_FAILURE_MODES = SQS_PUBLISH_FAILURE_MODES;
|
|
81
|
-
|
|
82
|
-
class SQSService extends _DependencyAware.default {
|
|
83
|
-
/**
|
|
84
|
-
* SQSService constructor
|
|
85
|
-
*
|
|
86
|
-
* @param di DependencyInjection
|
|
87
|
-
*/
|
|
88
|
-
constructor(di) {
|
|
89
|
-
super(di);
|
|
90
|
-
const {
|
|
91
|
-
LAMBDA_WRAPPER_OFFLINE_SQS_HOST: offlineHost = 'localhost',
|
|
92
|
-
LAMBDA_WRAPPER_OFFLINE_SQS_PORT: offlinePort = '4576',
|
|
93
|
-
LAMBDA_WRAPPER_OFFLINE_SQS_MODE: offlineMode = SQS_OFFLINE_MODES.DIRECT,
|
|
94
|
-
AWS_ACCOUNT_ID,
|
|
95
|
-
REGION
|
|
96
|
-
} = process.env;
|
|
97
|
-
const container = this.getContainer();
|
|
98
|
-
const context = container.getContext();
|
|
99
|
-
const queues = container.getConfiguration('QUEUES');
|
|
100
|
-
const accountId = context && context.invokedFunctionArn && _alai.default.parse(context) || AWS_ACCOUNT_ID;
|
|
101
|
-
this.queues = {};
|
|
102
|
-
this.$lambda = null;
|
|
103
|
-
this.$sqs = null;
|
|
104
|
-
|
|
105
|
-
if (container.isOffline && !Object.values(SQS_OFFLINE_MODES).includes(offlineMode)) {
|
|
106
|
-
throw new Error(`Invalid LAMBDA_WRAPPER_OFFLINE_SQS_MODE: ${offlineMode}\n` + `Please use one of: ${Object.values(SQS_OFFLINE_MODES).join(', ')}`);
|
|
107
|
-
} // Add the queues from configuration
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (queues !== null && Object.keys(queues).length > 0) {
|
|
111
|
-
Object.keys(queues).forEach(queueDefinition => {
|
|
112
|
-
if (container.isOffline && offlineMode === SQS_OFFLINE_MODES.LOCAL) {
|
|
113
|
-
// custom URL when using an offline SQS service such as Localstack
|
|
114
|
-
this.queues[queueDefinition] = `http://${offlineHost}:${offlinePort}/queue/${queues[queueDefinition]}`;
|
|
115
|
-
} else {
|
|
116
|
-
// default AWS queue URL
|
|
117
|
-
this.queues[queueDefinition] = `https://sqs.${REGION}.amazonaws.com/${accountId}/${queues[queueDefinition]}`;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Returns an SQS client instance
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
get sqs() {
|
|
128
|
-
if (!this.$sqs) {
|
|
129
|
-
this.$sqs = new _awsSdk.default.SQS({
|
|
130
|
-
region: process.env.REGION,
|
|
131
|
-
httpOptions: {
|
|
132
|
-
// longest publish on NOTV took 5 seconds
|
|
133
|
-
connectTimeout: 8 * 1000,
|
|
134
|
-
timeout: 8 * 1000
|
|
135
|
-
},
|
|
136
|
-
maxRetries: 3 // default is 3, we can change that
|
|
137
|
-
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return this.$sqs;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Returns a Lambda client instance
|
|
145
|
-
*/
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
get lambda() {
|
|
149
|
-
if (!this.$lambda) {
|
|
150
|
-
const endpoint = process.env.SERVICE_LAMBDA_URL;
|
|
151
|
-
|
|
152
|
-
if (!endpoint) {
|
|
153
|
-
throw new Error('process.env.SERVICE_LAMBDA_URL must be defined.');
|
|
154
|
-
} // move to subprocess
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.$lambda = new _awsSdk.default.Lambda({
|
|
158
|
-
region: process.env.AWS_REGION,
|
|
159
|
-
endpoint
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return this.$lambda;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Returns the mode to use for offline SQS.
|
|
167
|
-
*
|
|
168
|
-
* This is configured by `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`. The
|
|
169
|
-
* default is `SQS_OFFLINE_MODES.LAMBDA`.
|
|
170
|
-
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
static get offlineMode() {
|
|
174
|
-
return process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE || SQS_OFFLINE_MODES.DIRECT;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Batch delete messages
|
|
178
|
-
*
|
|
179
|
-
* @param queue strung
|
|
180
|
-
* @param messageModels [SQSMessageModel]
|
|
181
|
-
* @returns {Promise<any>}
|
|
182
|
-
*/
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
batchDelete(queue, messageModels) {
|
|
186
|
-
const container = this.getContainer();
|
|
187
|
-
const queueUrl = this.queues[queue];
|
|
188
|
-
const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
189
|
-
const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
|
|
190
|
-
const timerId = `sqs-batch-delete-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
|
|
191
|
-
return new Promise(resolve => {
|
|
192
|
-
const messagesForDeletion = [];
|
|
193
|
-
Timer.start(timerId); // assuming openFiles is an array of file names
|
|
194
|
-
|
|
195
|
-
(0, _each.default)(messageModels, (messageModel, callback) => {
|
|
196
|
-
if (messageModel instanceof _Message.default && messageModel.isForDeletion() === true) {
|
|
197
|
-
messagesForDeletion.push({
|
|
198
|
-
Id: messageModel.getMessageId(),
|
|
199
|
-
ReceiptHandle: messageModel.getReceiptHandle()
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
callback();
|
|
204
|
-
}, loopError => {
|
|
205
|
-
if (loopError) {
|
|
206
|
-
Logger.error(loopError);
|
|
207
|
-
resolve();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
this.sqs.deleteMessageBatch({
|
|
211
|
-
Entries: messagesForDeletion,
|
|
212
|
-
QueueUrl: queueUrl
|
|
213
|
-
}, error => {
|
|
214
|
-
Timer.stop(timerId);
|
|
215
|
-
|
|
216
|
-
if (error) {
|
|
217
|
-
Logger.error(error);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
resolve();
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Check SQS status
|
|
227
|
-
*
|
|
228
|
-
* @returns {Promise<any>}
|
|
229
|
-
*/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
checkStatus() {
|
|
233
|
-
const container = this.getContainer();
|
|
234
|
-
const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
235
|
-
const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
|
|
236
|
-
const timerId = `sqs-list-queues-${(0, _uuid.v4)()}`;
|
|
237
|
-
return new Promise(resolve => {
|
|
238
|
-
Timer.start(timerId);
|
|
239
|
-
this.sqs.listQueues({}, (error, data) => {
|
|
240
|
-
Timer.stop(timerId);
|
|
241
|
-
const statusModel = new _Status.default('SQS', _Status.STATUS_TYPES.OK);
|
|
242
|
-
|
|
243
|
-
if (error) {
|
|
244
|
-
Logger.error(error);
|
|
245
|
-
statusModel.setStatus(_Status.STATUS_TYPES.APPLICATION_FAILURE);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (typeof data.QueueUrls === 'undefined' || data.QueueUrls.length === 0) {
|
|
249
|
-
statusModel.setStatus(_Status.STATUS_TYPES.APPLICATION_FAILURE);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
resolve(statusModel);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get number of messages in a queue
|
|
258
|
-
*
|
|
259
|
-
* @param queue
|
|
260
|
-
* @returns {Promise<any>}
|
|
261
|
-
*/
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
getMessageCount(queue) {
|
|
265
|
-
const container = this.getContainer();
|
|
266
|
-
const queueUrl = this.queues[queue];
|
|
267
|
-
const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
268
|
-
const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
|
|
269
|
-
const timerId = `sqs-get-queue-attributes-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
|
|
270
|
-
return new Promise(resolve => {
|
|
271
|
-
Timer.start(timerId);
|
|
272
|
-
this.sqs.getQueueAttributes({
|
|
273
|
-
AttributeNames: ['ApproximateNumberOfMessages'],
|
|
274
|
-
QueueUrl: queueUrl
|
|
275
|
-
}, (error, data) => {
|
|
276
|
-
Timer.stop(timerId);
|
|
277
|
-
|
|
278
|
-
if (error) {
|
|
279
|
-
Logger.error(error);
|
|
280
|
-
resolve(0);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
resolve(Number.parseInt(data.Attributes.ApproximateNumberOfMessages, 10));
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Publish to message queue
|
|
289
|
-
*
|
|
290
|
-
* When running within serverless-offline, messages can be published to a
|
|
291
|
-
* local Lambda or SQS service instead of to AWS, depending on the offline
|
|
292
|
-
* mode specified by `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`.
|
|
293
|
-
*
|
|
294
|
-
* @param queue string
|
|
295
|
-
* @param messageObject object
|
|
296
|
-
* @param messageGroupId string
|
|
297
|
-
* @param {'catch' | 'throw'} failureMode Choose how failures are handled:
|
|
298
|
-
* - `catch`: errors will be caught and logged. This is the default.
|
|
299
|
-
* - `throw`: errors will be thrown, causing promise to reject.
|
|
300
|
-
* @returns {Promise<any>}
|
|
301
|
-
*/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
async publish(queue, messageObject, messageGroupId = null, failureMode = SQS_PUBLISH_FAILURE_MODES.CATCH) {
|
|
305
|
-
if (!Object.values(SQS_PUBLISH_FAILURE_MODES).includes(failureMode)) {
|
|
306
|
-
throw new Error(`Invalid value for 'failureMode': ${failureMode}`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const container = this.getContainer();
|
|
310
|
-
const queueUrl = this.queues[queue];
|
|
311
|
-
const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
|
|
312
|
-
const timerId = `sqs-send-message-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
|
|
313
|
-
Timer.start(timerId);
|
|
314
|
-
const messageParameters = {
|
|
315
|
-
MessageBody: JSON.stringify(messageObject),
|
|
316
|
-
QueueUrl: queueUrl
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
if (queueUrl.includes('.fifo')) {
|
|
320
|
-
messageParameters.MessageDeduplicationId = (0, _uuid.v4)();
|
|
321
|
-
messageParameters.MessageGroupId = messageGroupId !== null ? messageGroupId : (0, _uuid.v4)();
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
if (container.isOffline && this.constructor.offlineMode === SQS_OFFLINE_MODES.DIRECT) {
|
|
326
|
-
await this.publishOffline(queue, messageParameters);
|
|
327
|
-
} else {
|
|
328
|
-
await this.sqs.sendMessage(messageParameters).promise();
|
|
329
|
-
}
|
|
330
|
-
} catch (error) {
|
|
331
|
-
if (failureMode === SQS_PUBLISH_FAILURE_MODES.CATCH) {
|
|
332
|
-
container.get(_Dependencies.DEFINITIONS.LOGGER).error(error);
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
throw error;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return queue;
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Sends a message to a queue consumer running in serverless-offline.
|
|
343
|
-
*
|
|
344
|
-
* This method invokes the consumer function directly instead of sending the
|
|
345
|
-
* message to SQS, which requires a real or emulated SQS service not provided
|
|
346
|
-
* by serverless-offline. This works very well for local testing.
|
|
347
|
-
*
|
|
348
|
-
* @param queue
|
|
349
|
-
* @param messageParameters
|
|
350
|
-
*/
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
async publishOffline(queue, messageParameters) {
|
|
354
|
-
const container = this.getContainer();
|
|
355
|
-
|
|
356
|
-
if (!container.isOffline) {
|
|
357
|
-
throw new Error('Can only publishOffline while running serverless offline.');
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const consumers = container.getConfiguration('QUEUE_CONSUMERS') || {};
|
|
361
|
-
const FunctionName = consumers[queue];
|
|
362
|
-
|
|
363
|
-
if (!FunctionName) {
|
|
364
|
-
throw new Error(`Queue consumer for queue ${queue} was not found. Please configure your application's QUEUE_CONSUMERS.`);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const InvocationType = 'RequestResponse';
|
|
368
|
-
const Payload = JSON.stringify({
|
|
369
|
-
Records: [{
|
|
370
|
-
body: messageParameters.MessageBody
|
|
371
|
-
}]
|
|
372
|
-
});
|
|
373
|
-
const parameters = {
|
|
374
|
-
FunctionName,
|
|
375
|
-
InvocationType,
|
|
376
|
-
Payload
|
|
377
|
-
};
|
|
378
|
-
await this.lambda.invoke(parameters).promise();
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Receive from message queue
|
|
382
|
-
*
|
|
383
|
-
* @param queue string
|
|
384
|
-
* @param timeout number
|
|
385
|
-
* @returns {Promise<any>}
|
|
386
|
-
*/
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
receive(queue, timeout = 15) {
|
|
390
|
-
const container = this.getContainer();
|
|
391
|
-
const queueUrl = this.queues[queue];
|
|
392
|
-
const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
393
|
-
const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
|
|
394
|
-
const timerId = `sqs-receive-message-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
|
|
395
|
-
return new Promise((resolve, reject) => {
|
|
396
|
-
Timer.start(timerId);
|
|
397
|
-
this.sqs.receiveMessage({
|
|
398
|
-
QueueUrl: queueUrl,
|
|
399
|
-
VisibilityTimeout: timeout,
|
|
400
|
-
MaxNumberOfMessages: 10
|
|
401
|
-
}, (error, data) => {
|
|
402
|
-
Timer.stop(timerId);
|
|
403
|
-
|
|
404
|
-
if (error) {
|
|
405
|
-
Logger.error(error);
|
|
406
|
-
return reject(error);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (typeof data.Messages === 'undefined') {
|
|
410
|
-
return resolve([]);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return resolve(data.Messages.map(message => new _Message.default(message)));
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
exports.default = SQSService;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _Dependencies = require("../Config/Dependencies");
|
|
9
|
-
|
|
10
|
-
var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
|
|
11
|
-
|
|
12
|
-
var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
|
|
13
|
-
|
|
14
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* TimerService class
|
|
18
|
-
*/
|
|
19
|
-
class TimerService extends _DependencyAware.default {
|
|
20
|
-
/**
|
|
21
|
-
* TimerService constructor
|
|
22
|
-
*
|
|
23
|
-
* @param di
|
|
24
|
-
*/
|
|
25
|
-
constructor(di) {
|
|
26
|
-
super(di);
|
|
27
|
-
this.timers = {};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Start timer
|
|
31
|
-
*
|
|
32
|
-
* @param identifier
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
start(identifier) {
|
|
37
|
-
this.timers[identifier] = Date.now();
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Stop timer
|
|
41
|
-
*
|
|
42
|
-
* @param identifier
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
stop(identifier) {
|
|
47
|
-
if (typeof this.timers[identifier] !== 'undefined') {
|
|
48
|
-
const duration = Date.now() - this.timers[identifier];
|
|
49
|
-
this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER).info(`Timing - ${identifier} took ${duration}ms to complete`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
exports.default = TimerService;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
*/
|
|
11
|
-
class LambdaTermination extends Error {
|
|
12
|
-
/**
|
|
13
|
-
* Triggers a Lambda Termination.
|
|
14
|
-
* Offers developer details (that are logged)
|
|
15
|
-
* an code for the Lambda and a front facing
|
|
16
|
-
* consumer message.
|
|
17
|
-
*
|
|
18
|
-
* @param {object|string} internal
|
|
19
|
-
* @param {number?} code
|
|
20
|
-
* @param {object|string?} body
|
|
21
|
-
* @param details
|
|
22
|
-
*/
|
|
23
|
-
constructor(internal, code = 500, body = null, details = 'unknown error') {
|
|
24
|
-
let stringified = internal;
|
|
25
|
-
|
|
26
|
-
if (typeof internal !== 'string') {
|
|
27
|
-
stringified = JSON.stringify(internal);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
super(stringified);
|
|
31
|
-
this.internal = internal;
|
|
32
|
-
this.code = code;
|
|
33
|
-
this.body = body || 'unknown error';
|
|
34
|
-
this.details = details;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
exports.default = LambdaTermination;
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.handleSuccess = exports.handleError = exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _epsagon = _interopRequireDefault(require("epsagon"));
|
|
9
|
-
|
|
10
|
-
var _Dependencies = require("../Config/Dependencies");
|
|
11
|
-
|
|
12
|
-
var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
|
|
13
|
-
|
|
14
|
-
var _Response = _interopRequireDefault(require("../Model/Response.model"));
|
|
15
|
-
|
|
16
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
-
|
|
18
|
-
/* eslint-disable sonarjs/cognitive-complexity */
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Processes the outcome once we have one
|
|
22
|
-
*
|
|
23
|
-
* @param di
|
|
24
|
-
* @param outcome
|
|
25
|
-
*/
|
|
26
|
-
const handleSuccess = (di, outcome) => {
|
|
27
|
-
const logger = di.get(_Dependencies.DEFINITIONS.LOGGER); // Outcome may be undefined as not all lambdas have a return value.
|
|
28
|
-
|
|
29
|
-
logger.metric('lambda.statusCode', outcome && outcome.statusCode || 200);
|
|
30
|
-
return outcome;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Gracefully handles an error
|
|
34
|
-
* logging in Epsagon and generating
|
|
35
|
-
* a response reflecting the `code`
|
|
36
|
-
* of the error, if defined.
|
|
37
|
-
*
|
|
38
|
-
* Note about Epsagon:
|
|
39
|
-
* Epsagon generates alerts for logs on level ERROR.
|
|
40
|
-
* This means that logger.error will produce an alert.
|
|
41
|
-
* To avoid not meaningful notifications, most likely
|
|
42
|
-
* coming from tests, we log INFO unless either:
|
|
43
|
-
*
|
|
44
|
-
* 1. `error.raiseOnEpsagon` is defined & truthy
|
|
45
|
-
* 2. `error.code` is defined and `error.code >= 500`.
|
|
46
|
-
*
|
|
47
|
-
* @param {DependencyInjection} di
|
|
48
|
-
* @param {Error} error
|
|
49
|
-
* @param {boolean} [throwError=false]
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
exports.handleSuccess = handleSuccess;
|
|
54
|
-
|
|
55
|
-
const handleError = (di, error, throwError = false) => {
|
|
56
|
-
const logger = di.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
57
|
-
logger.metric('lambda.statusCode', error.code || 500);
|
|
58
|
-
|
|
59
|
-
if (error.raiseOnEpsagon || !error.code || error.code >= 500) {
|
|
60
|
-
logger.error(error);
|
|
61
|
-
} else {
|
|
62
|
-
logger.info(error);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (throwError) {
|
|
66
|
-
if (error instanceof Error) {
|
|
67
|
-
return error;
|
|
68
|
-
} // We want to be absolutely sure
|
|
69
|
-
// that we are returning an error
|
|
70
|
-
// as Lambda sync handlers will only fail
|
|
71
|
-
// if the object is instanceof Error
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return new Error(error);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const responseDetails = {
|
|
78
|
-
body: error.body || {},
|
|
79
|
-
code: error.code || 500,
|
|
80
|
-
details: error.details || 'unknown error'
|
|
81
|
-
};
|
|
82
|
-
return _Response.default.generate(responseDetails.body, responseDetails.code, responseDetails.details);
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Lambda Wrapper.
|
|
86
|
-
*
|
|
87
|
-
* Wraps a lambda handler, generating a new function
|
|
88
|
-
* that has access to the dependency injection
|
|
89
|
-
* for the service and handles logging and exceptions.
|
|
90
|
-
*
|
|
91
|
-
* @param configuration
|
|
92
|
-
* @param handler
|
|
93
|
-
* @param throwError
|
|
94
|
-
*/
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
exports.handleError = handleError;
|
|
98
|
-
|
|
99
|
-
var _default = (configuration, handler, throwError = false) => {
|
|
100
|
-
let instance = (event, context, callback) => {
|
|
101
|
-
const di = new _DependencyInjection.default(configuration, event, context);
|
|
102
|
-
const request = di.get(_Dependencies.DEFINITIONS.REQUEST);
|
|
103
|
-
const logger = di.get(_Dependencies.DEFINITIONS.LOGGER);
|
|
104
|
-
context.callbackWaitsForEmptyEventLoop = false; // If the event is to trigger a warm up, then don't bother returning the function.
|
|
105
|
-
|
|
106
|
-
if (di.getEvent().source === 'serverless-plugin-warmup') {
|
|
107
|
-
return callback(null, 'Lambda is warm!');
|
|
108
|
-
} // Log the users ip address silently for use in error tracing
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (request.getIp() !== null) {
|
|
112
|
-
logger.metric('ipAddress', request.getIp(), true);
|
|
113
|
-
} // Add metrics with user browser information for rapid debugging
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const userBrowserAndDevice = request.getUserBrowserAndDevice();
|
|
117
|
-
|
|
118
|
-
if (userBrowserAndDevice !== null && typeof userBrowserAndDevice === 'object') {
|
|
119
|
-
Object.keys(userBrowserAndDevice).forEach(metricKey => {
|
|
120
|
-
logger.metric(metricKey, userBrowserAndDevice[metricKey], true);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
let outcome;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
outcome = handler.call(instance, di, request, callback);
|
|
128
|
-
|
|
129
|
-
if (outcome instanceof Promise) {
|
|
130
|
-
outcome = outcome.then(value => handleSuccess(di, value)).catch(error => {
|
|
131
|
-
const handled = handleError(di, error, throwError);
|
|
132
|
-
|
|
133
|
-
if (throwError) {
|
|
134
|
-
// AWS Lambda with async handler is looking for a rejection
|
|
135
|
-
// and not an error object directly
|
|
136
|
-
// and will treat resolved errors as successful
|
|
137
|
-
// as it will cast the error to JSON, i.e. `{}`
|
|
138
|
-
throw handled;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return handled;
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
} catch (error) {
|
|
145
|
-
outcome = handleError(di, error, throwError);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return outcome;
|
|
149
|
-
}; // If the Epsagon token is enabled, then wrap the instance in the Epsagon wrapper
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined') {
|
|
153
|
-
_epsagon.default.init({
|
|
154
|
-
token: process.env.EPSAGON_TOKEN,
|
|
155
|
-
appName: process.env.EPSAGON_SERVICE_NAME
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
instance = _epsagon.default.lambdaWrapper(instance);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return instance;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
exports.default = _default;
|