From 8202e1ec4e60023d84337f48871de3e7f96dafbd Mon Sep 17 00:00:00 2001 From: Benjin Dubishar Date: Thu, 13 Apr 2023 12:44:13 -0700 Subject: [PATCH] Changing dacFxService and schemaCompareService to use shared logic for error handling (#22718) * Move helper function to base class * Switching DacFxService over * Thenable -> Promise * Converting SchemaCompareService --- extensions/mssql/src/baseService.ts | 30 +++++ extensions/mssql/src/contracts.ts | 4 +- extensions/mssql/src/dacfx/dacFxService.ts | 111 +++++------------- .../src/schemaCompare/schemaCompareService.ts | 96 ++++----------- .../src/sqlProjects/sqlProjectsService.ts | 17 +-- 5 files changed, 85 insertions(+), 173 deletions(-) create mode 100644 extensions/mssql/src/baseService.ts diff --git a/extensions/mssql/src/baseService.ts b/extensions/mssql/src/baseService.ts new file mode 100644 index 0000000000..21386a557b --- /dev/null +++ b/extensions/mssql/src/baseService.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RequestType } from 'vscode-languageclient'; +import { SqlOpsDataClient } from 'dataprotocol-client'; + +/** + * Base class containing shared code to reduce boilerplate for services + */ +export abstract class BaseService { + constructor(protected readonly client: SqlOpsDataClient) { } + + /** + * Runs the specified request wrapped in the requisite try-catch + * @param type RequestType, typically in the format 'contracts.DoThingRequest.type' + * @param params parameters to be passed to the request + * @returns result from the request + */ + protected async runWithErrorHandling(type: RequestType, params: P): Promise { + try { + const result = await this.client.sendRequest(type, params); + return result; + } catch (e) { + this.client.logFailedRequest(type, e); + throw e; + } + } +} diff --git a/extensions/mssql/src/contracts.ts b/extensions/mssql/src/contracts.ts index 9e2f1ebeb0..b32cac9356 100644 --- a/extensions/mssql/src/contracts.ts +++ b/extensions/mssql/src/contracts.ts @@ -1106,11 +1106,11 @@ export namespace SchemaCompareGetDefaultOptionsRequest { } export namespace SchemaCompareIncludeExcludeNodeRequest { - export const type = new RequestType('schemaCompare/includeExcludeNode'); + export const type = new RequestType('schemaCompare/includeExcludeNode'); } export namespace SchemaCompareOpenScmpRequest { - export const type = new RequestType('schemaCompare/openScmp'); + export const type = new RequestType('schemaCompare/openScmp'); } export namespace SchemaCompareSaveScmpRequest { diff --git a/extensions/mssql/src/dacfx/dacFxService.ts b/extensions/mssql/src/dacfx/dacFxService.ts index dbb7aa59c2..21d9c7cbae 100644 --- a/extensions/mssql/src/dacfx/dacFxService.ts +++ b/extensions/mssql/src/dacfx/dacFxService.ts @@ -4,15 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import * as mssql from 'mssql'; -import { AppContext } from '../appContext'; -import { ISqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client'; -import { ClientCapabilities } from 'vscode-languageclient'; import * as constants from '../constants'; import * as Utils from '../utils'; import * as azdata from 'azdata'; import * as contracts from '../contracts'; -export class DacFxService implements mssql.IDacFxService { +import { AppContext } from '../appContext'; +import { ISqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client'; +import { ClientCapabilities } from 'vscode-languageclient'; +import { BaseService } from '../baseService'; + +export class DacFxService extends BaseService implements mssql.IDacFxService { public static asFeature(context: AppContext): ISqlOpsFeature { return class extends DacFxService { constructor(client: SqlOpsDataClient) { @@ -28,117 +30,58 @@ export class DacFxService implements mssql.IDacFxService { }; } - private constructor(context: AppContext, protected readonly client: SqlOpsDataClient) { + private constructor(context: AppContext, client: SqlOpsDataClient) { + super(client); context.registerService(constants.DacFxService, this); } - public exportBacpac(databaseName: string, packageFilePath: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public exportBacpac(databaseName: string, packageFilePath: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.ExportParams = { databaseName: databaseName, packageFilePath: packageFilePath, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.ExportRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.ExportRequest.type, e); - return Promise.reject(e); - } - ); + return this.runWithErrorHandling(contracts.ExportRequest.type, params); } - public importBacpac(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public importBacpac(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.ImportParams = { packageFilePath: packageFilePath, databaseName: databaseName, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.ImportRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.ImportRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.ImportRequest.type, params); } - public extractDacpac(databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public extractDacpac(databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.ExtractParams = { databaseName: databaseName, packageFilePath: packageFilePath, applicationName: applicationName, applicationVersion: applicationVersion, ownerUri: ownerUri, extractTarget: mssql.ExtractTarget.dacpac, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.ExtractRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.ExtractRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.ExtractRequest.type, params); } - public createProjectFromDatabase(databaseName: string, targetFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, extractTarget: mssql.ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode, includePermissions?: boolean): Thenable { + public createProjectFromDatabase(databaseName: string, targetFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, extractTarget: mssql.ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode, includePermissions?: boolean): Promise { const params: contracts.ExtractParams = { databaseName: databaseName, packageFilePath: targetFilePath, applicationName: applicationName, applicationVersion: applicationVersion, ownerUri: ownerUri, extractTarget: extractTarget, taskExecutionMode: taskExecutionMode, includePermissions: includePermissions }; - return this.client.sendRequest(contracts.ExtractRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.ExtractRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.ExtractRequest.type, params); } - public deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record, deploymentOptions?: mssql.DeploymentOptions): Thenable { + public deployDacpac(packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record, deploymentOptions?: mssql.DeploymentOptions): Promise { const params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.DeployRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.DeployRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.DeployRequest.type, params); } - public generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record, deploymentOptions?: mssql.DeploymentOptions): Thenable { + public generateDeployScript(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode, sqlCommandVariableValues?: Record, deploymentOptions?: mssql.DeploymentOptions): Promise { const params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, sqlCommandVariableValues: sqlCommandVariableValues, deploymentOptions: deploymentOptions, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.GenerateDeployScriptRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.GenerateDeployScriptRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.GenerateDeployScriptRequest.type, params); } - public generateDeployPlan(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public generateDeployPlan(packageFilePath: string, targetDatabaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.GenerateDeployPlanParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.GenerateDeployPlanRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.GenerateDeployPlanRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.GenerateDeployPlanRequest.type, params); } - public getOptionsFromProfile(profilePath: string): Thenable { + public getOptionsFromProfile(profilePath: string): Promise { const params: contracts.GetOptionsFromProfileParams = { profilePath: profilePath }; - return this.client.sendRequest(contracts.GetOptionsFromProfileRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.GetOptionsFromProfileRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.GetOptionsFromProfileRequest.type, params); } - public validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable { + public validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Promise { const params: contracts.ValidateStreamingJobParams = { packageFilePath: packageFilePath, createStreamingJobTsql: createStreamingJobTsql }; - return this.client.sendRequest(contracts.ValidateStreamingJobRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.ValidateStreamingJobRequest.type, e); - return Promise.reject(undefined); - } - ); + return this.runWithErrorHandling(contracts.ValidateStreamingJobRequest.type, params); } public async parseTSqlScript(filePath: string, databaseSchemaProvider: string): Promise { const params: contracts.ParseTSqlScriptParams = { filePath, databaseSchemaProvider }; - try { - const result = await this.client.sendRequest(contracts.ParseTSqlScriptRequest.type, params); - return result; - } catch (e) { - this.client.logFailedRequest(contracts.ParseTSqlScriptRequest.type, e); - throw e; - } + return this.runWithErrorHandling(contracts.ParseTSqlScriptRequest.type, params); } } diff --git a/extensions/mssql/src/schemaCompare/schemaCompareService.ts b/extensions/mssql/src/schemaCompare/schemaCompareService.ts index ec19651573..42aafb1d27 100644 --- a/extensions/mssql/src/schemaCompare/schemaCompareService.ts +++ b/extensions/mssql/src/schemaCompare/schemaCompareService.ts @@ -11,8 +11,9 @@ import * as Utils from '../utils'; import { ClientCapabilities } from 'vscode-languageclient'; import * as azdata from 'azdata'; import * as contracts from '../contracts'; +import { BaseService } from '../baseService'; -export class SchemaCompareService implements mssql.ISchemaCompareService { +export class SchemaCompareService extends BaseService implements mssql.ISchemaCompareService { public static asFeature(context: AppContext): ISqlOpsFeature { return class extends SchemaCompareService { constructor(client: SqlOpsDataClient) { @@ -28,106 +29,53 @@ export class SchemaCompareService implements mssql.ISchemaCompareService { }; } - private constructor(context: AppContext, protected readonly client: SqlOpsDataClient) { + private constructor(context: AppContext, client: SqlOpsDataClient) { + super(client); context.registerService(constants.SchemaCompareService, this); } - public schemaCompare(operationId: string, sourceEndpointInfo: mssql.SchemaCompareEndpointInfo, targetEndpointInfo: mssql.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: mssql.DeploymentOptions): Thenable { + public schemaCompare(operationId: string, sourceEndpointInfo: mssql.SchemaCompareEndpointInfo, targetEndpointInfo: mssql.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: mssql.DeploymentOptions): Promise { const params: contracts.SchemaCompareParams = { operationId: operationId, sourceEndpointInfo: sourceEndpointInfo, targetEndpointInfo: targetEndpointInfo, taskExecutionMode: taskExecutionMode, deploymentOptions: deploymentOptions }; - return this.client.sendRequest(contracts.SchemaCompareRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareRequest.type, params); } - public schemaCompareGenerateScript(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public schemaCompareGenerateScript(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.SchemaCompareGenerateScriptParams = { operationId: operationId, targetServerName: targetServerName, targetDatabaseName: targetDatabaseName, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.SchemaCompareGenerateScriptRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareGenerateScriptRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareGenerateScriptRequest.type, params); } - public schemaComparePublishDatabaseChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public schemaComparePublishDatabaseChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.SchemaComparePublishDatabaseChangesParams = { operationId: operationId, targetServerName: targetServerName, targetDatabaseName: targetDatabaseName, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.SchemaComparePublishDatabaseChangesRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaComparePublishDatabaseChangesRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaComparePublishDatabaseChangesRequest.type, params); } - public schemaComparePublishProjectChanges(operationId: string, targetProjectPath: string, targetFolderStructure: mssql.ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public schemaComparePublishProjectChanges(operationId: string, targetProjectPath: string, targetFolderStructure: mssql.ExtractTarget, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.SchemaComparePublishProjectChangesParams = { operationId: operationId, targetProjectPath: targetProjectPath, targetFolderStructure: targetFolderStructure, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.SchemaComparePublishProjectChangesRequest.type, params).then( - undefined, - (e: any) => { - this.client.logFailedRequest(contracts.SchemaComparePublishProjectChangesRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaComparePublishProjectChangesRequest.type, params); } - public schemaCompareGetDefaultOptions(): Thenable { + public schemaCompareGetDefaultOptions(): Promise { const params: contracts.SchemaCompareGetOptionsParams = {}; - return this.client.sendRequest(contracts.SchemaCompareGetDefaultOptionsRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareGetDefaultOptionsRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareGetDefaultOptionsRequest.type, params); } - public schemaCompareIncludeExcludeNode(operationId: string, diffEntry: mssql.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + public schemaCompareIncludeExcludeNode(operationId: string, diffEntry: mssql.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Promise { const params: contracts.SchemaCompareNodeParams = { operationId: operationId, diffEntry, includeRequest, taskExecutionMode: taskExecutionMode }; - return this.client.sendRequest(contracts.SchemaCompareIncludeExcludeNodeRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareIncludeExcludeNodeRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareIncludeExcludeNodeRequest.type, params); } - public schemaCompareOpenScmp(filePath: string): Thenable { + public schemaCompareOpenScmp(filePath: string): Promise { const params: contracts.SchemaCompareOpenScmpParams = { filePath: filePath }; - return this.client.sendRequest(contracts.SchemaCompareOpenScmpRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareOpenScmpRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareOpenScmpRequest.type, params); } - public schemaCompareSaveScmp(sourceEndpointInfo: mssql.SchemaCompareEndpointInfo, targetEndpointInfo: mssql.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: mssql.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: mssql.SchemaCompareObjectId[], excludedTargetObjects: mssql.SchemaCompareObjectId[]): Thenable { + public schemaCompareSaveScmp(sourceEndpointInfo: mssql.SchemaCompareEndpointInfo, targetEndpointInfo: mssql.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: mssql.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: mssql.SchemaCompareObjectId[], excludedTargetObjects: mssql.SchemaCompareObjectId[]): Promise { const params: contracts.SchemaCompareSaveScmpParams = { sourceEndpointInfo: sourceEndpointInfo, targetEndpointInfo: targetEndpointInfo, taskExecutionMode: taskExecutionMode, deploymentOptions: deploymentOptions, scmpFilePath: scmpFilePath, excludedSourceObjects: excludedSourceObjects, excludedTargetObjects: excludedTargetObjects }; - return this.client.sendRequest(contracts.SchemaCompareSaveScmpRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareSaveScmpRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareSaveScmpRequest.type, params); } - public schemaCompareCancel(operationId: string): Thenable { + public schemaCompareCancel(operationId: string): Promise { const params: contracts.SchemaCompareCancelParams = { operationId: operationId }; - return this.client.sendRequest(contracts.SchemaCompareCancellationRequest.type, params).then( - undefined, - e => { - this.client.logFailedRequest(contracts.SchemaCompareCancellationRequest.type, e); - return Promise.reject(e) - } - ); + return this.runWithErrorHandling(contracts.SchemaCompareCancellationRequest.type, params); } } diff --git a/extensions/mssql/src/sqlProjects/sqlProjectsService.ts b/extensions/mssql/src/sqlProjects/sqlProjectsService.ts index e35ccea583..4b465144b1 100644 --- a/extensions/mssql/src/sqlProjects/sqlProjectsService.ts +++ b/extensions/mssql/src/sqlProjects/sqlProjectsService.ts @@ -11,9 +11,9 @@ import * as contracts from '../contracts'; import { AppContext } from '../appContext'; import { ISqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client'; import { ClientCapabilities } from 'vscode-languageclient'; -import { RequestType } from 'vscode-languageclient'; +import { BaseService } from '../baseService'; -export class SqlProjectsService implements mssql.ISqlProjectsService { +export class SqlProjectsService extends BaseService implements mssql.ISqlProjectsService { public static asFeature(context: AppContext): ISqlOpsFeature { return class extends SqlProjectsService { constructor(client: SqlOpsDataClient) { @@ -29,7 +29,8 @@ export class SqlProjectsService implements mssql.ISqlProjectsService { }; } - private constructor(context: AppContext, protected readonly client: SqlOpsDataClient) { + private constructor(context: AppContext, client: SqlOpsDataClient) { + super(client); context.registerService(constants.SqlProjectsService, this); } @@ -445,14 +446,4 @@ export class SqlProjectsService implements mssql.ISqlProjectsService { const params: contracts.MoveItemParams = { projectUri: projectUri, destinationPath: destinationPath, path: path }; return await this.runWithErrorHandling(contracts.MoveNoneItemRequest.type, params); } - - private async runWithErrorHandling(type: RequestType, params: P): Promise { - try { - const result = await this.client.sendRequest(type, params); - return result; - } catch (e) { - this.client.logFailedRequest(type, e); - throw e; - } - } }