mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-24 09:35:37 -05:00
SQL-Migration extension - fix refresh reentrancy hang (#16482)
* Fix application hang on refresh * fix re-entrancy issue with refresh * adding additional refresh checking
This commit is contained in:
@@ -49,6 +49,8 @@ export class DashboardWidget {
|
||||
private _autoRefreshHandle!: NodeJS.Timeout;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
private isRefreshing: boolean = false;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
@@ -242,14 +244,19 @@ export class DashboardWidget {
|
||||
}
|
||||
|
||||
private setAutoRefresh(interval: SupportedAutoRefreshIntervals): void {
|
||||
let classVariable = this;
|
||||
const classVariable = this;
|
||||
clearInterval(this._autoRefreshHandle);
|
||||
if (interval !== -1) {
|
||||
this._autoRefreshHandle = setInterval(function () { classVariable.refreshMigrations(); }, interval);
|
||||
this._autoRefreshHandle = setInterval(async function () { await classVariable.refreshMigrations(); }, interval);
|
||||
}
|
||||
}
|
||||
|
||||
private async refreshMigrations(): Promise<void> {
|
||||
if (this.isRefreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRefreshing = true;
|
||||
this._viewAllMigrationsButton.enabled = false;
|
||||
this._migrationStatusCardLoadingContainer.loading = true;
|
||||
try {
|
||||
@@ -304,6 +311,7 @@ export class DashboardWidget {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
this._migrationStatusCardLoadingContainer.loading = false;
|
||||
this._viewAllMigrationsButton.enabled = true;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ export class MigrationCutoverDialog {
|
||||
private _autoRefreshHandle!: any;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
private isRefreshing = false;
|
||||
|
||||
readonly _infoFieldWidth: string = '250px';
|
||||
|
||||
constructor(migration: MigrationContext) {
|
||||
@@ -279,8 +281,8 @@ export class MigrationCutoverDialog {
|
||||
d => { try { d.dispose(); } catch { } });
|
||||
}));
|
||||
|
||||
return view.initializeModel(form).then((value) => {
|
||||
this.refreshStatus();
|
||||
return view.initializeModel(form).then(async (value) => {
|
||||
await this.refreshStatus();
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
@@ -493,13 +495,18 @@ export class MigrationCutoverDialog {
|
||||
const classVariable = this;
|
||||
clearInterval(this._autoRefreshHandle);
|
||||
if (interval !== -1) {
|
||||
this._autoRefreshHandle = setInterval(function () { classVariable.refreshStatus(); }, interval);
|
||||
this._autoRefreshHandle = setInterval(async function () { await classVariable.refreshStatus(); }, interval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async refreshStatus(): Promise<void> {
|
||||
if (this.isRefreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.isRefreshing = true;
|
||||
this._refreshLoader.loading = true;
|
||||
this._cutoverButton.enabled = false;
|
||||
this._cancelButton.enabled = false;
|
||||
@@ -615,8 +622,10 @@ export class MigrationCutoverDialog {
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
this._refreshLoader.loading = false;
|
||||
}
|
||||
this._refreshLoader.loading = false;
|
||||
}
|
||||
|
||||
private createInfoField(label: string, value: string): {
|
||||
|
||||
@@ -33,6 +33,8 @@ export class MigrationStatusDialog {
|
||||
private _autoRefreshHandle!: NodeJS.Timeout;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
private isRefreshing = false;
|
||||
|
||||
constructor(migrations: MigrationContext[], private _filter: AdsMigrationStatus) {
|
||||
this._model = new MigrationStatusDialogModel(migrations);
|
||||
this._dialogObject = azdata.window.createModelViewDialog(loc.MIGRATION_STATUS, 'MigrationControllerDialog', 'wide');
|
||||
@@ -109,19 +111,16 @@ export class MigrationStatusDialog {
|
||||
}));
|
||||
|
||||
this._refresh = this._view.modelBuilder.button().withProps({
|
||||
iconPath: {
|
||||
light: IconPathHelper.refresh.light,
|
||||
dark: IconPathHelper.refresh.dark
|
||||
},
|
||||
iconPath: IconPathHelper.refresh,
|
||||
iconHeight: '16px',
|
||||
iconWidth: '20px',
|
||||
height: '30px',
|
||||
label: loc.REFRESH_BUTTON_LABEL,
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._refresh.onDidClick((e) => {
|
||||
this.refreshTable();
|
||||
}));
|
||||
this._disposables.push(
|
||||
this._refresh.onDidClick(
|
||||
async (e) => { await this.refreshTable(); }));
|
||||
|
||||
const flexContainer = this._view.modelBuilder.flexContainer().withProps({
|
||||
width: 900,
|
||||
@@ -169,7 +168,7 @@ export class MigrationStatusDialog {
|
||||
const classVariable = this;
|
||||
clearInterval(this._autoRefreshHandle);
|
||||
if (interval !== -1) {
|
||||
this._autoRefreshHandle = setInterval(function () { classVariable.refreshTable(); }, interval);
|
||||
this._autoRefreshHandle = setInterval(async function () { await classVariable.refreshTable(); }, interval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,11 +446,22 @@ export class MigrationStatusDialog {
|
||||
}
|
||||
|
||||
private async refreshTable(): Promise<void> {
|
||||
this._refreshLoader.loading = true;
|
||||
const currentConnection = await azdata.connection.getCurrentConnection();
|
||||
this._model._migrations = await MigrationLocalStorage.getMigrationsBySourceConnections(currentConnection, true);
|
||||
await this.populateMigrationTable();
|
||||
this._refreshLoader.loading = false;
|
||||
if (this.isRefreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRefreshing = true;
|
||||
try {
|
||||
this._refreshLoader.loading = true;
|
||||
const currentConnection = await azdata.connection.getCurrentConnection();
|
||||
this._model._migrations = await MigrationLocalStorage.getMigrationsBySourceConnections(currentConnection, true);
|
||||
await this.populateMigrationTable();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
this._refreshLoader.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private createStatusTable(): azdata.DeclarativeTableComponent {
|
||||
|
||||
@@ -16,7 +16,7 @@ export class MigrationLocalStorage {
|
||||
}
|
||||
|
||||
public static async getMigrationsBySourceConnections(connectionProfile: azdata.connection.ConnectionProfile, refreshStatus?: boolean): Promise<MigrationContext[]> {
|
||||
|
||||
const undefinedSessionId = '{undefined}';
|
||||
const result: MigrationContext[] = [];
|
||||
const validMigrations: MigrationContext[] = [];
|
||||
|
||||
@@ -32,7 +32,7 @@ export class MigrationLocalStorage {
|
||||
migration.azureAccount,
|
||||
migration.subscription,
|
||||
migration.migrationContext,
|
||||
migration.sessionId!
|
||||
migration.sessionId ?? undefinedSessionId
|
||||
);
|
||||
migration.migrationContext.properties.sourceDatabaseName = sourceDatabase;
|
||||
migration.migrationContext.properties.backupConfiguration = backupConfiguration;
|
||||
@@ -41,7 +41,7 @@ export class MigrationLocalStorage {
|
||||
migration.azureAccount,
|
||||
migration.subscription,
|
||||
migration.asyncUrl,
|
||||
migration.sessionId!
|
||||
migration.sessionId ?? undefinedSessionId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user