serverless-plugin-warmup 8.2.1 → 8.4.0
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 +8 -8
- package/biome.json +47 -0
- package/package.json +36 -38
- package/src/config.js +159 -147
- package/src/index.js +245 -225
- package/src/schema.js +178 -162
- package/src/utils.js +1 -1
- package/src/warmer.js +139 -149
- package/.eslintignore +0 -2
- package/.eslintrc.js +0 -9
package/src/warmer.js
CHANGED
|
@@ -10,109 +10,92 @@ const execAsync = util.promisify(exec);
|
|
|
10
10
|
* @description Add warmer role to service
|
|
11
11
|
* */
|
|
12
12
|
function addWarmUpFunctionRoleToResources(service, stage, warmerName, warmerConfig) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
Effect: 'Allow',
|
|
102
|
-
Action: [
|
|
103
|
-
'ec2:CreateNetworkInterface',
|
|
104
|
-
'ec2:DescribeNetworkInterfaces',
|
|
105
|
-
'ec2:DetachNetworkInterface',
|
|
106
|
-
'ec2:DeleteNetworkInterface',
|
|
107
|
-
],
|
|
108
|
-
Resource: '*',
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
},
|
|
115
|
-
};
|
|
13
|
+
// eslint-disable-next-line no-param-reassign
|
|
14
|
+
warmerConfig.role = `WarmUpPlugin${capitalize(warmerName)}Role`;
|
|
15
|
+
if (typeof service.resources !== 'object') {
|
|
16
|
+
// eslint-disable-next-line no-param-reassign
|
|
17
|
+
service.resources = {};
|
|
18
|
+
}
|
|
19
|
+
if (typeof service.resources.Resources !== 'object') {
|
|
20
|
+
// eslint-disable-next-line no-param-reassign
|
|
21
|
+
service.resources.Resources = {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// eslint-disable-next-line no-param-reassign
|
|
25
|
+
service.resources.Resources[warmerConfig.role] = {
|
|
26
|
+
Type: 'AWS::IAM::Role',
|
|
27
|
+
Properties: {
|
|
28
|
+
Path: '/',
|
|
29
|
+
RoleName: warmerConfig.roleName || {
|
|
30
|
+
'Fn::Join': [
|
|
31
|
+
'-',
|
|
32
|
+
[service.service, stage, { Ref: 'AWS::Region' }, warmerName.toLowerCase(), 'role'],
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
AssumeRolePolicyDocument: {
|
|
36
|
+
Version: '2012-10-17',
|
|
37
|
+
Statement: [
|
|
38
|
+
{
|
|
39
|
+
Effect: 'Allow',
|
|
40
|
+
Principal: {
|
|
41
|
+
Service: ['lambda.amazonaws.com'],
|
|
42
|
+
},
|
|
43
|
+
Action: 'sts:AssumeRole',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
Policies: [
|
|
48
|
+
{
|
|
49
|
+
PolicyName: {
|
|
50
|
+
'Fn::Join': [
|
|
51
|
+
'-',
|
|
52
|
+
[service.service, stage, 'warmer', warmerName.toLowerCase(), 'policy'],
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
PolicyDocument: {
|
|
56
|
+
Version: '2012-10-17',
|
|
57
|
+
Statement: [
|
|
58
|
+
{
|
|
59
|
+
Effect: 'Allow',
|
|
60
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream'],
|
|
61
|
+
Resource: [
|
|
62
|
+
{
|
|
63
|
+
'Fn::Sub': `arn:\${AWS::Partition}:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:/aws/lambda/${warmerConfig.name}:*`,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
Effect: 'Allow',
|
|
69
|
+
Action: ['logs:PutLogEvents'],
|
|
70
|
+
Resource: [
|
|
71
|
+
{
|
|
72
|
+
'Fn::Sub': `arn:\${AWS::Partition}:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:/aws/lambda/${warmerConfig.name}:*:*`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
Effect: 'Allow',
|
|
78
|
+
Action: ['lambda:InvokeFunction'],
|
|
79
|
+
Resource: warmerConfig.functions.map((fn) => ({
|
|
80
|
+
'Fn::Sub': `arn:\${AWS::Partition}:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${fn.name}*`,
|
|
81
|
+
})),
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
Effect: 'Allow',
|
|
85
|
+
Action: [
|
|
86
|
+
'ec2:CreateNetworkInterface',
|
|
87
|
+
'ec2:DescribeNetworkInterfaces',
|
|
88
|
+
'ec2:DetachNetworkInterface',
|
|
89
|
+
'ec2:DeleteNetworkInterface',
|
|
90
|
+
],
|
|
91
|
+
Resource: '*',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
};
|
|
116
99
|
}
|
|
117
100
|
|
|
118
101
|
/**
|
|
@@ -126,18 +109,25 @@ function addWarmUpFunctionRoleToResources(service, stage, warmerName, warmerConf
|
|
|
126
109
|
* @return {Promise}
|
|
127
110
|
* */
|
|
128
111
|
async function createWarmUpFunctionArtifact(functions, tracing, verbose, region, handlerFolder) {
|
|
129
|
-
|
|
130
|
-
|
|
112
|
+
const warmUpFunction = `
|
|
131
113
|
/** Generated by Serverless WarmUp Plugin **/
|
|
132
114
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const lambda = new AWS.Lambda({
|
|
115
|
+
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
|
|
116
|
+
import { NodeHttpHandler } from '@smithy/node-http-handler';
|
|
117
|
+
|
|
118
|
+
const uninstrumentedLambdaClient = new LambdaClient({
|
|
138
119
|
apiVersion: '2015-03-31',
|
|
139
|
-
region: '${region}'
|
|
120
|
+
region: '${region}',
|
|
121
|
+
requestHandler: new NodeHttpHandler({ connectionTimeout: 1000 }),
|
|
140
122
|
});
|
|
123
|
+
|
|
124
|
+
${
|
|
125
|
+
tracing
|
|
126
|
+
? `import * as AWSXRay from 'aws-xray-sdk';
|
|
127
|
+
const lambdaClient = AWSXRay.captureAWSv3Client(uninstrumentedLambdaClient);`
|
|
128
|
+
: 'const lambdaClient = uninstrumentedLambdaClient;'
|
|
129
|
+
}
|
|
130
|
+
|
|
141
131
|
const functions = ${JSON.stringify(functions, null, ' ')};
|
|
142
132
|
|
|
143
133
|
function logVerbose(str) {
|
|
@@ -164,7 +154,7 @@ function getConcurrency(func, envVars) {
|
|
|
164
154
|
return concurrency;
|
|
165
155
|
}
|
|
166
156
|
|
|
167
|
-
|
|
157
|
+
export const warmUp = async (event, context) => {
|
|
168
158
|
logVerbose('Warm Up Start');
|
|
169
159
|
|
|
170
160
|
const invokes = await Promise.all(functions.map(async (func) => {
|
|
@@ -174,7 +164,7 @@ module.exports.warmUp = async (event, context) => {
|
|
|
174
164
|
? func.config.clientContext
|
|
175
165
|
: func.config.payload;
|
|
176
166
|
|
|
177
|
-
const
|
|
167
|
+
const invokeCommand = new InvokeCommand({
|
|
178
168
|
ClientContext: clientContext
|
|
179
169
|
? Buffer.from(\`{"custom":\${clientContext}}\`).toString('base64')
|
|
180
170
|
: undefined,
|
|
@@ -183,10 +173,10 @@ module.exports.warmUp = async (event, context) => {
|
|
|
183
173
|
LogType: 'None',
|
|
184
174
|
Qualifier: func.config.alias || process.env.SERVERLESS_ALIAS,
|
|
185
175
|
Payload: func.config.payload
|
|
186
|
-
};
|
|
176
|
+
});
|
|
187
177
|
|
|
188
178
|
try {
|
|
189
|
-
await Promise.all(Array(concurrency).fill(0).map(async () => await
|
|
179
|
+
await Promise.all(Array(concurrency).fill(0).map(async () => await lambdaClient.send(invokeCommand)));
|
|
190
180
|
logVerbose(\`Warm Up Invoke Success: \${func.name}\`);
|
|
191
181
|
return true;
|
|
192
182
|
} catch (e) {
|
|
@@ -198,48 +188,48 @@ module.exports.warmUp = async (event, context) => {
|
|
|
198
188
|
logVerbose(\`Warm Up Finished with \${invokes.filter(r => !r).length} invoke errors\`);
|
|
199
189
|
}`;
|
|
200
190
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
191
|
+
/** Write warm up file */
|
|
192
|
+
await fs.mkdir(handlerFolder, { recursive: true });
|
|
193
|
+
await fs.writeFile(path.join(handlerFolder, 'index.mjs'), warmUpFunction);
|
|
204
194
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
195
|
+
if (tracing) {
|
|
196
|
+
await execAsync('npm init -y', { cwd: handlerFolder });
|
|
197
|
+
await execAsync('npm install --save aws-xray-sdk-core', { cwd: handlerFolder });
|
|
198
|
+
}
|
|
209
199
|
}
|
|
210
200
|
|
|
211
201
|
/**
|
|
212
202
|
* @description Add warmer function to service
|
|
213
203
|
* */
|
|
214
204
|
function addWarmUpFunctionToService(service, warmerName, warmerConfig) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
205
|
+
// eslint-disable-next-line no-param-reassign
|
|
206
|
+
service.functions[`warmUpPlugin${capitalize(warmerName)}`] = {
|
|
207
|
+
description: `Serverless WarmUp Plugin (warmer "${warmerName}")`,
|
|
208
|
+
events: warmerConfig.events,
|
|
209
|
+
handler: warmerConfig.pathHandler.split(path.sep).join(path.posix.sep),
|
|
210
|
+
memorySize: warmerConfig.memorySize,
|
|
211
|
+
name: warmerConfig.name,
|
|
212
|
+
...(warmerConfig.architecture ? { architecture: warmerConfig.architecture } : {}),
|
|
213
|
+
runtime: 'nodejs24.x',
|
|
214
|
+
package: warmerConfig.package,
|
|
215
|
+
timeout: warmerConfig.timeout,
|
|
216
|
+
...(Object.keys(warmerConfig.environment).length
|
|
217
|
+
? { environment: warmerConfig.environment }
|
|
218
|
+
: {}),
|
|
219
|
+
...(warmerConfig.tracing !== undefined ? { tracing: warmerConfig.tracing } : {}),
|
|
220
|
+
...(warmerConfig.logRetentionInDays !== undefined
|
|
221
|
+
? { logRetentionInDays: warmerConfig.logRetentionInDays }
|
|
222
|
+
: {}),
|
|
223
|
+
...(warmerConfig.roleName ? { roleName: warmerConfig.roleName } : {}),
|
|
224
|
+
...(warmerConfig.role ? { role: warmerConfig.role } : {}),
|
|
225
|
+
...(warmerConfig.tags ? { tags: warmerConfig.tags } : {}),
|
|
226
|
+
...(warmerConfig.vpc ? { vpc: warmerConfig.vpc } : {}),
|
|
227
|
+
layers: [],
|
|
228
|
+
};
|
|
239
229
|
}
|
|
240
230
|
|
|
241
231
|
module.exports = {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
232
|
+
addWarmUpFunctionRoleToResources,
|
|
233
|
+
createWarmUpFunctionArtifact,
|
|
234
|
+
addWarmUpFunctionToService,
|
|
245
235
|
};
|
package/.eslintignore
DELETED