-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Add Poll class, fix some tests, throttle polling. #6141
Conversation
Thanks for making a pull request to JupyterLab! To try out this branch on binder, follow this link: |
The broken tests are correct. I will remove the |
@afshin - I notice this is still WIP. Do you want me to review it yet for the prerelease this week? |
@jasongrout Sorry! I put it back into WIP because some things needed refactoring. This will be ready before our meeting tomorrow. Is that enough time for you to review? |
@jasongrout Assuming tests pass, this is ready for review. I created an issue to refactor the file browser model, which is the only poll I left out, because it is more deeply embedded in the file browser and it will not require an API change so we can do it later. |
Thanks. I'm looking at this now. |
I have a PR to submit to this PR with some slight (but I feel important) modifications to the math of the jitter algorithm. I also looked a bit into jitter algorithms. https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ was one of the few interesting results I found in a quick search, and discussed more at https://trac.torproject.org/projects/tor/ticket/23816#no2. Using the terminology from the blog post, we essentially have a variant of their "Equal Jitter" approach. Perhaps it would be better to use something like "Decorrelated Jitter", which essentially puts a static lower bound on the polling interval, but just increases the max exponentially, and picks a uniform random value between the min and max. I like this approach because it tends to really spread clients out quickly, rather than still grouping them around the exponential values. What do you think about using that algorithm instead? Then "no jitter" would just be basically a setTimeout with a single value. |
That sounds good to me, the decorrelated jitter sounds like a good behavior to me. Please post a PR if you're working on one. If not, I can implement it tomorrow. |
Also, one change I recently made that I want to undo is that instead of if (!this.isReady) {
await this.ready;
} or something like that. I'm not sure whether to add |
I've been puzzling through the state transitions for a while this afternoon. I think checking the state phase won't work because the phase could be any number of things after the initialization. I like the synchronous |
Any phase after get isReady(): boolean {
return this.state.phase !== 'instantiated';
} Because any other phase can |
In reality, |
Hm, I think we should talk about jitter, I'm a little unsure about what we want. |
I opened https://github.com/afshin/jupyterlab/pull/24 for some changes to the kernel manager logic. I'm continuing to work my way through the files in the PR, and I may add more to that PR. |
let xsrfToken = getCookie('_xsrf'); | ||
if (xsrfToken !== void 0) { | ||
} | ||
if (typeof document !== 'undefined' && document && document.cookie) { |
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.
Can you elaborate on why you took out the else
here?
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.
This was causing reconnects (after stopping the server and starting again) to fail. I didn't definitively understand why but it seems reasonable if we have both the cookie and the header to use both and it turned out to eliminate a class of failures after reconnect.
Clean up some of the kernel manager async and request logic.
One more PR with changes to the terminal manager: https://github.com/afshin/jupyterlab/pull/25 |
Update terminal manager to be consistent with kernel/session manager async logic
For a future PR, I noticed in using the API it might be nice if |
@@ -124,7 +126,7 @@ describe('terminal', () => { | |||
let called = false; | |||
session = await manager.startNew(); | |||
manager.runningChanged.connect((sender, args) => { | |||
expect(session.isDisposed).to.equal(false); | |||
expect(session.isDisposed).to.equal(true); |
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.
Note to self: this may need to be changed back to false after my recent manager updates.
@@ -203,7 +221,7 @@ describe('kernel/manager', () => { | |||
const kernel = await manager.startNew(); | |||
const emission = testEmission(manager.runningChanged, { | |||
test: () => { | |||
expect(kernel.isDisposed).to.equal(false); | |||
expect(kernel.isDisposed).to.equal(true); |
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.
Note to self: this may need to be changed back to false after my recent manager updates.
We could potentially do something like: async refresh(passthrough = false): Promise<void> {
if (this.isDisposed) {
return;
}
if (this.state.phase === 'constructed') {
await this.ready;
}
if (this.state.phase !== 'refreshed') {
this.schedule({
interval: Private.IMMEDIATE,
payload: null,
phase: 'refreshed',
timestamp: new Date().getTime()
});
}
if (passthrough) {
await this.tick;
}
} But I'm not sure. The idea was to keep the API super simple and predictable: you always get the tick you created, the |
I'm not sure either. I'm happy to leave it as-is, with a simple consistent api, and see if that's okay, or if we want to make it slightly more convenient later. |
I apparently neglected to git push the doc string commit on my other machine, so I added it now. |
And the tests all pass! Thanks again for all your work on this one, @afshin! |
Nice! |
Fixes #3929
Poll
class to@jupyterlab/coreutils
to abstract polling and exponentially backing off in case of failure.Poll
class tests.Poll
class:@jupyterlab/services:KernelManager#models
@jupyterlab/services:KernelManager#specs
@jupyterlab/services:SessionManager#models
@jupyterlab/services:SessionManager#specs
@jupyterlab/services:TerminalManager#models
@jupyterlab/statusbar:MemoryUsage#metrics
async
.Poll
class that is possible is addingPoll[Symbol.asyncIterator]
,Poll#return()
, andPoll#next()
methods to make the poll anasync
iterator.dialog.spec.tsx
file that were accidentally disabled and modernizes them to jest API.Dialog
class API and adds an instance tracker:Dialog.tracker
State diagram of the possible state transitions between poll phases