Restart kernel initial implementation (#18835)

* Restart kernel initial implementation

* Update notebook extension TestKernel

* PR comments
This commit is contained in:
Chris LaFreniere
2022-03-29 12:56:52 -07:00
committed by GitHub
parent 8537a30996
commit af3d307d40
14 changed files with 95 additions and 14 deletions

View File

@@ -484,6 +484,10 @@ class KernelWrapper implements azdata.nb.IKernel {
interrupt(): Thenable<void> {
return this._proxy.ext.$interruptKernel(this.kernelDetails.kernelId);
}
restart(): Thenable<void> {
return this._proxy.ext.$restartKernel(this.kernelDetails.kernelId);
}
}

View File

@@ -213,6 +213,11 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
return kernel.interrupt();
}
$restartKernel(kernelId: number): Thenable<void> {
let kernel = this._getAdapter<azdata.nb.IKernel>(kernelId);
return kernel.restart();
}
$sendInputReply(futureId: number, content: azdata.nb.IInputReply): void {
let future = this._getAdapter<azdata.nb.IFuture>(futureId);
return future.sendInputReply(content);

View File

@@ -156,6 +156,10 @@ class VSCodeKernel implements azdata.nb.IKernel {
public async interrupt(): Promise<void> {
return;
}
public async restart(): Promise<void> {
return;
}
}
class VSCodeSession implements azdata.nb.ISession {

View File

@@ -952,6 +952,7 @@ export interface ExtHostNotebookShape {
$requestComplete(kernelId: number, content: azdata.nb.ICompleteRequest): Thenable<azdata.nb.ICompleteReplyMsg>;
$requestExecute(kernelId: number, content: azdata.nb.IExecuteRequest, disposeOnDone?: boolean): Thenable<INotebookFutureDetails>;
$interruptKernel(kernelId: number): Thenable<void>;
$restartKernel(kernelId: number): Thenable<void>;
// Future APIs
$sendInputReply(futureId: number, content: azdata.nb.IInputReply): void;

View File

@@ -239,6 +239,24 @@ CommandsRegistry.registerCommand({
}
});
CommandsRegistry.registerCommand({
id: 'notebook.restartKernel',
handler: async (accessor: ServicesAccessor) => {
const editorService: IEditorService = accessor.get(IEditorService);
if (editorService.activeEditor instanceof NotebookInput) {
await editorService.activeEditor.notebookModel?.clientSession?.restart();
}
}
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: 'notebook.restartKernel',
title: localize('restartNotebookKernel', "Restart Notebook Kernel"),
},
when: ContextKeyExpr.and(ActiveEditorContext.isEqualTo(NotebookEditor.ID))
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: TOGGLE_TAB_FOCUS_COMMAND_ID,

View File

@@ -168,6 +168,10 @@ class EmptyKernel implements nb.IKernel {
interrupt(): Thenable<void> {
return Promise.resolve(undefined);
}
restart(): Thenable<void> {
return Promise.resolve(undefined);
}
}
export class EmptyFuture implements FutureInternal {

View File

@@ -353,7 +353,7 @@ export class ClientSessionStub implements IClientSession {
selectKernel(): Promise<void> {
throw new Error('Method not implemented.');
}
restart(): Promise<boolean> {
restart(): Promise<void> {
throw new Error('Method not implemented.');
}
setPath(path: string): Promise<void> {
@@ -464,6 +464,9 @@ export class KernelStub implements nb.IKernel {
interrupt(): Thenable<void> {
throw new Error('Method not implemented.');
}
restart(): Thenable<void> {
throw new Error('Method not implemented.');
}
}
export class FutureStub implements nb.IFuture {

View File

@@ -323,16 +323,27 @@ export class ClientSession implements IClientSession {
/**
* Restart the session.
*
* @returns A promise that resolves with whether the kernel has restarted.
* @returns A promise that resolves when the kernel has restarted.
*
* #### Notes
* If there is a running kernel, present a dialog.
* If there is no kernel, we start a kernel with the last run
* kernel name and resolves with `true`. If no kernel has been started,
* this is a no-op, and resolves with `false`.
* If there is an existing kernel, restart it and resolve.
* If no kernel has been started, this is a no-op, and resolves.
* Reject on error.
*/
restart(): Promise<boolean> {
throw new Error('Not implemented');
restart(): Promise<void> {
if (!this._session?.kernel) {
// no-op if no kernel is present
return Promise.resolve();
}
let restartCompleted = new Deferred<void>();
this._session?.kernel?.restart().then(() => {
this.options.notificationService.info(localize('kernelRestartedSuccessfully', 'Kernel restarted successfully'));
restartCompleted.resolve();
}, err => {
this.options.notificationService.error(localize('kernelRestartFailed', 'Kernel restart failed: {0}', err));
restartCompleted.reject(err);
});
return restartCompleted.promise;
}
/**

View File

@@ -179,15 +179,14 @@ export interface IClientSession extends IDisposable {
/**
* Restart the session.
*
* @returns A promise that resolves with whether the kernel has restarted.
* @returns A promise that resolves when the kernel has restarted.
*
* #### Notes
* If there is a running kernel, present a dialog.
* If there is no kernel, we start a kernel with the last run
* kernel name and resolves with `true`. If no kernel has been started,
* this is a no-op, and resolves with `false`.
* If there is an existing kernel, restart it and resolve.
* If no kernel has been started, this is a no-op, and resolves.
* Reject on error.
*/
restart(): Promise<boolean>;
restart(): Promise<void>;
/**
* Change the session path.

View File

@@ -382,6 +382,10 @@ class SqlKernel extends Disposable implements nb.IKernel {
});
}
restart(): Thenable<void> {
return Promise.reject(localize('SqlKernelRestartNotSupported', 'SQL kernel restart not supported'));
}
private addQueryEventListeners(queryRunner: QueryRunner): void {
this._register(queryRunner.onQueryEnd(() => {
this.queryComplete().catch(error => {

View File

@@ -252,6 +252,9 @@ class ExtHostNotebookStub implements ExtHostNotebookShape {
$interruptKernel(kernelId: number): Thenable<void> {
throw new Error('Method not implemented.');
}
$restartKernel(kernelId: number): Thenable<void> {
throw new Error('Method not implemented.');
}
$sendInputReply(futureId: number, content: azdata.nb.IInputReply): void {
throw new Error('Method not implemented.');
}