-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
core: remove protocol timeout for Page.navigate #6413
Conversation
a9fabde
to
d798047
Compare
lighthouse-core/gather/driver.js
Outdated
@@ -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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm % tweak
lighthouse-core/gather/driver.js
Outdated
@@ -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 |
There was a problem hiding this comment.
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.
There was a problem hiding this 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
OK, I've disabled the timeout completely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
lighthouse-core/gather/driver.js
Outdated
@@ -286,18 +286,19 @@ class Driver { | |||
} | |||
} | |||
return new Promise(async (resolve, reject) => { | |||
const asyncTimeout = setTimeout((_ => { | |||
const asyncTimeout = timeout > 0 ? setTimeout((_ => { |
There was a problem hiding this comment.
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(...)
}
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
lighthouse-core/gather/driver.js
Outdated
const result = await this._connection.sendCommand(method, ...params); | ||
clearTimeout(asyncTimeout); | ||
resolve(result); | ||
resolve(await this._connection.sendCommand(method, ...params)); |
There was a problem hiding this comment.
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.
lighthouse-core/gather/driver.js
Outdated
@@ -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. |
There was a problem hiding this comment.
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? :)
lighthouse-core/gather/driver.js
Outdated
@@ -259,6 +259,8 @@ class Driver { | |||
} | |||
|
|||
/** | |||
* If > 0, timeout is used for the next call to 'sendCommand'. | |||
* If <= 0, no timeout is used. |
There was a problem hiding this comment.
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.
lighthouse-core/gather/driver.js
Outdated
@@ -286,18 +286,19 @@ class Driver { | |||
} | |||
} | |||
return new Promise(async (resolve, reject) => { | |||
const asyncTimeout = setTimeout((_ => { | |||
const asyncTimeout = timeout > 0 ? setTimeout((_ => { |
There was a problem hiding this comment.
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
There was a problem hiding this 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?
lighthouse-core/gather/driver.js
Outdated
reject(err); | ||
}), timeout); | ||
let asyncTimeout; | ||
if (timeout > 0) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coolness thx
There was a problem hiding this 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.
lighthouse-core/gather/driver.js
Outdated
* @param {LH.CrdpCommands[C]['paramsType']} params | ||
* @return {Promise<LH.CrdpCommands[C]['returnType']>} | ||
*/ | ||
innerSendCommand(method, ...params) { |
There was a problem hiding this comment.
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
There was a problem hiding this 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) { | ||
// :) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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!! 👌
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice, done
i think 60s will be bettersee #6407 (comment)