-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Startup the jupyter server when appropriate #9708
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
Conversation
And to be noted, our existing functional tests caught a bug in my implementation. Woot. |
@@ -142,6 +152,11 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { | |||
localize.DataScience.nativeEditorTitle(), | |||
ViewColumn.Active | |||
); | |||
|
|||
// Start the server as soon as we open if allowed | |||
if (!this.configService.getSettings().datascience.disableJupyterAutoStart) { |
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 think auto starting of notebooks should be done outside the editor.
I'd prefer the editor focus on editing alone. #Resolved
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 editor has always started the server, just not when it opens.
In reply to: 369669813 [](ancestors = 369669813)
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 think it's a good time to move this out.
At least auto starting. Feels like to much is happening in this space and we keep wrong more stuff. #Resolved
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.
Disagree. The internal implementation of the notebook (interactiveBase actually) requires a server to run code. Where is it supposed to get this server from if it doesn't start it? It assumes it was already started? That sounds like the wrong dependency to me.
In reply to: 369689773 [](ancestors = 369689773)
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 the auto starting though. Just not the ensureServer calls.
In reply to: 369692802 [](ancestors = 369692802,369689773)
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.
Actually that breaks the connection between the server and the UI. It doesn't know it got started. So I'll have to add other code to check if it's already started.
In reply to: 369693209 [](ancestors = 369693209,369692802,369689773)
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.
Which means some sort of global event on the JupyterExecution class.
In reply to: 369695742 [](ancestors = 369695742,369693209,369692802,369689773)
await this.fileSystem.createDirectory(path.dirname(filePath)); | ||
return this.fileSystem.writeFile(filePath, contents); | ||
} else { | ||
return this.fileSystem.deleteFile(filePath); |
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.
Do we care if there are any exceptions in here when deleting a backup file? #WontFix
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.
If not, I'd prefer adding that and removing the catch
. Feels like catch
will bury issues instead of them getting reported. #WontFix
} | ||
|
||
private onDidOpenOrCloseInteractive(interactive: IInteractiveWindow | undefined) { | ||
if (interactive) { |
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.
Not sure why this is necessary?
Is it possible to open an interactive window without starting a server?
Also, why should we start a server when switching between tabs from interactive window to something else? #Resolved
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.
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 I should rename startServer. it doesn't just start a server. It checks if one was succesfully started, and if so, writes the memento item to indicate it was succesful.
In reply to: 369690429 [](ancestors = 369690429,369673234)
// This is the list of things that should cause us to start a local server | ||
// 1) Notebook is opened | ||
// 2) Notebook was opened in the past 7 days | ||
// 3) Interactive window was opened in the past 7 days |
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.
Lets discuss these rules/criteria.
// Make sure it has a server | ||
assert.ok(editor.notebook, 'Notebook did not start with a server'); | ||
|
||
// Close down all servers and mock restarting |
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.
Do we need such a test, testing of restarting servers after disposing them?
I thought servers get disposed only when VS Code is closed. #Resolved
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.
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.
Shouldn't that be a separate test? #Resolved
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.
Yeah that would probably be better, especially if I only run these with mocking.
In reply to: 369692742 [](ancestors = 369692742)
Codecov Report
@@ Coverage Diff @@
## master #9708 +/- ##
========================================
Coverage ? 60.6%
========================================
Files ? 552
Lines ? 29833
Branches ? 4514
========================================
Hits ? 18079
Misses ? 10743
Partials ? 1011
Continue to review full report at Codecov.
|
this.notebookProvider.onDidOpenNotebookEditor(this.onDidOpenNotebook.bind(this)); | ||
this.interactiveProvider.onDidChangeActiveInteractiveWindow(this.onDidOpenOrCloseInteractive.bind(this)); | ||
} | ||
public activate(): Promise<void> { |
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 seems off in remote connection cases. Just making sure that I'm reading this right, but it looks like it would be starting up local servers if you opened a notebook and had just connected it remote. Is that correct? #Resolved
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.
No. The serverstart only starts a local server if the options for starting don't include a server URI
In reply to: 369711529 [](ancestors = 369711529)
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 I should update the comment here to say that.
In reply to: 369713520 [](ancestors = 369713520,369711529)
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.
cancelToken?: CancellationToken, | ||
currentKernel?: IJupyterKernelSpec | LiveKernelModel | ||
): Promise<KernelSpecInterpreter> { | ||
let suggestions = await this.selectionProvider.getKernelSelectionsForRemoteSession(session, cancelToken); | ||
suggestions = suggestions.filter(item => !this.kernelIdsToHide.has(item.selection.kernelModel?.id || '')); | ||
return this.selectKernel(suggestions, session, cancelToken, currentKernel); | ||
return this.selectKernel(suggestions, session, disableUI, cancelToken, currentKernel); |
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.
Why not just avoid calling these methods. After all, selectRemoteKernel
will display a picker, thats what its mean to do.
We can avoid passing these flags by not calling the methods higher up. #Resolved
cancelToken?: CancellationToken, | ||
currentKernel?: IJupyterKernelSpec | LiveKernelModel | ||
): Promise<KernelSpecInterpreter> { | ||
let suggestions = await this.selectionProvider.getKernelSelectionsForLocalSession(session, cancelToken); | ||
suggestions = suggestions.filter(item => !this.kernelIdsToHide.has(item.selection.kernelModel?.id || '')); | ||
return this.selectKernel(suggestions, session, cancelToken, currentKernel); | ||
return this.selectKernel(suggestions, session, disableUI, cancelToken, currentKernel); |
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.
Why not just avoid calling these methods. After all, selectRemoteKernel
will display a picker, thats what its mean to do.
We can avoid passing these flags by not calling the methods higher up. #Resolved
} else { | ||
telemetryProps.promptedToSelect = true; | ||
selection = await this.selectLocalKernel(sessionManager, cancelToken); | ||
selection = await this.selectLocalKernel(sessionManager, disableUI, cancelToken); |
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.
No need to call this method as user needs to select a kernel, hence the name selectLocalKernel
. #Resolved
@@ -126,7 +132,7 @@ export class JupyterExecutionBase implements IJupyterExecution { | |||
// Get hold of the kernelspec and corresponding (matching) interpreter that'll be used as the spec. | |||
// We can do this in parallel, while starting the server (faster). | |||
traceInfo(`Getting kernel specs for ${options ? options.purpose : 'unknown type of'} server`); | |||
kernelSpecInterpreterPromise = this.kernelSelector.getKernelForLocalConnection(undefined, options?.metadata, kernelSpecCancelSource.token); | |||
kernelSpecInterpreterPromise = this.kernelSelector.getKernelForLocalConnection(undefined, options?.metadata, !allowUI, kernelSpecCancelSource.token); |
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.
Why not just abort starting server if there's no kernel information.
I.e. in non-ui mode we cannot have a server without any kernels, hence we can just abort here (or just after the kernel promise has resolved).
I think that'll be more readable as well, indicating the fact that in non-ui mode it is mandatory. #Resolved
|
||
// See if the old options had the same UI setting. If not, | ||
// cancel the old | ||
if (data && data.options.disableUI !== fixedOptions.disableUI) { |
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 think maybe I should add a unit test for this stuff. It'd be rather hairy to try and get a functional tset with the right timing on this. #Resolved
@DonJayamanne did you have any more comments? |
Kudos, SonarCloud Quality Gate passed!
|
For #7232
We will now start the jupyter server process (well the daemon in most cases) when:
On my machine (once the server has started), execution is basically instantaneous.