Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/services/notebookExecutionStateServiceImpl.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Emitter } from '../../../../../base/common/event.js';
7
import { combinedDisposable, Disposable, IDisposable } from '../../../../../base/common/lifecycle.js';
8
import { ResourceMap } from '../../../../../base/common/map.js';
9
import { isEqual } from '../../../../../base/common/resources.js';
10
import { URI } from '../../../../../base/common/uri.js';
11
import { generateUuid } from '../../../../../base/common/uuid.js';
12
import { AccessibilitySignal, IAccessibilitySignalService } from '../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
13
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
14
import { ILogService } from '../../../../../platform/log/common/log.js';
15
import { NotebookTextModel } from '../../common/model/notebookTextModel.js';
16
import { CellEditType, CellUri, ICellEditOperation, NotebookCellExecutionState, NotebookCellInternalMetadata, NotebookExecutionState, NotebookTextModelWillAddRemoveEvent } from '../../common/notebookCommon.js';
17
import { CellExecutionUpdateType, INotebookExecutionService } from '../../common/notebookExecutionService.js';
18
import { ICellExecuteUpdate, ICellExecutionComplete, ICellExecutionStateChangedEvent, ICellExecutionStateUpdate, IExecutionStateChangedEvent, IFailedCellInfo, INotebookCellExecution, INotebookExecution, INotebookExecutionStateService, INotebookFailStateChangedEvent, NotebookExecutionType } from '../../common/notebookExecutionStateService.js';
19
import { INotebookKernelService } from '../../common/notebookKernelService.js';
20
import { INotebookService } from '../../common/notebookService.js';
21
22
export class NotebookExecutionStateService extends Disposable implements INotebookExecutionStateService {
23
declare _serviceBrand: undefined;
24
25
private readonly _executions = new ResourceMap<Map<number, CellExecution>>();
26
private readonly _notebookExecutions = new ResourceMap<[NotebookExecution, IDisposable]>();
27
private readonly _notebookListeners = new ResourceMap<NotebookExecutionListeners>();
28
private readonly _cellListeners = new ResourceMap<IDisposable>();
29
private readonly _lastFailedCells = new ResourceMap<IFailedCellInfo>();
30
private readonly _lastCompletedCellHandles = new ResourceMap<number>();
31
32
private readonly _onDidChangeExecution = this._register(new Emitter<ICellExecutionStateChangedEvent | IExecutionStateChangedEvent>());
33
onDidChangeExecution = this._onDidChangeExecution.event;
34
35
private readonly _onDidChangeLastRunFailState = this._register(new Emitter<INotebookFailStateChangedEvent>());
36
onDidChangeLastRunFailState = this._onDidChangeLastRunFailState.event;
37
38
constructor(
39
@IInstantiationService private readonly _instantiationService: IInstantiationService,
40
@ILogService private readonly _logService: ILogService,
41
@INotebookService private readonly _notebookService: INotebookService,
42
@IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService
43
) {
44
super();
45
}
46
47
getLastFailedCellForNotebook(notebook: URI): number | undefined {
48
const failedCell = this._lastFailedCells.get(notebook);
49
return failedCell?.visible ? failedCell.cellHandle : undefined;
50
}
51
52
getLastCompletedCellForNotebook(notebook: URI): number | undefined {
53
return this._lastCompletedCellHandles.get(notebook);
54
}
55
56
forceCancelNotebookExecutions(notebookUri: URI): void {
57
const notebookCellExecutions = this._executions.get(notebookUri);
58
if (notebookCellExecutions) {
59
for (const exe of notebookCellExecutions.values()) {
60
this._onCellExecutionDidComplete(notebookUri, exe.cellHandle, exe);
61
}
62
}
63
if (this._notebookExecutions.has(notebookUri)) {
64
this._onExecutionDidComplete(notebookUri);
65
}
66
}
67
68
getCellExecution(cellUri: URI): INotebookCellExecution | undefined {
69
const parsed = CellUri.parse(cellUri);
70
if (!parsed) {
71
throw new Error(`Not a cell URI: ${cellUri}`);
72
}
73
74
const exeMap = this._executions.get(parsed.notebook);
75
if (exeMap) {
76
return exeMap.get(parsed.handle);
77
}
78
79
return undefined;
80
}
81
getExecution(notebook: URI): INotebookExecution | undefined {
82
return this._notebookExecutions.get(notebook)?.[0];
83
}
84
85
getCellExecutionsForNotebook(notebook: URI): INotebookCellExecution[] {
86
const exeMap = this._executions.get(notebook);
87
return exeMap ? Array.from(exeMap.values()) : [];
88
}
89
90
getCellExecutionsByHandleForNotebook(notebook: URI): Map<number, INotebookCellExecution> | undefined {
91
const exeMap = this._executions.get(notebook);
92
return exeMap ? new Map(exeMap.entries()) : undefined;
93
}
94
95
private _onCellExecutionDidChange(notebookUri: URI, cellHandle: number, exe: CellExecution): void {
96
this._onDidChangeExecution.fire(new NotebookCellExecutionEvent(notebookUri, cellHandle, exe));
97
}
98
99
private _onCellExecutionDidComplete(notebookUri: URI, cellHandle: number, exe: CellExecution, lastRunSuccess?: boolean): void {
100
const notebookExecutions = this._executions.get(notebookUri);
101
if (!notebookExecutions) {
102
this._logService.debug(`NotebookExecutionStateService#_onCellExecutionDidComplete - unknown notebook ${notebookUri.toString()}`);
103
return;
104
}
105
106
exe.dispose();
107
const cellUri = CellUri.generate(notebookUri, cellHandle);
108
this._cellListeners.get(cellUri)?.dispose();
109
this._cellListeners.delete(cellUri);
110
notebookExecutions.delete(cellHandle);
111
if (notebookExecutions.size === 0) {
112
this._executions.delete(notebookUri);
113
this._notebookListeners.get(notebookUri)?.dispose();
114
this._notebookListeners.delete(notebookUri);
115
}
116
117
if (lastRunSuccess !== undefined) {
118
if (lastRunSuccess) {
119
if (this._executions.size === 0) {
120
this._accessibilitySignalService.playSignal(AccessibilitySignal.notebookCellCompleted);
121
}
122
this._clearLastFailedCell(notebookUri);
123
} else {
124
this._accessibilitySignalService.playSignal(AccessibilitySignal.notebookCellFailed);
125
this._setLastFailedCell(notebookUri, cellHandle);
126
}
127
this._lastCompletedCellHandles.set(notebookUri, cellHandle);
128
}
129
130
this._onDidChangeExecution.fire(new NotebookCellExecutionEvent(notebookUri, cellHandle));
131
}
132
133
private _onExecutionDidChange(notebookUri: URI, exe: NotebookExecution): void {
134
this._onDidChangeExecution.fire(new NotebookExecutionEvent(notebookUri, exe));
135
}
136
137
private _onExecutionDidComplete(notebookUri: URI): void {
138
const disposables = this._notebookExecutions.get(notebookUri);
139
if (!Array.isArray(disposables)) {
140
this._logService.debug(`NotebookExecutionStateService#_onCellExecutionDidComplete - unknown notebook ${notebookUri.toString()}`);
141
return;
142
}
143
144
this._notebookExecutions.delete(notebookUri);
145
this._onDidChangeExecution.fire(new NotebookExecutionEvent(notebookUri));
146
disposables.forEach(d => d.dispose());
147
}
148
149
createCellExecution(notebookUri: URI, cellHandle: number): INotebookCellExecution {
150
const notebook = this._notebookService.getNotebookTextModel(notebookUri);
151
if (!notebook) {
152
throw new Error(`Notebook not found: ${notebookUri.toString()}`);
153
}
154
155
let notebookExecutionMap = this._executions.get(notebookUri);
156
if (!notebookExecutionMap) {
157
const listeners = this._instantiationService.createInstance(NotebookExecutionListeners, notebookUri);
158
this._notebookListeners.set(notebookUri, listeners);
159
160
notebookExecutionMap = new Map<number, CellExecution>();
161
this._executions.set(notebookUri, notebookExecutionMap);
162
}
163
164
let exe = notebookExecutionMap.get(cellHandle);
165
if (!exe) {
166
exe = this._createNotebookCellExecution(notebook, cellHandle);
167
notebookExecutionMap.set(cellHandle, exe);
168
exe.initialize();
169
this._onDidChangeExecution.fire(new NotebookCellExecutionEvent(notebookUri, cellHandle, exe));
170
}
171
172
return exe;
173
}
174
createExecution(notebookUri: URI): INotebookExecution {
175
const notebook = this._notebookService.getNotebookTextModel(notebookUri);
176
if (!notebook) {
177
throw new Error(`Notebook not found: ${notebookUri.toString()}`);
178
}
179
180
if (!this._notebookListeners.has(notebookUri)) {
181
const listeners = this._instantiationService.createInstance(NotebookExecutionListeners, notebookUri);
182
this._notebookListeners.set(notebookUri, listeners);
183
}
184
185
let info = this._notebookExecutions.get(notebookUri);
186
if (!info) {
187
info = this._createNotebookExecution(notebook);
188
this._notebookExecutions.set(notebookUri, info);
189
this._onDidChangeExecution.fire(new NotebookExecutionEvent(notebookUri, info[0]));
190
}
191
192
return info[0];
193
}
194
195
private _createNotebookCellExecution(notebook: NotebookTextModel, cellHandle: number): CellExecution {
196
const notebookUri = notebook.uri;
197
const exe: CellExecution = this._instantiationService.createInstance(CellExecution, cellHandle, notebook);
198
const disposable = combinedDisposable(
199
exe.onDidUpdate(() => this._onCellExecutionDidChange(notebookUri, cellHandle, exe)),
200
exe.onDidComplete(lastRunSuccess => this._onCellExecutionDidComplete(notebookUri, cellHandle, exe, lastRunSuccess)));
201
this._cellListeners.set(CellUri.generate(notebookUri, cellHandle), disposable);
202
203
return exe;
204
}
205
206
private _createNotebookExecution(notebook: NotebookTextModel): [NotebookExecution, IDisposable] {
207
const notebookUri = notebook.uri;
208
const exe: NotebookExecution = this._instantiationService.createInstance(NotebookExecution, notebook);
209
const disposable = combinedDisposable(
210
exe.onDidUpdate(() => this._onExecutionDidChange(notebookUri, exe)),
211
exe.onDidComplete(() => this._onExecutionDidComplete(notebookUri)));
212
return [exe, disposable];
213
}
214
215
private _setLastFailedCell(notebookURI: URI, cellHandle: number): void {
216
const prevLastFailedCellInfo = this._lastFailedCells.get(notebookURI);
217
const notebook = this._notebookService.getNotebookTextModel(notebookURI);
218
if (!notebook) {
219
return;
220
}
221
222
const newLastFailedCellInfo: IFailedCellInfo = {
223
cellHandle: cellHandle,
224
disposable: prevLastFailedCellInfo ? prevLastFailedCellInfo.disposable : this._getFailedCellListener(notebook),
225
visible: true
226
};
227
228
this._lastFailedCells.set(notebookURI, newLastFailedCellInfo);
229
230
this._onDidChangeLastRunFailState.fire({ visible: true, notebook: notebookURI });
231
}
232
233
private _setLastFailedCellVisibility(notebookURI: URI, visible: boolean): void {
234
const lastFailedCellInfo = this._lastFailedCells.get(notebookURI);
235
236
if (lastFailedCellInfo) {
237
this._lastFailedCells.set(notebookURI, {
238
cellHandle: lastFailedCellInfo.cellHandle,
239
disposable: lastFailedCellInfo.disposable,
240
visible: visible,
241
});
242
}
243
244
this._onDidChangeLastRunFailState.fire({ visible: visible, notebook: notebookURI });
245
}
246
247
private _clearLastFailedCell(notebookURI: URI): void {
248
const lastFailedCellInfo = this._lastFailedCells.get(notebookURI);
249
250
if (lastFailedCellInfo) {
251
lastFailedCellInfo.disposable?.dispose();
252
this._lastFailedCells.delete(notebookURI);
253
}
254
255
this._onDidChangeLastRunFailState.fire({ visible: false, notebook: notebookURI });
256
}
257
258
private _getFailedCellListener(notebook: NotebookTextModel): IDisposable {
259
return notebook.onWillAddRemoveCells((e: NotebookTextModelWillAddRemoveEvent) => {
260
const lastFailedCell = this._lastFailedCells.get(notebook.uri)?.cellHandle;
261
if (lastFailedCell !== undefined) {
262
const lastFailedCellPos = notebook.cells.findIndex(c => c.handle === lastFailedCell);
263
e.rawEvent.changes.forEach(([start, deleteCount, addedCells]) => {
264
if (deleteCount) {
265
if (lastFailedCellPos >= start && lastFailedCellPos < start + deleteCount) {
266
this._setLastFailedCellVisibility(notebook.uri, false);
267
}
268
}
269
270
if (addedCells.some(cell => cell.handle === lastFailedCell)) {
271
this._setLastFailedCellVisibility(notebook.uri, true);
272
}
273
274
});
275
}
276
});
277
}
278
279
override dispose(): void {
280
super.dispose();
281
this._executions.forEach(executionMap => {
282
executionMap.forEach(execution => execution.dispose());
283
executionMap.clear();
284
});
285
this._executions.clear();
286
this._notebookExecutions.forEach(disposables => {
287
disposables.forEach(d => d.dispose());
288
});
289
this._notebookExecutions.clear();
290
291
this._cellListeners.forEach(disposable => disposable.dispose());
292
this._notebookListeners.forEach(disposable => disposable.dispose());
293
this._lastFailedCells.forEach(elem => elem.disposable.dispose());
294
}
295
}
296
297
class NotebookCellExecutionEvent implements ICellExecutionStateChangedEvent {
298
readonly type = NotebookExecutionType.cell;
299
constructor(
300
readonly notebook: URI,
301
readonly cellHandle: number,
302
readonly changed?: CellExecution
303
) { }
304
305
affectsCell(cell: URI): boolean {
306
const parsedUri = CellUri.parse(cell);
307
return !!parsedUri && isEqual(this.notebook, parsedUri.notebook) && this.cellHandle === parsedUri.handle;
308
}
309
310
affectsNotebook(notebook: URI): boolean {
311
return isEqual(this.notebook, notebook);
312
}
313
}
314
315
class NotebookExecutionEvent implements IExecutionStateChangedEvent {
316
readonly type = NotebookExecutionType.notebook;
317
constructor(
318
readonly notebook: URI,
319
readonly changed?: NotebookExecution
320
) { }
321
322
affectsNotebook(notebook: URI): boolean {
323
return isEqual(this.notebook, notebook);
324
}
325
}
326
327
class NotebookExecutionListeners extends Disposable {
328
private readonly _notebookModel: NotebookTextModel;
329
330
constructor(
331
notebook: URI,
332
@INotebookService private readonly _notebookService: INotebookService,
333
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
334
@INotebookExecutionService private readonly _notebookExecutionService: INotebookExecutionService,
335
@INotebookExecutionStateService private readonly _notebookExecutionStateService: INotebookExecutionStateService,
336
@ILogService private readonly _logService: ILogService,
337
) {
338
super();
339
this._logService.debug(`NotebookExecution#ctor ${notebook.toString()}`);
340
341
const notebookModel = this._notebookService.getNotebookTextModel(notebook);
342
if (!notebookModel) {
343
throw new Error('Notebook not found: ' + notebook);
344
}
345
346
this._notebookModel = notebookModel;
347
this._register(this._notebookModel.onWillAddRemoveCells(e => this.onWillAddRemoveCells(e)));
348
this._register(this._notebookModel.onWillDispose(() => this.onWillDisposeDocument()));
349
}
350
351
private cancelAll(): void {
352
this._logService.debug(`NotebookExecutionListeners#cancelAll`);
353
const exes = this._notebookExecutionStateService.getCellExecutionsForNotebook(this._notebookModel.uri);
354
this._notebookExecutionService.cancelNotebookCellHandles(this._notebookModel, exes.map(exe => exe.cellHandle));
355
}
356
357
private onWillDisposeDocument(): void {
358
this._logService.debug(`NotebookExecution#onWillDisposeDocument`);
359
this.cancelAll();
360
}
361
362
private onWillAddRemoveCells(e: NotebookTextModelWillAddRemoveEvent): void {
363
const notebookExes = this._notebookExecutionStateService.getCellExecutionsByHandleForNotebook(this._notebookModel.uri);
364
365
const executingDeletedHandles = new Set<number>();
366
const pendingDeletedHandles = new Set<number>();
367
if (notebookExes) {
368
e.rawEvent.changes.forEach(([start, deleteCount]) => {
369
if (deleteCount) {
370
const deletedHandles = this._notebookModel.cells.slice(start, start + deleteCount).map(c => c.handle);
371
deletedHandles.forEach(h => {
372
const exe = notebookExes.get(h);
373
if (exe?.state === NotebookCellExecutionState.Executing) {
374
executingDeletedHandles.add(h);
375
} else if (exe) {
376
pendingDeletedHandles.add(h);
377
}
378
});
379
}
380
});
381
}
382
383
if (executingDeletedHandles.size || pendingDeletedHandles.size) {
384
const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(this._notebookModel);
385
if (kernel) {
386
const implementsInterrupt = kernel.implementsInterrupt;
387
const handlesToCancel = implementsInterrupt ? [...executingDeletedHandles] : [...executingDeletedHandles, ...pendingDeletedHandles];
388
this._logService.debug(`NotebookExecution#onWillAddRemoveCells, ${JSON.stringify([...handlesToCancel])}`);
389
if (handlesToCancel.length) {
390
kernel.cancelNotebookCellExecution(this._notebookModel.uri, handlesToCancel);
391
}
392
}
393
}
394
}
395
}
396
397
function updateToEdit(update: ICellExecuteUpdate, cellHandle: number): ICellEditOperation {
398
if (update.editType === CellExecutionUpdateType.Output) {
399
return {
400
editType: CellEditType.Output,
401
handle: update.cellHandle,
402
append: update.append,
403
outputs: update.outputs,
404
};
405
} else if (update.editType === CellExecutionUpdateType.OutputItems) {
406
return {
407
editType: CellEditType.OutputItems,
408
items: update.items,
409
append: update.append,
410
outputId: update.outputId
411
};
412
} else if (update.editType === CellExecutionUpdateType.ExecutionState) {
413
const newInternalMetadata: Partial<NotebookCellInternalMetadata> = {};
414
if (typeof update.executionOrder !== 'undefined') {
415
newInternalMetadata.executionOrder = update.executionOrder;
416
}
417
if (typeof update.runStartTime !== 'undefined') {
418
newInternalMetadata.runStartTime = update.runStartTime;
419
}
420
return {
421
editType: CellEditType.PartialInternalMetadata,
422
handle: cellHandle,
423
internalMetadata: newInternalMetadata
424
};
425
}
426
427
throw new Error('Unknown cell update type');
428
}
429
430
class CellExecution extends Disposable implements INotebookCellExecution {
431
private readonly _onDidUpdate = this._register(new Emitter<void>());
432
readonly onDidUpdate = this._onDidUpdate.event;
433
434
private readonly _onDidComplete = this._register(new Emitter<boolean | undefined>());
435
readonly onDidComplete = this._onDidComplete.event;
436
437
private _state: NotebookCellExecutionState = NotebookCellExecutionState.Unconfirmed;
438
get state() {
439
return this._state;
440
}
441
442
get notebook(): URI {
443
return this._notebookModel.uri;
444
}
445
446
private _didPause = false;
447
get didPause() {
448
return this._didPause;
449
}
450
451
private _isPaused = false;
452
get isPaused() {
453
return this._isPaused;
454
}
455
456
constructor(
457
readonly cellHandle: number,
458
private readonly _notebookModel: NotebookTextModel,
459
@ILogService private readonly _logService: ILogService,
460
) {
461
super();
462
this._logService.debug(`CellExecution#ctor ${this.getCellLog()}`);
463
}
464
465
initialize() {
466
const startExecuteEdit: ICellEditOperation = {
467
editType: CellEditType.PartialInternalMetadata,
468
handle: this.cellHandle,
469
internalMetadata: {
470
executionId: generateUuid(),
471
runStartTime: null,
472
runEndTime: null,
473
lastRunSuccess: null,
474
executionOrder: null,
475
renderDuration: null,
476
}
477
};
478
this._applyExecutionEdits([startExecuteEdit]);
479
}
480
481
private getCellLog(): string {
482
return `${this._notebookModel.uri.toString()}, ${this.cellHandle}`;
483
}
484
485
private logUpdates(updates: ICellExecuteUpdate[]): void {
486
const updateTypes = updates.map(u => CellExecutionUpdateType[u.editType]).join(', ');
487
this._logService.debug(`CellExecution#updateExecution ${this.getCellLog()}, [${updateTypes}]`);
488
}
489
490
confirm() {
491
this._logService.debug(`CellExecution#confirm ${this.getCellLog()}`);
492
this._state = NotebookCellExecutionState.Pending;
493
this._onDidUpdate.fire();
494
}
495
496
update(updates: ICellExecuteUpdate[]): void {
497
this.logUpdates(updates);
498
if (updates.some(u => u.editType === CellExecutionUpdateType.ExecutionState)) {
499
this._state = NotebookCellExecutionState.Executing;
500
}
501
502
if (!this._didPause && updates.some(u => u.editType === CellExecutionUpdateType.ExecutionState && u.didPause)) {
503
this._didPause = true;
504
}
505
506
const lastIsPausedUpdate = [...updates].reverse().find(u => u.editType === CellExecutionUpdateType.ExecutionState && typeof u.isPaused === 'boolean');
507
if (lastIsPausedUpdate) {
508
this._isPaused = (lastIsPausedUpdate as ICellExecutionStateUpdate).isPaused!;
509
}
510
511
const cellModel = this._notebookModel.cells.find(c => c.handle === this.cellHandle);
512
if (!cellModel) {
513
this._logService.debug(`CellExecution#update, updating cell not in notebook: ${this._notebookModel.uri.toString()}, ${this.cellHandle}`);
514
} else {
515
const edits = updates.map(update => updateToEdit(update, this.cellHandle));
516
this._applyExecutionEdits(edits);
517
}
518
519
if (updates.some(u => u.editType === CellExecutionUpdateType.ExecutionState)) {
520
this._onDidUpdate.fire();
521
}
522
}
523
524
complete(completionData: ICellExecutionComplete): void {
525
const cellModel = this._notebookModel.cells.find(c => c.handle === this.cellHandle);
526
if (!cellModel) {
527
this._logService.debug(`CellExecution#complete, completing cell not in notebook: ${this._notebookModel.uri.toString()}, ${this.cellHandle}`);
528
} else {
529
const edit: ICellEditOperation = {
530
editType: CellEditType.PartialInternalMetadata,
531
handle: this.cellHandle,
532
internalMetadata: {
533
lastRunSuccess: completionData.lastRunSuccess,
534
runStartTime: this._didPause ? null : cellModel.internalMetadata.runStartTime,
535
runEndTime: this._didPause ? null : completionData.runEndTime,
536
error: completionData.error
537
}
538
};
539
this._applyExecutionEdits([edit]);
540
}
541
542
this._onDidComplete.fire(completionData.lastRunSuccess);
543
}
544
545
private _applyExecutionEdits(edits: ICellEditOperation[]): void {
546
this._notebookModel.applyEdits(edits, true, undefined, () => undefined, undefined, false);
547
}
548
}
549
550
class NotebookExecution extends Disposable implements INotebookExecution {
551
private readonly _onDidUpdate = this._register(new Emitter<void>());
552
readonly onDidUpdate = this._onDidUpdate.event;
553
554
private readonly _onDidComplete = this._register(new Emitter<void>());
555
readonly onDidComplete = this._onDidComplete.event;
556
557
private _state: NotebookExecutionState = NotebookExecutionState.Unconfirmed;
558
get state() {
559
return this._state;
560
}
561
562
get notebook(): URI {
563
return this._notebookModel.uri;
564
}
565
566
constructor(
567
private readonly _notebookModel: NotebookTextModel,
568
@ILogService private readonly _logService: ILogService,
569
) {
570
super();
571
this._logService.debug(`NotebookExecution#ctor`);
572
}
573
private debug(message: string) {
574
this._logService.debug(`${message} ${this._notebookModel.uri.toString()}`);
575
}
576
577
confirm() {
578
this.debug(`Execution#confirm`);
579
this._state = NotebookExecutionState.Pending;
580
this._onDidUpdate.fire();
581
}
582
583
begin(): void {
584
this.debug(`Execution#begin`);
585
this._state = NotebookExecutionState.Executing;
586
this._onDidUpdate.fire();
587
}
588
589
complete(): void {
590
this.debug(`Execution#begin`);
591
this._state = NotebookExecutionState.Unconfirmed;
592
this._onDidComplete.fire();
593
}
594
}
595
596