Skip to content

Commit

Permalink
Fix race condition when saving caches
Browse files Browse the repository at this point in the history
In the previous code there was a potential race condition when two or
more workflows checked the cache at the same time:

1. Workflow 1: cache miss; Workflow 2: cache miss
2. Workflow 1: install; Workflow 2: install
3. Workflow 1: save cache; Workflow 2: save cache <<< RACE CONDITION

This resulted in the step failing with the following error:

Error: reserveCache failed: Cache already exists. Scope: refs/heads/master,
Key: <key>, Version: <...>

It's a bug in the @actions/cache package and it's discussed in the
following issue: actions/toolkit#537

The correct behaviour would be for Workflow 2 to simply drop its attempt
to save the cache entry when this situation occurs.

For now, this code uses a workaround to fix this issue which works by
detecting and catchin the above error based on its error message.
  • Loading branch information
weibeld committed Oct 9, 2020
1 parent f7cd3e8 commit cd67d2c
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ async function main() {
version = execSync('npm view ajv-cli version').toString().trim();
core.info(`Latest version of ajv-cli is ${version}`);
} else if (!execSync('npm view ajv-cli versions').includes(version)) {
fail(`${version} is not a valid version of ajv-cli (list available versions with 'npm view ajv-cli versions'`);
}
fail(`${version} is not a valid version of ajv-cli`);
}

key = `ajv-cli-${version}-${process.env.RUNNER_OS}`;
installDir = `${process.env.RUNNER_TEMP}/${key}`;
Expand All @@ -42,7 +42,16 @@ async function main() {
core.endGroup();
// Save installation directory to cache
core.startGroup(`Caching installation directory with key ${key}`);
await cache.saveCache([installDir], key);
try {
await cache.saveCache([installDir], key);
// Workaround for race condition: https://github.com/actions/toolkit/issues/537
} catch (err) {
if (err.message.includes("Cache already exists")) {
core.info(`Cache entry ${key} has already been created by another worfklow`);
} else {
throw err;
}
}
core.endGroup();
// If cache has been found and restored
} else {
Expand Down

0 comments on commit cd67d2c

Please sign in to comment.