lambda-warmer
Advanced tools
Comparing version
109
index.js
@@ -9,3 +9,6 @@ 'use strict' | ||
const id = Date.now().toString() + '-' + ('0000' + Math.floor(Math.random()*1000).toString()).substr(-4) | ||
const id = | ||
Date.now().toString() + | ||
'-' + | ||
('0000' + Math.floor(Math.random() * 1000).toString()).substr(-4) | ||
@@ -20,31 +23,28 @@ let warm = false | ||
module.exports = (event,cfg = {}) => { | ||
let config = Object.assign({}, { | ||
flag: 'warmer', // default test flag | ||
concurrency: 'concurrency', // default concurrency field | ||
test: 'test', // default test flag | ||
log: true, // default logging to true | ||
correlationId: id, // default the correlationId | ||
delay: 75 // default the delay to 75ms | ||
},cfg) | ||
const handleEvent = (event, config) => { | ||
// If the event is a warmer ping | ||
if (event && event[config.flag]) { | ||
let concurrency = | ||
event[config.concurrency] && | ||
!isNaN(event[config.concurrency]) && | ||
event[config.concurrency] > 1 | ||
? event[config.concurrency] | ||
: 1 | ||
let concurrency = event[config.concurrency] | ||
&& !isNaN(event[config.concurrency]) | ||
&& event[config.concurrency] > 1 | ||
? event[config.concurrency] : 1 | ||
// Default target to funcName | ||
let target = event[config.target] || funcName | ||
let invokeCount = event['__WARMER_INVOCATION__'] | ||
&& !isNaN(event['__WARMER_INVOCATION__']) | ||
? event['__WARMER_INVOCATION__'] : 1 | ||
let invokeCount = | ||
event['__WARMER_INVOCATION__'] && !isNaN(event['__WARMER_INVOCATION__']) | ||
? event['__WARMER_INVOCATION__'] | ||
: 1 | ||
let invokeTotal = event['__WARMER_CONCURRENCY__'] | ||
&& !isNaN(event['__WARMER_CONCURRENCY__']) | ||
? event['__WARMER_CONCURRENCY__'] : concurrency | ||
let invokeTotal = | ||
event['__WARMER_CONCURRENCY__'] && !isNaN(event['__WARMER_CONCURRENCY__']) | ||
? event['__WARMER_CONCURRENCY__'] | ||
: concurrency | ||
let correlationId = event['__WARMER_CORRELATIONID__'] | ||
? event['__WARMER_CORRELATIONID__'] : config.correlationId | ||
? event['__WARMER_CORRELATIONID__'] | ||
: config.correlationId | ||
@@ -61,3 +61,6 @@ // Create log record | ||
lastAccessed: lastAccess, | ||
lastAccessedSeconds: lastAccess === null ? null : ((Date.now()-lastAccess)/1000).toFixed(1) | ||
lastAccessedSeconds: | ||
lastAccess === null | ||
? null | ||
: ((Date.now() - lastAccess) / 1000).toFixed(1) | ||
} | ||
@@ -72,5 +75,7 @@ | ||
// Check wether this lambda is invoking a different lambda | ||
let isDifferentTarget = target !== funcName | ||
// Fan out if concurrency is set higher than 1 | ||
if (concurrency > 1 && !event[config.test]) { | ||
if ((concurrency > 1 || isDifferentTarget) && !event[config.test]) { | ||
// init Lambda service | ||
@@ -83,15 +88,16 @@ let lambda = require('./lib/lambda-service') | ||
// loop through concurrency count | ||
for (let i=2; i <= concurrency; i++) { | ||
for (let i = isDifferentTarget ? 1 : 2; i <= concurrency; i++) { | ||
// Set the params and wait for the final function to finish | ||
let params = { | ||
FunctionName: funcName + ':' + funcVersion, | ||
FunctionName: target, | ||
InvocationType: i === concurrency ? 'RequestResponse' : 'Event', | ||
LogType: 'None', | ||
Payload: Buffer.from(JSON.stringify({ | ||
[config.flag]: true, // send warmer flag | ||
'__WARMER_INVOCATION__': i, // send invocation number | ||
'__WARMER_CONCURRENCY__': concurrency, // send total concurrency | ||
'__WARMER_CORRELATIONID__': correlationId // send correlation id | ||
})) | ||
Payload: new Buffer( | ||
JSON.stringify({ | ||
[config.flag]: true, // send warmer flag | ||
__WARMER_INVOCATION__: i, // send invocation number | ||
__WARMER_CONCURRENCY__: concurrency, // send total concurrency | ||
__WARMER_CORRELATIONID__: correlationId // send correlation id | ||
}) | ||
) | ||
} | ||
@@ -101,9 +107,6 @@ | ||
invocations.push(lambda.invoke(params).promise()) | ||
} // end for | ||
// Invoke concurrent functions | ||
return Promise.all(invocations) | ||
.then(() => true) | ||
return Promise.all(invocations).then(() => true) | ||
} else if (invokeCount > 1) { | ||
@@ -119,3 +122,31 @@ return delay(config.delay).then(() => true) | ||
} | ||
} | ||
module.exports = (event, cfg = {}) => { | ||
let config = Object.assign( | ||
{}, | ||
{ | ||
flag: 'warmer', // default test flag | ||
concurrency: 'concurrency', // default concurrency field | ||
target: 'target', // default target field | ||
test: 'test', // default test flag | ||
log: true, // default logging to true | ||
correlationId: id, // default the correlationId | ||
delay: 75 // default the delay to 75ms | ||
}, | ||
cfg | ||
) | ||
if (Array.isArray(event)) { | ||
let i = 0 | ||
const handleNext = () => { | ||
if (i < event.length) { | ||
return handleEvent(event[i++], config).then(handleNext) | ||
} | ||
return Promise.resolve(true) | ||
} | ||
return handleNext() | ||
} else { | ||
return handleEvent(event, config) | ||
} | ||
} // end module |
{ | ||
"name": "lambda-warmer", | ||
"version": "1.2.3", | ||
"version": "1.3.0", | ||
"description": "Keep your Lambda functions warm", | ||
@@ -13,3 +13,4 @@ "main": "index.js", | ||
"lint:fix": "eslint . --fix", | ||
"dtslint": "dtslint types" | ||
"dtslint": "dtslint types", | ||
"prepublishOnly": "npm run lint:check && npm run test && npm run dtslint" | ||
}, | ||
@@ -34,8 +35,8 @@ "repository": { | ||
"devDependencies": { | ||
"aws-sdk": "^2.424.0", | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.3", | ||
"dtslint": "^4.1.1", | ||
"eslint": "^5.15.3", | ||
"mocha": "^9.0.0", | ||
"aws-sdk": "^2.1295.0", | ||
"chai": "^4.3.7", | ||
"coveralls": "^3.1.1", | ||
"dtslint": "^4.2.1", | ||
"eslint": "^5.16.0", | ||
"mocha": "^9.2.2", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
@@ -45,3 +46,3 @@ "nyc": "^14.1.1", | ||
"sinon": "^6.3.5", | ||
"typescript": "^4.3.5" | ||
"typescript": "^4.9.4" | ||
}, | ||
@@ -48,0 +49,0 @@ "files": [ |
@@ -111,2 +111,5 @@ # Lambda Warmer | ||
### target *(string)* | ||
Name of the target function to be warmed. Defaults to `funcName` (the name of the function itself). | ||
Example passing a configuration: | ||
@@ -154,8 +157,8 @@ | ||
CodeUri: 's3://my-bucket/function.zip' | ||
Events: | ||
WarmingSchedule: | ||
Type: Schedule | ||
Properties: | ||
Schedule: rate(5 minutes) | ||
Input: '{ "warmer":true,"concurrency":3 }' | ||
Events: | ||
WarmingSchedule: | ||
Type: Schedule | ||
Properties: | ||
Schedule: rate(5 minutes) | ||
Input: '{ "warmer":true,"concurrency":3 }' | ||
``` | ||
@@ -181,2 +184,26 @@ | ||
## Setting multiple targets | ||
In addition to passing a single-target input (either the function itself or the configured target), Lambda Warmer also accepts an array of events, each allowing a separate config (concurrency, target, etc.). This allows the re-use of a single CloudWatch rule for multiple targets, beyond the limit of CloudWatch itself, which is 5. It also simplifies sharing the rule in Serverless. | ||
```yaml | ||
myFunction: | ||
name: myFunction | ||
handler: myFunction.handler | ||
events: | ||
- schedule: | ||
name: warmer-schedule-name | ||
rate: rate(5 minutes) | ||
enabled: true | ||
input: | ||
- warmer: true | ||
concurrency: 1 | ||
target: myOtherFunction | ||
- warmer: true | ||
concurrency: 2 | ||
target: myOtherFunction2 | ||
- warmer: true | ||
concurrency: 2 | ||
target: myOtherFunction3 | ||
``` | ||
## Logs | ||
@@ -183,0 +210,0 @@ |
interface WarmerConfig { | ||
flag?: string; | ||
concurrency?: string; | ||
concurrency?: number; | ||
test?: string; | ||
@@ -8,2 +8,3 @@ log?: boolean; | ||
delay?: number; | ||
target?: string; | ||
} | ||
@@ -10,0 +11,0 @@ |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
18179
11.33%159
29.27%228
13.43%0
-100%