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

Check our saved jupyter interpreters before allowing any of them to be used as active interpreters #10113

Merged

Conversation

IanMatthewHuff
Copy link
Member

@IanMatthewHuff IanMatthewHuff commented Feb 13, 2020

For #9904

Skip news as this is the second PR for this item.

  • Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR).
  • Title summarizes what is changing.
  • Has a news entry file (remember to thank yourself!).
  • Appropriate comments and documentation strings in the code.
  • Has sufficient logging.
  • Has telemetry for enhancements.
  • Unit tests & system/integration tests are added/updated.
  • Test plan is updated as appropriate.
  • package-lock.json has been regenerated by running npm install (if dependencies have changed).
  • The wiki is updated with any design decisions/details.

@IanMatthewHuff IanMatthewHuff changed the title initial idea DRAFT initial idea Feb 13, 2020
@@ -28,6 +28,7 @@ export class Activation implements IExtensionSingleActivationService {
public async activate(): Promise<void> {
this.disposables.push(this.notebookProvider.onDidOpenNotebookEditor(this.onDidOpenNotebookEditor, this));
this.disposables.push(this.jupyterInterpreterService.onDidChangeInterpreter(this.onDidChangeInterpreter, this));
this.testSavedInterpreter();
Copy link
Member Author

Choose a reason for hiding this comment

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

Note: not sure on the placement here. Maybe at the same time as PreWarmDaemonPool?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd like to just make it part of the getSelectedInterpreter. But if I do that, I'm not sure if we are gaining anything from saving it, since we still would verify the first time that we run it and get the slowdown.

Copy link

Choose a reason for hiding this comment

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

Couldn't you also get into a problem here if auto start is turned on? Auto start would use the saved interpreter before you reset it?


In reply to: 379103857 [](ancestors = 379103857)

Copy link

@rchiodo rchiodo Feb 13, 2020

Choose a reason for hiding this comment

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

Maybe have the auto start stuff wait for the check too?


In reply to: 379116829 [](ancestors = 379116829,379103857)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I feel like this currently doesn't guarantee a good interpreter. But making things wait for it would reduce / remove the benefit of saving a good server I would think.

Copy link

Choose a reason for hiding this comment

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

Just the auto start case. Normal startup should not wait.


In reply to: 379118437 [](ancestors = 379118437)

Choose a reason for hiding this comment

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

To me it makes sense to have it in activate

Copy link
Member Author

Choose a reason for hiding this comment

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

@rchiodo . How about this. The saved interpreter check is a promise that we save (like ensureNotebook) and we fire it off on activate right away. Then getSelectedInterpreter always awaits on that promise before returning its result. This way we ensure that getSelectedInterpreter is returning something valid for all the notebook launch cases as well as stuff like preWarmVariables and the auto start server. If I do this, by the time the user is actually starting a notebook it should have completed, since it launched on activate so we still get the benefit of the saved server.

Copy link

Choose a reason for hiding this comment

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

Sounds good to me 👍

@IanMatthewHuff
Copy link
Member Author

I was starting to put some work in here on figuring out what to do when the saved server is bogus (aside from the message that I already added). I don't believe this is the full solution, but wanted to discuss it a bit.

Some things that I don't like about this idea.

  1. Timing. Lots of different areas access getSelectedInterpreter could something like prewarm already call getSelectedInterpreter before we check it? Or while we are checking it? If we run it at extension load, even as ignoreErrors is that slowing down our load?
  2. Does this actually ensure valid? I don't think that it does. This did do the trick for somethings that I tried, like blowing away python from an enlistment. But might not catch the kernel spec issue or other possible launch failures.

@codecov-io
Copy link

codecov-io commented Feb 13, 2020

Codecov Report

Merging #10113 into master will increase coverage by 0.01%.
The diff coverage is 86.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #10113      +/-   ##
==========================================
+ Coverage   61.37%   61.39%   +0.01%     
==========================================
  Files         565      567       +2     
  Lines       30559    30729     +170     
  Branches     4385     4404      +19     
==========================================
+ Hits        18757    18867     +110     
- Misses      10823    10878      +55     
- Partials      979      984       +5
Impacted Files Coverage Δ
src/client/common/process/types.ts 100% <ø> (ø) ⬆️
...upyter/interpreter/jupyterInterpreterStateStore.ts 73.33% <0%> (ø) ⬆️
src/client/datascience/activation.ts 94.28% <100%> (+0.16%) ⬆️
...e/jupyter/interpreter/jupyterInterpreterService.ts 89.02% <88.37%> (+38.32%) ⬆️
.../datascience/jupyter/interpreter/jupyterCommand.ts 50% <0%> (-5.24%) ⬇️
src/client/common/installer/productInstaller.ts 92.79% <0%> (-3.64%) ⬇️
...eter/jupyterCommandInterpreterDependencyService.ts 54.76% <0%> (-2.39%) ⬇️
src/client/datascience/jupyter/notebookStarter.ts 65.25% <0%> (-2.32%) ⬇️
...ient/datascience/jupyter/kernels/kernelSelector.ts 75.8% <0%> (-1.78%) ⬇️
...ient/datascience/interactive-ipynb/nativeEditor.ts 56.31% <0%> (-0.74%) ⬇️
... and 15 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c8e7e5e...331e7f7. Read the comment docs.

@IanMatthewHuff
Copy link
Member Author

Actually this did check and clear on a kernelspec issue.

@@ -64,7 +73,17 @@ export class JupyterInterpreterService {
return interpreter;
}

const pythonPath = this._selectedInterpreterPath || this.interpreterSelectionState.selectedPythonPath;
let pythonPath = this._selectedInterpreterPath;
Copy link

Choose a reason for hiding this comment

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

_selectedInterpreterPath [](start = 30, length = 24)

Seems like you need to check validate regardless? Or is it because _selectedInterpreterPath always starts out as empty on startup?

Copy link

Choose a reason for hiding this comment

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

It seems weird that this check is here at all because it's checked at the beginning of this function. Unless getInterpreterFromChangeOfOlderVersionOfExtension is setting it, but in that case, then you need to validate the old version.


In reply to: 379153900 [](ancestors = 379153900)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I think it only gets set once we pass though this function once. I'll triple check.

Copy link
Member Author

Choose a reason for hiding this comment

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

"it's checked at the beginning of this function" Are you confusing _selectedInterpreterPath with _selectedInterpreter? Only _selectedInterpreter is checked at the start of this function. But looking at it now it looks like getInterpreterFromChangeOfOlderVersionOfExtension does set the path, so I need to validate both cases here not just the saved one.

Copy link

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

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

🕐

@rchiodo
Copy link

rchiodo commented Feb 13, 2020

    if (interpreter) {

I think you need to validate this one too?


Refers to: src/client/datascience/jupyter/interpreter/jupyterInterpreterService.ts:72 in 8bc139a. [](commit_id = 8bc139a, deletion_comment = False)

@IanMatthewHuff IanMatthewHuff added the no-changelog No news entry required label Feb 14, 2020
return this._selectedInterpreter;
}
// Before we return _selected interpreter make sure that we have run our initial set interpreter once
await this.setInitialInterpreter(token);
Copy link
Member Author

Choose a reason for hiding this comment

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

I liked the promise at this level better. getSelectedInterpreter is basically a property here, having to swap out the promise results if you set the interpreter later feels like a weird pattern. Instead, just promise wrap the unit of work that we expect to only perform once per extension activation which will always have the same result, and make sure that it happens before we return the property for the first time.

Copy link

Choose a reason for hiding this comment

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

Could you just return the value of the promise?


In reply to: 379544662 [](ancestors = 379544662)

Copy link

Choose a reason for hiding this comment

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

Or is that not true because the promise may finish and then later something else updates the value?


In reply to: 379547528 [](ancestors = 379547528,379544662)

Copy link

Choose a reason for hiding this comment

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

That feels kinda confusing. Maybe a comment explaining how the two are separate. The initial promise must always be run, but the actual selection can be updated at any time.


In reply to: 379548204 [](ancestors = 379548204,379547528,379544662)

@IanMatthewHuff IanMatthewHuff marked this pull request as ready for review February 14, 2020 17:08

if (currentInterpreter) {
// Ask and give a chance to install dependencies in current interpreter
if (await this.interpreterConfiguration.areDependenciesInstalled(currentInterpreter, token)) {
Copy link

Choose a reason for hiding this comment

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

Should you use validate here instead of checking dependencies? Or is that overkill because you already have th einterpreter?

@IanMatthewHuff IanMatthewHuff changed the title DRAFT initial idea Check our saved jupyter interpreters before allowing any of them to be used as active interpreters Feb 14, 2020
@sonarcloud
Copy link

sonarcloud bot commented Feb 14, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

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

:shipit:

@IanMatthewHuff IanMatthewHuff merged commit 8bf0209 into microsoft:master Feb 14, 2020
@IanMatthewHuff IanMatthewHuff deleted the dev/ianhu/savedServerFail branch February 14, 2020 21:38
rchiodo pushed a commit that referenced this pull request Feb 15, 2020
rchiodo added a commit that referenced this pull request Feb 18, 2020
* Better messaging on notebook fail (#10056)

* Install jupyter instead of installing kernel spec (#10080)

* Install jupyter instead of installing kernel spec
For #10071

* Eliminate variable value when computing data frame info (#10081)

* Fix ndarray types to be viewable again (#10093)

* Eliminate variable value when computing data frame info

* Fix ndarrays to work again
Add test to make sure we don't regress this again

* Rchiodo/kernel telemetry (#10115)

* Add duration to select local/remote kernel

* Add notebook language telemetry

* Add news entries

* #9883 telemetry

* News entry

* Another spot for kernel spec failure

* Add telemetry on product install

* Fix install telemetry

* Undo launch.json change

* Handle other cases

* Better way to handle case

* Wrong event for jupyter install

* Fix unit tests

* Clear variables when restarting regardless if visible or not (#10117)

* Use different method for checking if kernelspec is available (#10114)

* Use different method for checking if kernelspec is available

* Fix unit tests

* More logging for kernelspec problems (#10132)

* More logging for kernelspec problems

* Actually capture the exception on the new code

* Not actually using output if first exception still there.

* Actually only return output on one of the expected calls.

* Fix nightly flake

* Check our saved jupyter interpreters before allowing any of them to be used as active interpreters (#10113)

* Update changelog and package.json

* Missing part of changelog

* Fix tests and linter problems

Co-authored-by: Ian Huff <ian.huff@gmail.com>
Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com>
@lock lock bot locked as resolved and limited conversation to collaborators Feb 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
no-changelog No news entry required
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants