mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
Split up NotebookProvider into separate providers for handling file serialization and cell execution. (#17176)
This commit is contained in:
@@ -12,9 +12,9 @@ import { localize } from 'vs/nls';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
import { ExtHostNotebookShape, MainThreadNotebookShape, SqlMainContext } from 'sql/workbench/api/common/sqlExtHost.protocol';
|
||||
import { INotebookManagerDetails, INotebookSessionDetails, INotebookKernelDetails, INotebookFutureDetails, FutureMessageType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { IExecuteManagerDetails, INotebookSessionDetails, INotebookKernelDetails, INotebookFutureDetails, FutureMessageType, ISerializationManagerDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
|
||||
type Adapter = azdata.nb.NotebookProvider | azdata.nb.NotebookManager | azdata.nb.ISession | azdata.nb.IKernel | azdata.nb.IFuture;
|
||||
type Adapter = azdata.nb.NotebookSerializationProvider | azdata.nb.SerializationManager | azdata.nb.NotebookExecuteProvider | azdata.nb.ExecuteManager | azdata.nb.ISession | azdata.nb.IKernel | azdata.nb.IFuture;
|
||||
|
||||
export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
private static _handlePool: number = 0;
|
||||
@@ -28,26 +28,40 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
//#region APIs called by main thread
|
||||
async $getNotebookManager(providerHandle: number, notebookUri: UriComponents): Promise<INotebookManagerDetails> {
|
||||
async $getSerializationManagerDetails(providerHandle: number, notebookUri: UriComponents): Promise<ISerializationManagerDetails> {
|
||||
let uri = URI.revive(notebookUri);
|
||||
let uriString = uri.toString();
|
||||
let adapter = this.findManagerForUri(uriString);
|
||||
let adapter = this.findSerializationManagerForUri(uriString);
|
||||
if (!adapter) {
|
||||
adapter = await this._withProvider(providerHandle, (provider) => {
|
||||
return this.getOrCreateManager(provider, uri);
|
||||
adapter = await this._withSerializationProvider(providerHandle, (provider) => {
|
||||
return this.getOrCreateSerializationManager(provider, uri);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
handle: adapter.handle,
|
||||
hasContentManager: !!adapter.contentManager
|
||||
};
|
||||
}
|
||||
async $getExecuteManagerDetails(providerHandle: number, notebookUri: UriComponents): Promise<IExecuteManagerDetails> {
|
||||
let uri = URI.revive(notebookUri);
|
||||
let uriString = uri.toString();
|
||||
let adapter = this.findExecuteManagerForUri(uriString);
|
||||
if (!adapter) {
|
||||
adapter = await this._withExecuteProvider(providerHandle, (provider) => {
|
||||
return this.getOrCreateExecuteManager(provider, uri);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
handle: adapter.handle,
|
||||
hasContentManager: !!adapter.contentManager,
|
||||
hasServerManager: !!adapter.serverManager
|
||||
};
|
||||
}
|
||||
$handleNotebookClosed(notebookUri: UriComponents): void {
|
||||
let uri = URI.revive(notebookUri);
|
||||
let uriString = uri.toString();
|
||||
let manager = this.findManagerForUri(uriString);
|
||||
let manager = this.findExecuteManagerForUri(uriString);
|
||||
if (manager) {
|
||||
manager.provider.handleNotebookClosed(uri);
|
||||
this._adapters.delete(manager.handle);
|
||||
@@ -62,12 +76,12 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
return this._withServerManager(managerHandle, (serverManager) => serverManager.stopServer());
|
||||
}
|
||||
|
||||
$getNotebookContents(managerHandle: number, notebookUri: UriComponents): Thenable<azdata.nb.INotebookContents> {
|
||||
return this._withContentManager(managerHandle, (contentManager) => contentManager.getNotebookContents(URI.revive(notebookUri)));
|
||||
$deserializeNotebook(managerHandle: number, contents: string): Thenable<azdata.nb.INotebookContents> {
|
||||
return this._withContentManager(managerHandle, (contentManager) => contentManager.deserializeNotebook(contents));
|
||||
}
|
||||
|
||||
$save(managerHandle: number, notebookUri: UriComponents, notebook: azdata.nb.INotebookContents): Thenable<azdata.nb.INotebookContents> {
|
||||
return this._withContentManager(managerHandle, (contentManager) => contentManager.save(URI.revive(notebookUri), notebook));
|
||||
$serializeNotebook(managerHandle: number, notebook: azdata.nb.INotebookContents): Thenable<string> {
|
||||
return this._withContentManager(managerHandle, (contentManager) => contentManager.serializeNotebook(notebook));
|
||||
}
|
||||
|
||||
$refreshSpecs(managerHandle: number): Thenable<azdata.nb.IAllKernels> {
|
||||
@@ -222,12 +236,21 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
//#endregion
|
||||
|
||||
//#region APIs called by extensions
|
||||
registerNotebookProvider(provider: azdata.nb.NotebookProvider): vscode.Disposable {
|
||||
registerExecuteProvider(provider: azdata.nb.NotebookExecuteProvider): vscode.Disposable {
|
||||
if (!provider || !provider.providerId) {
|
||||
throw new Error(localize('providerRequired', "A NotebookProvider with valid providerId must be passed to this method"));
|
||||
throw new Error(localize('executeProviderRequired', "A NotebookExecuteProvider with valid providerId must be passed to this method"));
|
||||
}
|
||||
const handle = this._addNewAdapter(provider);
|
||||
this._proxy.$registerNotebookProvider(provider.providerId, handle);
|
||||
this._proxy.$registerExecuteProvider(provider.providerId, handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
registerSerializationProvider(provider: azdata.nb.NotebookSerializationProvider): vscode.Disposable {
|
||||
if (!provider || !provider.providerId) {
|
||||
throw new Error(localize('serializationProviderRequired', "A NotebookSerializationProvider with valid providerId must be passed to this method"));
|
||||
}
|
||||
const handle = this._addNewAdapter(provider);
|
||||
this._proxy.$registerSerializationProvider(provider.providerId, handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
//#endregion
|
||||
@@ -245,8 +268,8 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
return matchingAdapters;
|
||||
}
|
||||
|
||||
private findManagerForUri(uriString: string): NotebookManagerAdapter {
|
||||
for (let manager of this.getAdapters(NotebookManagerAdapter)) {
|
||||
private findSerializationManagerForUri(uriString: string): SerializationManagerAdapter {
|
||||
for (let manager of this.getAdapters(SerializationManagerAdapter)) {
|
||||
if (manager.uriString === uriString) {
|
||||
return manager;
|
||||
}
|
||||
@@ -254,10 +277,27 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async getOrCreateManager(provider: azdata.nb.NotebookProvider, notebookUri: URI): Promise<NotebookManagerAdapter> {
|
||||
let manager = await provider.getNotebookManager(notebookUri);
|
||||
private findExecuteManagerForUri(uriString: string): ExecuteManagerAdapter {
|
||||
for (let manager of this.getAdapters(ExecuteManagerAdapter)) {
|
||||
if (manager.uriString === uriString) {
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async getOrCreateSerializationManager(provider: azdata.nb.NotebookSerializationProvider, notebookUri: URI): Promise<SerializationManagerAdapter> {
|
||||
let manager = await provider.getSerializationManager(notebookUri);
|
||||
let uriString = notebookUri.toString();
|
||||
let adapter = new NotebookManagerAdapter(provider, manager, uriString);
|
||||
let adapter = new SerializationManagerAdapter(provider, manager, uriString);
|
||||
adapter.handle = this._addNewAdapter(adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private async getOrCreateExecuteManager(provider: azdata.nb.NotebookExecuteProvider, notebookUri: URI): Promise<ExecuteManagerAdapter> {
|
||||
let manager = await provider.getExecuteManager(notebookUri);
|
||||
let uriString = notebookUri.toString();
|
||||
let adapter = new ExecuteManagerAdapter(provider, manager, uriString);
|
||||
adapter.handle = this._addNewAdapter(adapter);
|
||||
return adapter;
|
||||
}
|
||||
@@ -272,23 +312,39 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
return ExtHostNotebook._handlePool++;
|
||||
}
|
||||
|
||||
private _withProvider<R>(handle: number, callback: (provider: azdata.nb.NotebookProvider) => R | PromiseLike<R>): Promise<R> {
|
||||
let provider = this._adapters.get(handle) as azdata.nb.NotebookProvider;
|
||||
private _withSerializationProvider(handle: number, callback: (provider: azdata.nb.NotebookSerializationProvider) => SerializationManagerAdapter | PromiseLike<SerializationManagerAdapter>): Promise<SerializationManagerAdapter> {
|
||||
let provider = this._adapters.get(handle) as azdata.nb.NotebookSerializationProvider;
|
||||
if (provider === undefined) {
|
||||
return Promise.reject(new Error(localize('errNoProvider', "no notebook provider found")));
|
||||
return Promise.reject(new Error(localize('errNoSerializationProvider', "No notebook serialization provider found")));
|
||||
}
|
||||
return Promise.resolve(callback(provider));
|
||||
}
|
||||
|
||||
private _withNotebookManager<R>(handle: number, callback: (manager: NotebookManagerAdapter) => R | PromiseLike<R>): Promise<R> {
|
||||
let manager = this._adapters.get(handle) as NotebookManagerAdapter;
|
||||
if (manager === undefined) {
|
||||
return Promise.reject(new Error(localize('errNoManager', "No Manager found")));
|
||||
private _withExecuteProvider(handle: number, callback: (provider: azdata.nb.NotebookExecuteProvider) => ExecuteManagerAdapter | PromiseLike<ExecuteManagerAdapter>): Promise<ExecuteManagerAdapter> {
|
||||
let provider = this._adapters.get(handle) as azdata.nb.NotebookExecuteProvider;
|
||||
if (provider === undefined) {
|
||||
return Promise.reject(new Error(localize('errNoExecuteProvider', "No notebook execute provider found")));
|
||||
}
|
||||
return this.callbackWithErrorWrap<R>(callback, manager);
|
||||
return Promise.resolve(callback(provider));
|
||||
}
|
||||
|
||||
private async callbackWithErrorWrap<R>(callback: (manager: NotebookManagerAdapter) => R | PromiseLike<R>, manager: NotebookManagerAdapter): Promise<R> {
|
||||
private _withSerializationManager<R>(handle: number, callback: (manager: SerializationManagerAdapter) => R | PromiseLike<R>): Promise<R> {
|
||||
let manager = this._adapters.get(handle) as SerializationManagerAdapter;
|
||||
if (manager === undefined) {
|
||||
return Promise.reject(new Error(localize('errNoSerializationManager', "No serialization manager found")));
|
||||
}
|
||||
return this.callbackWithErrorWrap<SerializationManagerAdapter, R>(callback, manager);
|
||||
}
|
||||
|
||||
private _withExecuteManager<R>(handle: number, callback: (manager: ExecuteManagerAdapter) => R | PromiseLike<R>): Promise<R> {
|
||||
let manager = this._adapters.get(handle) as ExecuteManagerAdapter;
|
||||
if (manager === undefined) {
|
||||
return Promise.reject(new Error(localize('errNoExecuteManager', "No execute manager found")));
|
||||
}
|
||||
return this.callbackWithErrorWrap<ExecuteManagerAdapter, R>(callback, manager);
|
||||
}
|
||||
|
||||
private async callbackWithErrorWrap<A, R>(callback: (manager: A) => R | PromiseLike<R>, manager: A): Promise<R> {
|
||||
try {
|
||||
let value = await callback(manager);
|
||||
return value;
|
||||
@@ -298,7 +354,7 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
private _withServerManager<R>(handle: number, callback: (manager: azdata.nb.ServerManager) => PromiseLike<R>): Promise<R> {
|
||||
return this._withNotebookManager(handle, (notebookManager) => {
|
||||
return this._withExecuteManager(handle, (notebookManager) => {
|
||||
let serverManager = notebookManager.serverManager;
|
||||
if (!serverManager) {
|
||||
return Promise.reject(new Error(localize('noServerManager', "Notebook Manager for notebook {0} does not have a server manager. Cannot perform operations on it", notebookManager.uriString)));
|
||||
@@ -308,7 +364,7 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
private _withContentManager<R>(handle: number, callback: (manager: azdata.nb.ContentManager) => PromiseLike<R>): Promise<R> {
|
||||
return this._withNotebookManager(handle, (notebookManager) => {
|
||||
return this._withSerializationManager(handle, (notebookManager) => {
|
||||
let contentManager = notebookManager.contentManager;
|
||||
if (!contentManager) {
|
||||
return Promise.reject(new Error(localize('noContentManager', "Notebook Manager for notebook {0} does not have a content manager. Cannot perform operations on it", notebookManager.uriString)));
|
||||
@@ -318,7 +374,7 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
private _withSessionManager<R>(handle: number, callback: (manager: azdata.nb.SessionManager) => PromiseLike<R>): Promise<R> {
|
||||
return this._withNotebookManager(handle, (notebookManager) => {
|
||||
return this._withExecuteManager(handle, (notebookManager) => {
|
||||
let sessionManager = notebookManager.sessionManager;
|
||||
if (!sessionManager) {
|
||||
return Promise.reject(new Error(localize('noSessionManager', "Notebook Manager for notebook {0} does not have a session manager. Cannot perform operations on it", notebookManager.uriString)));
|
||||
@@ -344,12 +400,11 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
//#endregion
|
||||
}
|
||||
|
||||
|
||||
class NotebookManagerAdapter implements azdata.nb.NotebookManager {
|
||||
class SerializationManagerAdapter implements azdata.nb.SerializationManager {
|
||||
public handle: number;
|
||||
constructor(
|
||||
public readonly provider: azdata.nb.NotebookProvider,
|
||||
private manager: azdata.nb.NotebookManager,
|
||||
public readonly provider: azdata.nb.NotebookSerializationProvider,
|
||||
private manager: azdata.nb.SerializationManager,
|
||||
public readonly uriString: string
|
||||
) {
|
||||
}
|
||||
@@ -357,6 +412,16 @@ class NotebookManagerAdapter implements azdata.nb.NotebookManager {
|
||||
public get contentManager(): azdata.nb.ContentManager {
|
||||
return this.manager.contentManager;
|
||||
}
|
||||
}
|
||||
|
||||
class ExecuteManagerAdapter implements azdata.nb.ExecuteManager {
|
||||
public handle: number;
|
||||
constructor(
|
||||
public readonly provider: azdata.nb.NotebookExecuteProvider,
|
||||
private manager: azdata.nb.ExecuteManager,
|
||||
public readonly uriString: string
|
||||
) {
|
||||
}
|
||||
|
||||
public get sessionManager(): azdata.nb.SessionManager {
|
||||
return this.manager.sessionManager;
|
||||
|
||||
Reference in New Issue
Block a user