feat: support concurrent installation of browsers (#3929)
A few details on locking registry to prohibit concurrent access: - locking is done by creating a `__dirlock` directory in the top-level of our registry. - since `__dirlock` directory does not match any of browser directories, old versions of the installer will ignore it - in case of concurrent access, installation will wait for a lock to be released for 10 minutes, periodically trying to grab the lock. If it fails to do so in 10 minutes, the installation will fail. Fixes #3912
This commit is contained in:
Родитель
2fbe767142
Коммит
7925a51149
|
@ -1328,6 +1328,15 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/proper-lockfile": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.1.tgz",
|
||||
"integrity": "sha512-HAjVfDa73pFgivViHyDu8HHHcds+W4MgOuZZAdyFJrHS8ngtCXmhl4hc2YXqSOwO6Bsa+iF2Sgxb2+gv874VOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/retry": "*"
|
||||
}
|
||||
},
|
||||
"@types/proxy-from-env": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/proxy-from-env/-/proxy-from-env-1.0.1.tgz",
|
||||
|
@ -1337,6 +1346,12 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/rimraf": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.0.tgz",
|
||||
|
@ -4226,8 +4241,7 @@
|
|||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
|
@ -6066,6 +6080,16 @@
|
|||
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
|
||||
"dev": true
|
||||
},
|
||||
"proper-lockfile": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.1.tgz",
|
||||
"integrity": "sha512-1w6rxXodisVpn7QYvLk706mzprPTAPCYAqxMvctmPN3ekuRk/kuGkGc82pangZiAt4R3lwSuUzheTTn0/Yb7Zg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"retry": "^0.12.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
|
@ -6445,6 +6469,11 @@
|
|||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"dev": true
|
||||
},
|
||||
"retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
|
||||
},
|
||||
"reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
|
@ -6641,6 +6670,11 @@
|
|||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
},
|
||||
"slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
"mime": "^2.4.6",
|
||||
"pngjs": "^5.0.0",
|
||||
"progress": "^2.0.3",
|
||||
"proper-lockfile": "^4.1.1",
|
||||
"proxy-from-env": "^1.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ws": "^7.3.1"
|
||||
|
@ -55,6 +56,7 @@
|
|||
"@types/node": "^10.17.28",
|
||||
"@types/pngjs": "^3.4.2",
|
||||
"@types/progress": "^2.0.3",
|
||||
"@types/proper-lockfile": "^4.1.1",
|
||||
"@types/proxy-from-env": "^1.0.1",
|
||||
"@types/rimraf": "^3.0.0",
|
||||
"@types/ws": "7.2.6",
|
||||
|
|
|
@ -19,6 +19,7 @@ import * as fs from 'fs';
|
|||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as removeFolder from 'rimraf';
|
||||
import * as lockfile from 'proper-lockfile';
|
||||
import * as browserPaths from '../utils/browserPaths';
|
||||
import * as browserFetcher from './browserFetcher';
|
||||
import { getFromENV } from '../utils/utils';
|
||||
|
@ -32,16 +33,29 @@ const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
|
|||
const removeFolderAsync = util.promisify(removeFolder);
|
||||
|
||||
export async function installBrowsersWithProgressBar(packagePath: string) {
|
||||
const browsersPath = browserPaths.browsersPath(packagePath);
|
||||
const linksDir = path.join(browsersPath, '.links');
|
||||
|
||||
if (getFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {
|
||||
browserFetcher.logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');
|
||||
return false;
|
||||
}
|
||||
|
||||
const browsersPath = browserPaths.browsersPath(packagePath);
|
||||
await fsMkdirAsync(browsersPath, { recursive: true });
|
||||
const releaseLock = await lockfile.lock(browsersPath, {
|
||||
retries: {
|
||||
retries: 10,
|
||||
// Retry 20 times during 10 minutes with
|
||||
// exponential back-off.
|
||||
// See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions
|
||||
factor: 1.27579,
|
||||
},
|
||||
lockfilePath: path.join(browsersPath, '__dirlock'),
|
||||
});
|
||||
const linksDir = path.join(browsersPath, '.links');
|
||||
|
||||
await fsMkdirAsync(linksDir, { recursive: true });
|
||||
await fsWriteFileAsync(path.join(linksDir, sha1(packagePath)), packagePath);
|
||||
await validateCache(packagePath, browsersPath, linksDir);
|
||||
await releaseLock();
|
||||
}
|
||||
|
||||
async function validateCache(packagePath: string, browsersPath: string, linksDir: string) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче