diff --git a/extensions/integration-tests/src/test/notebook.test.ts b/extensions/integration-tests/src/test/notebook.test.ts index a70a5153e0..0b59b4f3cb 100644 --- a/extensions/integration-tests/src/test/notebook.test.ts +++ b/extensions/integration-tests/src/test/notebook.test.ts @@ -84,7 +84,7 @@ suite('Notebook integration test suite', function () { } }); - test('Sql NB run cells above and below test @UNSTABLE@', async function () { + test('Sql NB run cells above and below test', async function () { let notebook = await openNotebook(sqlNotebookMultipleCellsContent, sqlKernelMetadata, this.test.title + this.invocationCount++); // When running all cells above a cell, ensure that only cells preceding current cell have output await runCells(notebook, true, undefined, notebook.document.cells[1]); @@ -101,13 +101,13 @@ suite('Notebook integration test suite', function () { assert(notebook.document.cells[2].contents.outputs.length === 3, `Expected length: '3', Actual: '${notebook.document.cells[2].contents.outputs.length}'`); }); - test('Clear cell output - SQL notebook @UNSTABLE@', async function () { + test('Clear cell output - SQL notebook', async function () { let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++); await runCell(notebook); await verifyClearOutputs(notebook); }); - test('Clear all outputs - SQL notebook @UNSTABLE@', async function () { + test('Clear all outputs - SQL notebook', async function () { let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++); await runCell(notebook); await verifyClearAllOutputs(notebook); diff --git a/src/sql/workbench/contrib/notebook/test/stubs.ts b/src/sql/workbench/contrib/notebook/test/stubs.ts index 9ba75338b9..676b9d9ff3 100644 --- a/src/sql/workbench/contrib/notebook/test/stubs.ts +++ b/src/sql/workbench/contrib/notebook/test/stubs.ts @@ -39,6 +39,9 @@ export class NotebookModelStub implements INotebookModel { get clientSession(): IClientSession { throw new Error('method not implemented.'); } + get sessionLoadFinished(): Promise { + throw new Error('method not implemented.'); + } get notebookManagers(): INotebookManager[] { throw new Error('method not implemented.'); } diff --git a/src/sql/workbench/services/notebook/browser/models/cell.ts b/src/sql/workbench/services/notebook/browser/models/cell.ts index e6508f8ce6..654e49803d 100644 --- a/src/sql/workbench/services/notebook/browser/models/cell.ts +++ b/src/sql/workbench/services/notebook/browser/models/cell.ts @@ -373,12 +373,14 @@ export class CellModel implements ICellModel { private async getOrStartKernel(notificationService: INotificationService): Promise { let model = this._options.notebook; + if (model) { + await model.sessionLoadFinished; + } let clientSession = model && model.clientSession; if (!clientSession) { this.sendNotification(notificationService, Severity.Error, localize('notebookNotReady', "The session for this notebook is not yet ready")); return undefined; } else if (!clientSession.isReady || clientSession.status === 'dead') { - this.sendNotification(notificationService, Severity.Info, localize('sessionNotReady', "The session for this notebook will start momentarily")); await clientSession.kernelChangeCompleted; } diff --git a/src/sql/workbench/services/notebook/browser/models/modelInterfaces.ts b/src/sql/workbench/services/notebook/browser/models/modelInterfaces.ts index 3c1e78114e..66e61d4a62 100644 --- a/src/sql/workbench/services/notebook/browser/models/modelInterfaces.ts +++ b/src/sql/workbench/services/notebook/browser/models/modelInterfaces.ts @@ -233,6 +233,10 @@ export interface INotebookModel { * Client Session in the notebook, used for sending requests to the notebook service */ readonly clientSession: IClientSession; + /** + * Promise indicating when client session is ready to use. + */ + readonly sessionLoadFinished: Promise; /** * LanguageInfo saved in the notebook */ diff --git a/src/sql/workbench/services/notebook/browser/models/notebookModel.ts b/src/sql/workbench/services/notebook/browser/models/notebookModel.ts index fb7ce0df83..58f678dc2a 100644 --- a/src/sql/workbench/services/notebook/browser/models/notebookModel.ts +++ b/src/sql/workbench/services/notebook/browser/models/notebookModel.ts @@ -29,6 +29,7 @@ import { find, firstIndex } from 'vs/base/common/arrays'; import { startsWith } from 'vs/base/common/strings'; import { notebookConstants } from 'sql/workbench/services/notebook/browser/interfaces'; import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; +import { Deferred } from 'sql/base/common/promise'; /* * Used to control whether a message in a dialog/wizard is displayed as an error, @@ -54,7 +55,7 @@ export class NotebookModel extends Disposable implements INotebookModel { private _layoutChanged = new Emitter(); private _inErrorState: boolean = false; private _activeClientSession: IClientSession; - private _sessionLoadFinished: Promise; + private _sessionLoadFinished = new Deferred(); private _onClientSessionReady = new Emitter(); private _onProviderIdChanged = new Emitter(); private _trustedMode: boolean; @@ -148,7 +149,6 @@ export class NotebookModel extends Disposable implements INotebookModel { return this._contentChangedEmitter.event; } - public get isSessionReady(): boolean { return !!this._activeClientSession; } @@ -492,7 +492,9 @@ export class NotebookModel extends Disposable implements INotebookModel { clientSession.statusChanged(async (session) => { this._kernelsChangedEmitter.fire(session.kernel); }); - await clientSession.initialize(); + await clientSession.initialize().then(() => { + this._sessionLoadFinished.resolve(); + }); // By somehow we have to wait for ready, otherwise may not be called for some cases. await clientSession.ready; if (clientSession.kernel) {