Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #76: Add configurable update rate #77

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@ The only required input is `project-name`.
the one defined here replaces the one in the CodeBuild project.
For a list of CodeBuild environment variables, see

1. **update-interval** (optional) :
Update interval as seconds for how often the API is called to check on the status.

A higher value mitigates the chance of hitting API rate-limiting especially when
running many instances of this action in parallel, but also introduces a larger
potential time overhead (ranging from 0 to update interval) for the action to
fetch the build result and finish.

Lower value limits the potential time overhead worst case but it may hit the API
rate-limit more often, depending on the use-case.

The default value is 30.

1. **update-back-off** (optional) :
Back-off time in seconds for the update interval.

When API rate-limiting is hit, the back-off time will be added to the next update
interval.
E.g. with update interval of 30 and back-off time of 15, upon hitting the rate-limit
the next interval for the update call will be 45s and if the rate-limit is hit again
the next interval will be 60s and so on.

The default value is 15.

### Outputs

1. **aws-build-id** : The CodeBuild build ID of the build that the action ran.
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ inputs:
env-vars-for-codebuild:
description: 'Comma separated list of environment variables to send to CodeBuild'
required: false
update-interval:
description: 'How often the action calls the API for updates'
required: false
update-back-off:
description: 'Back-off time for the update calls for API if rate-limiting is encountered'
required: false
outputs:
aws-build-id:
description: 'The AWS CodeBuild Build ID for this build.'
Expand Down
43 changes: 30 additions & 13 deletions code-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,37 @@ function runBuild() {
// get a codeBuild instance from the SDK
const sdk = buildSdk();

const inputs = githubInputs();

const config = (({ updateInterval, updateBackOff }) => ({
updateInterval,
updateBackOff,
}))(inputs);

// Get input options for startBuild
const params = inputs2Parameters(githubInputs());
const params = inputs2Parameters(inputs);

return build(sdk, params);
return build(sdk, params, config);
}

async function build(sdk, params) {
async function build(sdk, params, config) {
// Start the build
const start = await sdk.codeBuild.startBuild(params).promise();

// Wait for the build to "complete"
return waitForBuildEndTime(sdk, start.build);
return waitForBuildEndTime(sdk, start.build, config);
}

async function waitForBuildEndTime(
sdk,
{ id, logs },
{ updateInterval, updateBackOff },
seqEmptyLogs,
totalEvents,
throttleCount,
nextToken
) {
const {
codeBuild,
cloudWatchLogs,
wait = 1000 * 30,
backOff = 1000 * 15,
} = sdk;
const { codeBuild, cloudWatchLogs } = sdk;

totalEvents = totalEvents || 0;
seqEmptyLogs = seqEmptyLogs || 0;
Expand Down Expand Up @@ -87,16 +90,17 @@ async function waitForBuildEndTime(
//We caught an error in trying to make the AWS api call, and are now checking to see if it was just a rate limiting error
if (errObject.message && errObject.message.search("Rate exceeded") !== -1) {
//We were rate-limited, so add `backOff` seconds to the wait time
let newWait = wait + backOff;
let newWait = updateInterval + updateBackOff;
throttleCount++;

//Sleep before trying again
await new Promise((resolve) => setTimeout(resolve, newWait));

// Try again from the same token position
return waitForBuildEndTime(
{ ...sdk, wait: newWait },
{ ...sdk },
{ id, logs },
{ updateInterval: newWait, updateBackOff },
seqEmptyLogs,
totalEvents,
throttleCount,
Expand Down Expand Up @@ -136,13 +140,19 @@ async function waitForBuildEndTime(
// More to do: Sleep for a few seconds to avoid rate limiting
// If never throttled and build is complete, halve CWL polling delay to minimize latency
await new Promise((resolve) =>
setTimeout(resolve, current.endTime && throttleCount == 0 ? wait / 2 : wait)
setTimeout(
resolve,
current.endTime && throttleCount == 0
? updateInterval / 2
: updateInterval
)
);

// Try again
return waitForBuildEndTime(
sdk,
current,
{ updateInterval, updateBackOff },
seqEmptyLogs,
totalEvents,
throttleCount,
Expand Down Expand Up @@ -175,13 +185,20 @@ function githubInputs() {
.map((i) => i.trim())
.filter((i) => i !== "");

const updateInterval =
core.getInput("update-interval", { required: false }) || 1000 * 30;
const updateBackOff =
core.getInput("update-back-off", { required: false }) || 1000 * 15;

return {
projectName,
owner,
repo,
sourceVersion,
buildspecOverride,
envPassthrough,
updateInterval,
updateBackOff,
};
}

Expand Down
Loading