Skip to content

Commit 069ab7c

Browse files
authored
Present kernel detection progress in kernel picker/status (microsoft#166294)
* Experimental kernel detection task * Update kernel detection progress * no need for start/end now. * Enforce proposed api
1 parent 73d882b commit 069ab7c

File tree

9 files changed

+119
-2
lines changed

9 files changed

+119
-2
lines changed

src/vs/workbench/api/browser/mainThreadNotebookKernels.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/ext
1515
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
1616
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
1717
import { INotebookCellExecution, INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
18-
import { INotebookKernel, INotebookKernelChangeEvent, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
18+
import { INotebookKernel, INotebookKernelChangeEvent, INotebookKernelDetectionTask, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
1919
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
2020
import { ExtHostContext, ExtHostNotebookKernelsShape, ICellExecuteUpdateDto, ICellExecutionCompleteDto, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape } from '../common/extHost.protocol';
2121
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
@@ -101,13 +101,18 @@ abstract class MainThreadKernel implements INotebookKernel {
101101
abstract cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise<void>;
102102
}
103103

104+
class MainThreadKernelDetectionTask implements INotebookKernelDetectionTask {
105+
constructor(readonly notebookType: string) { }
106+
}
107+
104108
@extHostNamedCustomer(MainContext.MainThreadNotebookKernels)
105109
export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape {
106110

107111
private readonly _editors = new DisposableMap<INotebookEditor>();
108112
private readonly _disposables = new DisposableStore();
109113

110114
private readonly _kernels = new Map<number, [kernel: MainThreadKernel, registraion: IDisposable]>();
115+
private readonly _kernelDetectionTasks = new Map<number, [task: MainThreadKernelDetectionTask, registraion: IDisposable]>();
111116
private readonly _proxy: ExtHostNotebookKernelsShape;
112117

113118
private readonly _executions = new Map<number, INotebookCellExecution>();
@@ -143,6 +148,9 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
143148
for (const [, registration] of this._kernels.values()) {
144149
registration.dispose();
145150
}
151+
for (const [, registration] of this._kernelDetectionTasks.values()) {
152+
registration.dispose();
153+
}
146154
this._editors.dispose();
147155
}
148156

@@ -286,4 +294,19 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
286294
this._executions.delete(handle);
287295
}
288296
}
297+
298+
// --- notebook kernel detection task
299+
async $addKernelDetectionTask(handle: number, notebookType: string): Promise<void> {
300+
const kernelDetectionTask = new MainThreadKernelDetectionTask(notebookType);
301+
const registration = this._notebookKernelService.registerNotebookKernelDetectionTask(kernelDetectionTask);
302+
this._kernelDetectionTasks.set(handle, [kernelDetectionTask, registration]);
303+
}
304+
305+
$removeKernelDetectionTask(handle: number): void {
306+
const tuple = this._kernelDetectionTasks.get(handle);
307+
if (tuple) {
308+
tuple[1].dispose();
309+
this._kernelDetectionTasks.delete(handle);
310+
}
311+
}
289312
}

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
11481148
createRendererMessaging(rendererId) {
11491149
return extHostNotebookRenderers.createRendererMessaging(extension, rendererId);
11501150
},
1151+
createNotebookControllerDetectionTask(notebookType: string) {
1152+
checkProposedApiEnabled(extension, 'notebookKernelSource');
1153+
return extHostNotebookKernels.createNotebookControllerDetectionTask(extension, notebookType);
1154+
},
11511155
onDidChangeNotebookCellExecutionState(listener, thisArgs?, disposables?) {
11521156
checkProposedApiEnabled(extension, 'notebookCellExecutionState');
11531157
return extHostNotebookKernels.onDidChangeNotebookCellExecutionState(listener, thisArgs, disposables);

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,9 @@ export interface MainThreadNotebookKernelsShape extends IDisposable {
10421042
$createExecution(handle: number, controllerId: string, uri: UriComponents, cellHandle: number): void;
10431043
$updateExecution(handle: number, data: SerializableObjectWithBuffers<ICellExecuteUpdateDto[]>): void;
10441044
$completeExecution(handle: number, data: SerializableObjectWithBuffers<ICellExecutionCompleteDto>): void;
1045+
1046+
$addKernelDetectionTask(handle: number, notebookType: string): Promise<void>;
1047+
$removeKernelDetectionTask(handle: number): void;
10451048
}
10461049

10471050
export interface MainThreadNotebookRenderersShape extends IDisposable {

src/vs/workbench/api/common/extHostNotebookKernels.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
4444
private readonly _proxy: MainThreadNotebookKernelsShape;
4545
private readonly _activeExecutions = new ResourceMap<NotebookCellExecutionTask>();
4646

47+
private _kernelDetectionTask = new Map<number, vscode.NotebookControllerDetectionTask>();
48+
private _kernelDetectionTaskHandlePool: number = 0;
49+
4750
private readonly _kernelData = new Map<number, IKernelData>();
4851
private _handlePool: number = 0;
4952

@@ -271,6 +274,24 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
271274
return null;
272275
}
273276

277+
createNotebookControllerDetectionTask(extension: IExtensionDescription, viewType: string): vscode.NotebookControllerDetectionTask {
278+
const handle = this._kernelDetectionTaskHandlePool++;
279+
const that = this;
280+
281+
this._logService.trace(`NotebookControllerDetectionTask[${handle}], CREATED by ${extension.identifier.value}`);
282+
this._proxy.$addKernelDetectionTask(handle, viewType);
283+
284+
const detectionTask: vscode.NotebookControllerDetectionTask = {
285+
dispose: () => {
286+
this._kernelDetectionTask.delete(handle);
287+
that._proxy.$removeKernelDetectionTask(handle);
288+
}
289+
};
290+
291+
this._kernelDetectionTask.set(handle, detectionTask);
292+
return detectionTask;
293+
}
294+
274295
$acceptNotebookAssociation(handle: number, uri: UriComponents, value: boolean): void {
275296
const obj = this._kernelData.get(handle);
276297
if (obj) {

src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ registerAction2(class extends Action2 {
192192
? nls.localize('prompt.placeholder.change', "Change kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true }))
193193
: nls.localize('prompt.placeholder.select', "Select kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true }));
194194

195+
quickPick.busy = notebookKernelService.getKernelDetectionTasks(notebook).length > 0;
196+
197+
const kernelDetectionTaskListener = notebookKernelService.onDidChangeKernelDetectionTasks(() => {
198+
quickPick.busy = notebookKernelService.getKernelDetectionTasks(notebook).length > 0;
199+
});
200+
195201
// run extension recommendataion task if quickPickItems is empty
196202
const extensionRecommendataionPromise = quickPickItems.length === 0
197203
? createCancelablePromise(token => this._showInstallKernelExtensionRecommendation(notebook, quickPick, extensionWorkbenchService, token))
@@ -250,6 +256,7 @@ registerAction2(class extends Action2 {
250256
});
251257

252258
quickPick.onDidHide(() => () => {
259+
kernelDetectionTaskListener.dispose();
253260
kernelChangeEventListener.dispose();
254261
quickPick.dispose();
255262
reject();

src/vs/workbench/contrib/notebook/browser/services/notebookKernelServiceImpl.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { Event, Emitter } from 'vs/base/common/event';
77
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
88
import { INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
9-
import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, ISourceAction, INotebookSourceActionChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
9+
import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, ISourceAction, INotebookSourceActionChangeEvent, INotebookKernelDetectionTask } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
1010
import { LRUCache, ResourceMap } from 'vs/base/common/map';
1111
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
1212
import { URI } from 'vs/base/common/uri';
@@ -105,12 +105,15 @@ export class NotebookKernelService extends Disposable implements INotebookKernel
105105
private readonly _onDidChangeNotebookAffinity = this._register(new Emitter<void>());
106106
private readonly _onDidChangeSourceActions = this._register(new Emitter<INotebookSourceActionChangeEvent>());
107107
private readonly _kernelSources = new Map<string, IKernelInfoCache>();
108+
private readonly _kernelDetectionTasks = new Map<string, INotebookKernelDetectionTask[]>();
109+
private readonly _onDidChangeKernelDetectionTasks = this._register(new Emitter<string>());
108110

109111
readonly onDidChangeSelectedNotebooks: Event<ISelectedNotebooksChangeEvent> = this._onDidChangeNotebookKernelBinding.event;
110112
readonly onDidAddKernel: Event<INotebookKernel> = this._onDidAddKernel.event;
111113
readonly onDidRemoveKernel: Event<INotebookKernel> = this._onDidRemoveKernel.event;
112114
readonly onDidChangeNotebookAffinity: Event<void> = this._onDidChangeNotebookAffinity.event;
113115
readonly onDidChangeSourceActions: Event<INotebookSourceActionChangeEvent> = this._onDidChangeSourceActions.event;
116+
readonly onDidChangeKernelDetectionTasks: Event<string> = this._onDidChangeKernelDetectionTasks.event;
114117

115118
private static _storageNotebookBinding = 'notebook.controller2NotebookBindings';
116119

@@ -342,4 +345,25 @@ export class NotebookKernelService extends Disposable implements INotebookKernel
342345

343346
return info.actions.map(a => a[0]);
344347
}
348+
349+
registerNotebookKernelDetectionTask(task: INotebookKernelDetectionTask): IDisposable {
350+
const notebookType = task.notebookType;
351+
const all = this._kernelDetectionTasks.get(notebookType) ?? [];
352+
all.push(task);
353+
this._kernelDetectionTasks.set(notebookType, all);
354+
this._onDidChangeKernelDetectionTasks.fire(notebookType);
355+
return toDisposable(() => {
356+
const all = this._kernelDetectionTasks.get(notebookType) ?? [];
357+
const idx = all.indexOf(task);
358+
if (idx >= 0) {
359+
all.splice(idx, 1);
360+
this._kernelDetectionTasks.set(notebookType, all);
361+
this._onDidChangeKernelDetectionTasks.fire(notebookType);
362+
}
363+
});
364+
}
365+
366+
getKernelDetectionTasks(notebook: INotebookTextModelLike): INotebookKernelDetectionTask[] {
367+
return this._kernelDetectionTasks.get(notebook.viewType) ?? [];
368+
}
345369
}

src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
3333
this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this));
3434
this._register(_notebookKernelService.onDidChangeSelectedNotebooks(this._update, this));
3535
this._register(_notebookKernelService.onDidChangeSourceActions(this._update, this));
36+
this._register(_notebookKernelService.onDidChangeKernelDetectionTasks(this._update, this));
3637
}
3738

3839
override render(container: HTMLElement): void {
@@ -60,6 +61,11 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
6061
return;
6162
}
6263

64+
const detectionTasks = this._notebookKernelService.getKernelDetectionTasks(notebook);
65+
if (detectionTasks.length) {
66+
return this._updateActionFromDetectionTask();
67+
}
68+
6369
const runningActions = this._notebookKernelService.getRunningSourceActions(notebook);
6470
if (runningActions.length) {
6571
return this._updateActionFromSourceAction(runningActions[0] /** TODO handle multiple actions state */, true);
@@ -73,6 +79,12 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
7379
this._updateActionFromKernelInfo(info);
7480
}
7581

82+
private _updateActionFromDetectionTask() {
83+
this._action.enabled = true;
84+
this._action.label = localize('kernels.detecting', "Detecting Kernels");
85+
this._action.class = ThemeIcon.asClassName(ThemeIcon.modify(executingStateIcon, 'spin'));
86+
}
87+
7688
private _updateActionFromSourceAction(sourceAction: ISourceAction, running: boolean) {
7789
const action = sourceAction.action;
7890
this.action.class = running ? ThemeIcon.asClassName(ThemeIcon.modify(executingStateIcon, 'spin')) : ThemeIcon.asClassName(selectKernelIcon);

src/vs/workbench/contrib/notebook/common/notebookKernelService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export interface INotebookProxyKernelChangeEvent extends INotebookKernelChangeEv
6767
connectionState?: true;
6868
}
6969

70+
export interface INotebookKernelDetectionTask {
71+
readonly notebookType: string;
72+
}
73+
7074
export interface ISourceAction {
7175
readonly action: IAction;
7276
readonly onDidChangeState: Event<void>;
@@ -115,6 +119,12 @@ export interface INotebookKernelService {
115119
*/
116120
updateKernelNotebookAffinity(kernel: INotebookKernel, notebook: URI, preference: number | undefined): void;
117121

122+
//#region Kernel detection tasks
123+
readonly onDidChangeKernelDetectionTasks: Event<string>;
124+
registerNotebookKernelDetectionTask(task: INotebookKernelDetectionTask): IDisposable;
125+
getKernelDetectionTasks(notebook: INotebookTextModelLike): INotebookKernelDetectionTask[];
126+
//#endregion
127+
118128
//#region Kernel source actions
119129
readonly onDidChangeSourceActions: Event<INotebookSourceActionChangeEvent>;
120130
getSourceActions(notebook: INotebookTextModelLike, contextKeyService: IContextKeyService | undefined): ISourceAction[];

src/vscode-dts/vscode.proposed.notebookKernelSource.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,17 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
declare module 'vscode' {
7+
export interface NotebookControllerDetectionTask {
8+
/**
9+
* Dispose and remove the detection task.
10+
*/
11+
dispose(): void;
12+
}
13+
14+
export namespace notebooks {
15+
/**
16+
* Create notebook controller detection task
17+
*/
18+
export function createNotebookControllerDetectionTask(notebookType: string): NotebookControllerDetectionTask;
19+
}
720
}

0 commit comments

Comments
 (0)