-
Notifications
You must be signed in to change notification settings - Fork 297
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
Remove unnecessary nullables #9766
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,10 +25,10 @@ import { | |
INotebookServerOptions, | ||
INotebookServer, | ||
JupyterServerUriHandle, | ||
INotebookStarter | ||
INotebookStarter, | ||
INotebookServerFactory | ||
} from '../types'; | ||
import { IJupyterSubCommandExecutionService } from '../types.node'; | ||
import { IServiceContainer } from '../../../platform/ioc/types'; | ||
|
||
const LocalHosts = ['localhost', '127.0.0.1', '::1']; | ||
|
||
|
@@ -45,7 +45,7 @@ export class JupyterExecutionBase implements IJupyterExecution { | |
private readonly notebookStarter: INotebookStarter | undefined, | ||
private readonly jupyterInterpreterService: IJupyterSubCommandExecutionService | undefined, | ||
private readonly jupyterPickerRegistration: IJupyterUriProviderRegistration, | ||
private readonly serviceContainer: IServiceContainer | ||
private readonly notebookServerFactory: INotebookServerFactory | ||
) { | ||
this.disposableRegistry.push(this.interpreterService.onDidChangeInterpreter(() => this.onSettingsChanged())); | ||
this.disposableRegistry.push(this); | ||
|
@@ -101,7 +101,7 @@ export class JupyterExecutionBase implements IJupyterExecution { | |
public connectToNotebookServer( | ||
options: INotebookServerOptions, | ||
cancelToken: CancellationToken | ||
): Promise<INotebookServer | undefined> { | ||
): Promise<INotebookServer> { | ||
// Return nothing if we cancel | ||
// eslint-disable-next-line | ||
return Cancellation.race(async () => { | ||
|
@@ -122,12 +122,11 @@ export class JupyterExecutionBase implements IJupyterExecution { | |
if (!connection.localLaunch && LocalHosts.includes(connection.hostName.toLowerCase())) { | ||
sendTelemetryEvent(Telemetry.ConnectRemoteJupyterViaLocalHost); | ||
} | ||
// Create a server tha t we will then attempt to connect to. | ||
result = this.serviceContainer.get<INotebookServer>(INotebookServer); | ||
|
||
// eslint-disable-next-line no-constant-condition | ||
traceInfo(`Connecting to process server`); | ||
await result.connect(connection, cancelToken); | ||
|
||
// Create a server tha t we will then attempt to connect to. | ||
result = await this.notebookServerFactory.createNotebookServer(connection); | ||
traceInfo(`Connection complete server`); | ||
|
||
sendTelemetryEvent( | ||
|
@@ -152,7 +151,7 @@ export class JupyterExecutionBase implements IJupyterExecution { | |
} else if (connection) { | ||
// If this is occurring during shutdown, don't worry about it. | ||
if (this.disposed) { | ||
return undefined; | ||
throw err; | ||
} | ||
|
||
// Something else went wrong | ||
|
@@ -182,6 +181,7 @@ export class JupyterExecutionBase implements IJupyterExecution { | |
} | ||
throw lastTryError; | ||
} | ||
throw new Error('Max number of attempts reached'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function was the root cause, we have an explicit |
||
}, cancelToken); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
import '../../../../platform/common/extensions'; | ||
|
||
import { CancellationToken } from 'vscode-jsonrpc'; | ||
import { injectable, inject, named } from 'inversify'; | ||
import { inject, named } from 'inversify'; | ||
import { IWorkspaceService } from '../../../../platform/common/application/types'; | ||
import { STANDARD_OUTPUT_CHANNEL } from '../../../../platform/common/constants'; | ||
import { traceInfo, traceError, traceInfoIfCI } from '../../../../platform/logging'; | ||
|
@@ -16,7 +16,7 @@ import { | |
IDisposable, | ||
IDisplayOptions | ||
} from '../../../../platform/common/types'; | ||
import { Deferred, createDeferred, sleep } from '../../../../platform/common/utils/async'; | ||
import { createDeferred, sleep } from '../../../../platform/common/utils/async'; | ||
import { DataScience } from '../../../../platform/common/utils/localize'; | ||
import { StopWatch } from '../../../../platform/common/utils/stopWatch'; | ||
import { SessionDisposedError } from '../../../../platform/errors/sessionDisposedError'; | ||
|
@@ -34,27 +34,34 @@ import { JupyterNotebook } from '../jupyterNotebook'; | |
import { noop } from '../../../../platform/common/utils/misc'; | ||
import { Cancellation } from '../../../../platform/common/cancellation'; | ||
import { getDisplayPath } from '../../../../platform/common/platform/fs-paths'; | ||
import { INotebookServer, IJupyterSessionManagerFactory } from '../../types'; | ||
import { INotebookServer } from '../../types'; | ||
import { Uri } from 'vscode'; | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
|
||
@injectable() | ||
export class HostJupyterServer implements INotebookServer { | ||
private connection: IJupyterConnection | undefined; | ||
private connectPromise: Deferred<IJupyterConnection> = createDeferred<IJupyterConnection>(); | ||
private connectionInfoDisconnectHandler: IDisposable | undefined; | ||
private serverExitCode: number | undefined; | ||
private notebooks = new Set<Promise<INotebook>>(); | ||
private sessionManager: JupyterSessionManager | undefined; | ||
private disposed = false; | ||
constructor( | ||
@inject(IAsyncDisposableRegistry) private readonly asyncRegistry: IAsyncDisposableRegistry, | ||
@inject(IJupyterSessionManagerFactory) private readonly sessionManagerFactory: IJupyterSessionManagerFactory, | ||
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService, | ||
@inject(IOutputChannel) @named(STANDARD_OUTPUT_CHANNEL) private readonly jupyterOutputChannel: IOutputChannel, | ||
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry | ||
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry, | ||
public connection: IJupyterConnection, | ||
private sessionManager: JupyterSessionManager | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The connection property is accessed using Refactored this class to be created via a factory so that it can never be nullable, as a result the code paths are much simpler now. |
||
) { | ||
this.asyncRegistry.push(this); | ||
|
||
this.connectionInfoDisconnectHandler = this.connection.disconnected((c) => { | ||
try { | ||
this.serverExitCode = c; | ||
traceError(DataScience.jupyterServerCrashed().format(c.toString())); | ||
this.shutdown().ignoreErrors(); | ||
} catch { | ||
noop(); | ||
} | ||
}); | ||
} | ||
|
||
public async dispose(): Promise<void> { | ||
|
@@ -89,7 +96,7 @@ export class HostJupyterServer implements INotebookServer { | |
// Save the notebook | ||
this.trackDisposable(notebookPromise.promise); | ||
const getExistingSession = async () => { | ||
const connection = await this.computeLaunchInfo(); | ||
const connection = this.connection; | ||
this.throwIfDisposedOrCancelled(cancelToken); | ||
// Figure out the working directory we need for our new notebook. This is only necessary for local. | ||
const workingDirectory = isLocalConnection(kernelConnection) | ||
|
@@ -131,41 +138,6 @@ export class HostJupyterServer implements INotebookServer { | |
return notebookPromise.promise; | ||
} | ||
|
||
private async computeLaunchInfo(): Promise<IJupyterConnection> { | ||
// First we need our launch information so we can start a new session (that's what our notebook is really) | ||
let launchInfo = await this.waitForConnect(); | ||
if (!launchInfo) { | ||
throw this.getDisposedError(); | ||
} | ||
return launchInfo; | ||
} | ||
|
||
public async connect(connection: IJupyterConnection, _cancelToken: CancellationToken): Promise<void> { | ||
traceInfo(`Connecting server kernel ${connection.baseUrl}`); | ||
|
||
// Save our launch info | ||
this.connection = connection; | ||
|
||
// Indicate connect started | ||
this.connectPromise.resolve(connection); | ||
|
||
this.connectionInfoDisconnectHandler = this.connection.disconnected((c) => { | ||
try { | ||
this.serverExitCode = c; | ||
traceError(DataScience.jupyterServerCrashed().format(c.toString())); | ||
this.shutdown().ignoreErrors(); | ||
} catch { | ||
noop(); | ||
} | ||
}); | ||
|
||
// Indicate we have a new session on the output channel | ||
this.logRemoteOutput(DataScience.connectingToJupyterUri().format(connection.baseUrl)); | ||
|
||
// Create our session manager | ||
this.sessionManager = (await this.sessionManagerFactory.create(connection)) as JupyterSessionManager; | ||
} | ||
|
||
public async createNotebook( | ||
resource: Resource, | ||
kernelConnection: KernelConnectionMetadata, | ||
|
@@ -235,28 +207,22 @@ export class HostJupyterServer implements INotebookServer { | |
if (result === 10_000) { | ||
traceError(`Session shutdown timed out.`); | ||
} | ||
this.sessionManager = undefined; | ||
} | ||
|
||
// After shutting down notebooks and session manager, kill the main process. | ||
if (this.connection && this.connection) { | ||
traceInfo('Shutdown server - dispose conn info'); | ||
this.connection.dispose(); // This should kill the process that's running | ||
this.connection = undefined; | ||
} | ||
} catch (e) { | ||
traceError(`Error during shutdown: `, e); | ||
} | ||
} | ||
|
||
private waitForConnect(): Promise<IJupyterConnection | undefined> { | ||
return this.connectPromise.promise; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Funky code now a thing of the past due to nullables being removed. |
||
} | ||
|
||
// Return a copy of the connection information that this server used to connect with | ||
public getConnectionInfo(): IJupyterConnection | undefined { | ||
public getConnectionInfo(): IJupyterConnection { | ||
if (!this.connection) { | ||
return undefined; | ||
throw new Error('Not connected'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. THis is impossible, when the class is contructed, the first things that called is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This class is now instantiated via a factory, hence |
||
} | ||
|
||
// Return a copy with a no-op for dispose | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
import { inject, injectable, named } from 'inversify'; | ||
import {} from 'underscore'; | ||
import { IWorkspaceService } from '../../../../platform/common/application/types'; | ||
import { STANDARD_OUTPUT_CHANNEL } from '../../../../platform/common/constants'; | ||
import { IAsyncDisposableRegistry, IDisposableRegistry, IOutputChannel } from '../../../../platform/common/types'; | ||
import { DataScience } from '../../../../platform/common/utils/localize'; | ||
import { traceInfo } from '../../../../platform/logging'; | ||
import { IJupyterConnection } from '../../../types'; | ||
import { JupyterSessionManager } from '../../session/jupyterSessionManager'; | ||
import { IJupyterSessionManagerFactory, INotebookServer, INotebookServerFactory } from '../../types'; | ||
import { HostJupyterServer } from './hostJupyterServer'; | ||
|
||
@injectable() | ||
export class HostJupyterServerFactory implements INotebookServerFactory { | ||
constructor( | ||
@inject(IAsyncDisposableRegistry) private readonly asyncRegistry: IAsyncDisposableRegistry, | ||
@inject(IJupyterSessionManagerFactory) private readonly sessionManagerFactory: IJupyterSessionManagerFactory, | ||
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService, | ||
@inject(IOutputChannel) @named(STANDARD_OUTPUT_CHANNEL) private readonly jupyterOutputChannel: IOutputChannel, | ||
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry | ||
) {} | ||
public async createNotebookServer(connection: IJupyterConnection): Promise<INotebookServer> { | ||
traceInfo(`Connecting server kernel ${connection.baseUrl}`); | ||
|
||
// Indicate we have a new session on the output channel | ||
if (!connection.localLaunch) { | ||
this.jupyterOutputChannel.appendLine(DataScience.connectingToJupyterUri().format(connection.baseUrl)); | ||
} | ||
// Create our session manager | ||
const sessionManager = (await this.sessionManagerFactory.create(connection)) as JupyterSessionManager; | ||
// Create a server tha t we will then attempt to connect to. | ||
return new HostJupyterServer( | ||
this.asyncRegistry, | ||
this.workspaceService, | ||
this.jupyterOutputChannel, | ||
this.disposables, | ||
connection, | ||
sessionManager | ||
); | ||
} | ||
} |
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.
update comment? (Or just remove)