Skip to content

Commit 68f4339

Browse files
authored
manage scheduling of getting children to prevent too many requests (#202904)
1 parent f284d7b commit 68f4339

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

src/vs/workbench/contrib/notebook/browser/contrib/notebookVariables/notebookVariablesDataSource.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
7-
import { CancellationToken } from 'vs/base/common/cancellation';
7+
import { CancellationTokenSource } from 'vs/base/common/cancellation';
88
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
99
import { INotebookKernel, INotebookKernelService, VariablesResult, variablePageSize } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
1010

@@ -28,12 +28,22 @@ export interface INotebookVariableElement {
2828

2929
export class NotebookVariableDataSource implements IAsyncDataSource<INotebookScope, INotebookVariableElement> {
3030

31-
constructor(private readonly notebookKernelService: INotebookKernelService) { }
31+
private cancellationTokenSource: CancellationTokenSource;
32+
33+
constructor(private readonly notebookKernelService: INotebookKernelService) {
34+
this.cancellationTokenSource = new CancellationTokenSource();
35+
}
3236

3337
hasChildren(element: INotebookScope | INotebookVariableElement): boolean {
3438
return element.kind === 'root' || element.hasNamedChildren || element.indexedChildrenCount > 0;
3539
}
3640

41+
public cancel(): void {
42+
this.cancellationTokenSource.cancel();
43+
this.cancellationTokenSource.dispose();
44+
this.cancellationTokenSource = new CancellationTokenSource();
45+
}
46+
3747
async getChildren(element: INotebookScope | INotebookVariableElement): Promise<Array<INotebookVariableElement>> {
3848
if (element.kind === 'root') {
3949
return this.getRootVariables(element.notebook);
@@ -48,7 +58,7 @@ export class NotebookVariableDataSource implements IAsyncDataSource<INotebookSco
4858

4959
let children: INotebookVariableElement[] = [];
5060
if (parent.hasNamedChildren) {
51-
const variables = selectedKernel.provideVariables(parent.notebook.uri, parent.extHostId, 'named', 0, CancellationToken.None);
61+
const variables = selectedKernel.provideVariables(parent.notebook.uri, parent.extHostId, 'named', 0, this.cancellationTokenSource.token);
5262
const childNodes = await variables
5363
.map(variable => { return this.createVariableElement(variable, parent.notebook); })
5464
.toPromise();
@@ -88,7 +98,7 @@ export class NotebookVariableDataSource implements IAsyncDataSource<INotebookSco
8898
}
8999
}
90100
else if (parent.indexedChildrenCount > 0) {
91-
const variables = kernel.provideVariables(parent.notebook.uri, parent.extHostId, 'indexed', parent.indexStart ?? 0, CancellationToken.None);
101+
const variables = kernel.provideVariables(parent.notebook.uri, parent.extHostId, 'indexed', parent.indexStart ?? 0, this.cancellationTokenSource.token);
92102

93103
for await (const variable of variables) {
94104
childNodes.push(this.createVariableElement(variable, parent.notebook));
@@ -104,7 +114,7 @@ export class NotebookVariableDataSource implements IAsyncDataSource<INotebookSco
104114
async getRootVariables(notebook: NotebookTextModel): Promise<INotebookVariableElement[]> {
105115
const selectedKernel = this.notebookKernelService.getMatchingKernel(notebook).selected;
106116
if (selectedKernel && selectedKernel.hasVariableProvider) {
107-
const variables = selectedKernel.provideVariables(notebook.uri, undefined, 'named', 0, CancellationToken.None);
117+
const variables = selectedKernel.provideVariables(notebook.uri, undefined, 'named', 0, this.cancellationTokenSource.token);
108118
return await variables
109119
.map(variable => { return this.createVariableElement(variable, notebook); })
110120
.toPromise();

src/vs/workbench/contrib/notebook/browser/contrib/notebookVariables/notebookVariablesView.ts

+22-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { RunOnceScheduler } from 'vs/base/common/async';
67
import { URI } from 'vs/base/common/uri';
78
import * as nls from 'vs/nls';
89
import { ILocalizedString } from 'vs/platform/action/common/action';
@@ -34,6 +35,9 @@ export class NotebookVariablesView extends ViewPane {
3435

3536
private tree: WorkbenchAsyncDataTree<INotebookScope, INotebookVariableElement> | undefined;
3637
private activeNotebook: NotebookTextModel | undefined;
38+
private readonly dataSource: NotebookVariableDataSource;
39+
40+
private updateScheduler: RunOnceScheduler;
3741

3842
constructor(
3943
options: IViewPaneOptions,
@@ -59,6 +63,9 @@ export class NotebookVariablesView extends ViewPane {
5963
this._register(this.notebookExecutionStateService.onDidChangeExecution(this.handleExecutionStateChange.bind(this)));
6064

6165
this.setActiveNotebook();
66+
67+
this.dataSource = new NotebookVariableDataSource(this.notebookKernelService);
68+
this.updateScheduler = new RunOnceScheduler(() => this.tree?.updateChildren(), 100);
6269
}
6370

6471
protected override renderBody(container: HTMLElement): void {
@@ -70,7 +77,7 @@ export class NotebookVariablesView extends ViewPane {
7077
container,
7178
new NotebookVariablesDelegate(),
7279
[new NotebookVariableRenderer()],
73-
new NotebookVariableDataSource(this.notebookKernelService),
80+
this.dataSource,
7481
{
7582
accessibilityProvider: new NotebookVariableAccessibilityProvider(),
7683
identityProvider: { getId: (e: INotebookVariableElement) => e.id },
@@ -87,7 +94,7 @@ export class NotebookVariablesView extends ViewPane {
8794
this.tree?.layout(height, width);
8895
}
8996

90-
setActiveNotebook() {
97+
private setActiveNotebook() {
9198
const current = this.activeNotebook;
9299
const activeEditorPane = this.editorService.activeEditorPane;
93100
if (activeEditorPane && activeEditorPane.getId() === 'workbench.editor.notebook') {
@@ -101,23 +108,31 @@ export class NotebookVariablesView extends ViewPane {
101108
private handleActiveEditorChange() {
102109
if (this.setActiveNotebook() && this.activeNotebook) {
103110
this.tree?.setInput({ kind: 'root', notebook: this.activeNotebook });
104-
this.tree?.updateChildren();
111+
this.updateScheduler.schedule();
105112
}
106113
}
107114

108115
private handleExecutionStateChange(event: ICellExecutionStateChangedEvent | IExecutionStateChangedEvent) {
109116
if (this.activeNotebook) {
110-
// changed === undefined -> excecution ended
111-
if (event.changed === undefined && event.affectsNotebook(this.activeNotebook?.uri)) {
112-
this.tree?.updateChildren();
117+
if (event.affectsNotebook(this.activeNotebook.uri)) {
118+
// new execution state means either new variables or the kernel is busy so we shouldn't ask
119+
this.dataSource.cancel();
120+
121+
// changed === undefined -> excecution ended
122+
if (event.changed === undefined) {
123+
this.updateScheduler.schedule();
124+
}
125+
else {
126+
this.updateScheduler.cancel();
127+
}
113128
}
114129
}
115130
}
116131

117132
private handleVariablesChanged(notebookUri: URI) {
118133
if (this.activeNotebook && notebookUri.toString() === this.activeNotebook.uri.toString()) {
119134
this.tree?.setInput({ kind: 'root', notebook: this.activeNotebook });
120-
this.tree?.updateChildren();
135+
this.updateScheduler.schedule();
121136
}
122137
}
123138
}

0 commit comments

Comments
 (0)