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

core: remove protocol timeout for Page.navigate #6413

Merged
merged 11 commits into from
Nov 20, 2018

Conversation

connorjclark
Copy link
Collaborator

@connorjclark connorjclark commented Oct 27, 2018

i think 60s will be better

see #6407 (comment)

@connorjclark connorjclark changed the title Issue 6407 increase page navigate timeout core: increase page navigate timeout Oct 27, 2018
@connorjclark connorjclark force-pushed the issue-6407-increase-page-navigate-timeout branch from a9fabde to d798047 Compare October 27, 2018 00:22
@@ -840,7 +840,7 @@ class Driver {
// happen _after_ onload: https://crbug.com/768961
this.sendCommand('Page.enable');
this.sendCommand('Emulation.setScriptExecutionDisabled', {value: disableJS});
this.setNextProtocolTimeout(30 * 1000);
this.setNextProtocolTimeout(60 * 1000); // see https://github.com/GoogleChrome/lighthouse/pull/6413
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT about @brendankenny's suggestion of ignoring the timeout, we don't wait or care about the result of this command at all so seems a bit silly to need to control a timeout for it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sg. i turned it all the way to 90s on lightrider.

might as well use that here, too.

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm % tweak

@@ -840,7 +840,7 @@ class Driver {
// happen _after_ onload: https://crbug.com/768961
this.sendCommand('Page.enable');
this.sendCommand('Emulation.setScriptExecutionDisabled', {value: disableJS});
this.setNextProtocolTimeout(30 * 1000);
this.setNextProtocolTimeout(60 * 1000); // see https://github.com/GoogleChrome/lighthouse/pull/6413
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sg. i turned it all the way to 90s on lightrider.

might as well use that here, too.

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM if we need to land this, but agree with @patrickhulce's comment that if we're purposefully disabling the timeout we should just do so explicitly

@connorjclark
Copy link
Collaborator Author

OK, I've disabled the timeout completely.

Copy link
Member

@exterkamp exterkamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@@ -286,18 +286,19 @@ class Driver {
}
}
return new Promise(async (resolve, reject) => {
const asyncTimeout = setTimeout((_ => {
const asyncTimeout = timeout > 0 ? setTimeout((_ => {
Copy link
Member

@brendankenny brendankenny Oct 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the ternary ends up stretching pretty far. What about just

let asyncTimeout;
if (timeout > 0) {
  asyncTimeout = setTimeout(...)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should also add a note about the 0 behavior to setNextProtocolTimeout

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have gone that route first, but it would need to be let, and my personal preferences led me to choose the ternary before reaching for let. wdyt

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, yeah, let. And what's with that explicit undefined. Going to edit my comment because my brain was apparently off while writing that :)

The main issue is that you have to look down four lines to see the other half of the conditional, and the syntax makes it harder to parse than normal control flow mechanisms (like an if block). Generally long ternaries just aren't worth it, but at the very least, the null branch should be first

const result = await this._connection.sendCommand(method, ...params);
clearTimeout(asyncTimeout);
resolve(result);
resolve(await this._connection.sendCommand(method, ...params));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result is about as generic as you can get, but it does end up separating a bit of this (e.g. the await is significant if we want the timeout to work correctly. So I'd still be in favor of setting await this._connection.sendCommand to an intermediate result variable before resolving on it.

@@ -840,7 +841,7 @@ class Driver {
// happen _after_ onload: https://crbug.com/768961
this.sendCommand('Page.enable');
this.sendCommand('Emulation.setScriptExecutionDisabled', {value: disableJS});
this.setNextProtocolTimeout(30 * 1000);
this.setNextProtocolTimeout(0); // We don't need a strict timeout for Page.navigate. See #6413.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: drop the strict here now that we don't have any at all? :)

@@ -259,6 +259,8 @@ class Driver {
}

/**
* If > 0, timeout is used for the next call to 'sendCommand'.
* If <= 0, no timeout is used.
Copy link
Member

@brendankenny brendankenny Oct 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The >/<= describe literally what's allowed, but probably aren't worth including. Maybe go with timeout is used for the next call to 'sendCommand'. If 0, no timeout is used.

@@ -286,18 +286,19 @@ class Driver {
}
}
return new Promise(async (resolve, reject) => {
const asyncTimeout = setTimeout((_ => {
const asyncTimeout = timeout > 0 ? setTimeout((_ => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, yeah, let. And what's with that explicit undefined. Going to edit my comment because my brain was apparently off while writing that :)

The main issue is that you have to look down four lines to see the other half of the conditional, and the syntax makes it harder to parse than normal control flow mechanisms (like an if block). Generally long ternaries just aren't worth it, but at the very least, the null branch should be first

@brendankenny brendankenny changed the title core: increase page navigate timeout core: remove Page.navigate timeout Nov 19, 2018
Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Seems like we do still want this?

@brendankenny brendankenny changed the title core: remove Page.navigate timeout core: remove timeout for Page.navigate Nov 19, 2018
@brendankenny brendankenny changed the title core: remove timeout for Page.navigate core: remove protocol timeout for Page.navigate Nov 19, 2018
reject(err);
}), timeout);
let asyncTimeout;
if (timeout > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking another look at this.
I'm a bit hesitant to absorb this complexity.

What about adding a driver.innerSendCommand() which does the essence of sendCommand
And for the Page.Navigate command we use that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coolness thx

@paulirish
Copy link
Member

@brendankenny @patrickhulce @exterkamp lgty?

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize I this is something new (and it really should have been part of #6347), but looking at it now, it would be easy to throw in a test or two for timeout + sendCommand.

It should be just a mock Connection with a sendCommand that takes 10ms or whatever, call setNextProtocolTimeout(5), and make sure it throws (and the opposite timings don't). Not sure if we need any tests more complicated than that.

* @param {LH.CrdpCommands[C]['paramsType']} params
* @return {Promise<LH.CrdpCommands[C]['returnType']>}
*/
innerSendCommand(method, ...params) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a leading _ and mark it with @private (someday tsc will support it) to make it super clear it's intended for internal use

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than test! :)

await driver.sendCommand('Page.disable');
assert.fail('expected driver.sendCommand to timeout');
} catch (err) {
// :)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well here we want to assert that we didn't fail with the assert.fail you added :)

let's make sure that the message matches roughly what we want it to .includes('PROTOCOL_TIMEOUT') maybe?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks correct to me - if this command times out, the next statement in the try block should never be reached.

added check for err.code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks correct to me - if this command times out, the next statement in the try block should never be reached.

If the command times out, it would've thrown. If it doesn't time out as expected, it would've also thrown on the following line with the fail. Both paths led to an empty catch block. New error code assertion looks perfect though!! 👌

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, of course. I convinced myself that assert.fail didn't throw an error.. I was applying a pattern that works for other testing frameworks. But totally doesn't work here :p

@@ -240,6 +240,24 @@ describe('Browser Driver', () => {
});
});

it('.sendCommand timesout when commands take too long', async () => {
const driver = new Driver(connection);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than overriding a method of Driver, can this mock a Connection instead? That way we're only testing how the public Driver.sendCommand obeys timeouts, regardless of how internals evolve in the future (and only mocking the public interface of Connection)

Something like

const mockConnection = {
  async connect() {}
  async disconnect() {}
  sendCommand() {
    return new Promise(resolve => setTimeout(resolve, 15));
  }
};
const driver = new Driver(mockConnection);

should work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, done

@brendankenny brendankenny merged commit e45020b into master Nov 20, 2018
@brendankenny brendankenny deleted the issue-6407-increase-page-navigate-timeout branch November 20, 2018 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants