Skip to content
This repository was archived by the owner on Jan 16, 2025. It is now read-only.

Commit 1461efd

Browse files
authored
feat(runners): Add delay to prevent ssm rate limits using setTimeout (#2823)
* ISSUE-1841: Fix ssm rate limiting issue when instance count is greater than SSM parameter store max throughput * ISSUE-1841: Add jest test for creating 40 runners at once to cover ssm rate limits condition * ISSUE-1841: Fix linter and update test to check the actual time delay for creating 40+ runners * ISSUE-1841: Fix require statement for perf_hooks * ISSUE-1841: Fix formatting
1 parent 2840d5e commit 1461efd

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

modules/runners/lambdas/runners/src/aws/runners.test.ts

+70
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { EC2 } from 'aws-sdk';
2+
import { performance } from 'perf_hooks';
23

34
import ScaleError from './../scale-runners/ScaleError';
45
import { RunnerInfo, RunnerInputParameters, createRunner, listEC2Runners, terminateRunner } from './runners';
@@ -224,6 +225,75 @@ describe('create runner', () => {
224225
expect(mockSSM.putParameter).toBeCalledTimes(1);
225226
});
226227

228+
it('calls create fleet of 40 instances (ssm rate limit condition) to test time delay ', async () => {
229+
const startTime = performance.now();
230+
const instances = [
231+
{
232+
InstanceIds: [
233+
'i-1234',
234+
'i-5678',
235+
'i-5567',
236+
'i-5569',
237+
'i-5561',
238+
'i-5560',
239+
'i-5566',
240+
'i-5536',
241+
'i-5526',
242+
'i-5516',
243+
'i-122',
244+
'i-123',
245+
'i-124',
246+
'i-125',
247+
'i-126',
248+
'i-127',
249+
'i-128',
250+
'i-129',
251+
'i-130',
252+
'i-131',
253+
'i-132',
254+
'i-133',
255+
'i-134',
256+
'i-135',
257+
'i-136',
258+
'i-137',
259+
'i-138',
260+
'i-139',
261+
'i-140',
262+
'i-141',
263+
'i-142',
264+
'i-143',
265+
'i-144',
266+
'i-145',
267+
'i-146',
268+
'i-147',
269+
'i-148',
270+
'i-149',
271+
'i-150',
272+
'i-151',
273+
],
274+
},
275+
];
276+
mockCreateFleet.promise.mockReturnValue({
277+
Instances: instances,
278+
});
279+
280+
await createRunner({ ...createRunnerConfig(defaultRunnerConfig), numberOfRunners: 40 });
281+
const endTime = performance.now();
282+
283+
expect(endTime - startTime).toBeGreaterThan(1000);
284+
expect(mockEC2.createFleet).toBeCalledWith(
285+
expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, totalTargetCapacity: 40 }),
286+
);
287+
expect(mockSSM.putParameter).toBeCalledTimes(40);
288+
for (const instance of instances[0].InstanceIds) {
289+
expect(mockSSM.putParameter).toBeCalledWith({
290+
Name: `${SSM_TOKEN_PATH}/${instance}`,
291+
Type: 'SecureString',
292+
Value: '--token foo --url http://github.com',
293+
});
294+
}
295+
});
296+
227297
it('calls create fleet of 1 instance with the on-demand capacity', async () => {
228298
await createRunner(createRunnerConfig({ ...defaultRunnerConfig, capacityType: 'on-demand' }));
229299
expect(mockEC2.createFleet).toBeCalledWith(

modules/runners/lambdas/runners/src/aws/runners.ts

+9
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ export async function createRunner(runnerParameters: RunnerInputParameters): Pro
256256

257257
logger.info('Created instance(s): ', instances.join(','), LogFields.print());
258258

259+
const delay = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
260+
const ssmParameterStoreMaxThroughput = 40;
261+
const isDelay = instances.length >= ssmParameterStoreMaxThroughput ? true : false;
262+
259263
for (const instance of instances) {
260264
await ssm
261265
.putParameter({
@@ -264,5 +268,10 @@ export async function createRunner(runnerParameters: RunnerInputParameters): Pro
264268
Type: 'SecureString',
265269
})
266270
.promise();
271+
272+
if (isDelay) {
273+
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
274+
await delay(25);
275+
}
267276
}
268277
}

0 commit comments

Comments
 (0)