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

[BUG] Lock not released in case of ECONNRESET when installing #5110

Closed
alexdima opened this issue Jan 22, 2021 · 2 comments · Fixed by #5126
Closed

[BUG] Lock not released in case of ECONNRESET when installing #5110

alexdima opened this issue Jan 22, 2021 · 2 comments · Fixed by #5126
Assignees

Comments

@alexdima
Copy link
Member

Context:

  • Playwright Version: All
  • Operating System: All
  • Node.js version: 14.x
  • Browser: All
  • Extra: GitHub Action / Azure Pipelines

Background

We use caching of node_modules foders to speed up our CI build times and we execute yarn with PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD, so oftentimes node_modules are restored but the playwright downloads are not restored anyways, so we then run the install script by ourselves.

So on our build machines we invoke node node_modules/playwright/install.js and we see every now and again that builds fail due to ECONNRESET errors when trying to install playwright. e.g. https://github.com/microsoft/vscode/runs/1747455678#step:12:130

That is to be expected since internet might always be flaky, and the normal path forward is to just retry downloading.

Problem

We've added some code to retry installing on our side e.g.

export async function retry<T>(fn: () => Promise<T>): Promise<T> {
	for (let run = 1; run <= 10; run++) {
		try {
			return await fn();
		} catch (err) {
			if (!/ECONNRESET/.test(err.message)) {
				throw err;
			}

			const millis = (Math.random() * 200) + (50 * Math.pow(1.5, run));
			console.log(`Failed with ECONNRESET, retrying in ${millis}ms...`);

			// maximum delay is 10th retry: ~3 seconds
			await new Promise(c => setTimeout(c, millis));
		}
	}

	throw new Error('Retried too many times');
}

const { installBrowsersWithProgressBar } = require('playwright/lib/install/installer');
const playwrightPath = path.dirname(require.resolve('playwright'));
await retry(() => installBrowsersWithProgressBar(playwrightPath));

So basically we invoke installBrowsersWithProgressBar again and again until it stops throwing ECONNRESET but at most 10 times.

The problem is that we now get builds failing with Lock file is already being held errors e.g. https://github.com/microsoft/vscode/runs/1748968312#step:10:264

From a quick look there is some locking done in that function and the locks are not released in the error path. IMHO the problem might be in installBrowsersWithProgressBar which perhaps should wrap await releaseLock(); in a finally block.

If you have a better way to install playwright which is resilient to intermittent network errors, I would be happy to try that out instead.

aslushnikov added a commit to aslushnikov/playwright that referenced this issue Jan 23, 2021
- release lock if an exception happens during install
- retry downloading to support intermittent network

Fixes microsoft#5110
@aslushnikov
Copy link
Collaborator

@alexdima awesome investigation! I've adopted your snippet code into Playwright to run download re-tries.

@aslushnikov
Copy link
Collaborator

@alexdima so the fix has landed and is available at the playwright@next channel. We'll be happy if you can test this out and see if it makes things better for you. If it doesn't, please feel free to open a new issue to bring our attention to it! (we often miss notifications to the closed issues but are very carefully triaging all the incoming bugs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants