mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 4c9161a3f125f5a788aafa73a4ecfcb27dcfc319 (#9143)
* Merge from vscode 4c9161a3f125f5a788aafa73a4ecfcb27dcfc319 * minor spacing fix
This commit is contained in:
@@ -779,3 +779,107 @@ export async function retry<T>(task: ITask<Promise<T>>, delay: number, retries:
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
//#region Task Sequentializer
|
||||
|
||||
interface IPendingTask {
|
||||
taskId: number;
|
||||
cancel: () => void;
|
||||
promise: Promise<void>;
|
||||
}
|
||||
|
||||
interface ISequentialTask {
|
||||
promise: Promise<void>;
|
||||
promiseResolve: () => void;
|
||||
promiseReject: (error: Error) => void;
|
||||
run: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface ITaskSequentializerWithPendingTask {
|
||||
readonly pending: Promise<void>;
|
||||
}
|
||||
|
||||
export class TaskSequentializer {
|
||||
private _pending?: IPendingTask;
|
||||
private _next?: ISequentialTask;
|
||||
|
||||
hasPending(taskId?: number): this is ITaskSequentializerWithPendingTask {
|
||||
if (!this._pending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof taskId === 'number') {
|
||||
return this._pending.taskId === taskId;
|
||||
}
|
||||
|
||||
return !!this._pending;
|
||||
}
|
||||
|
||||
get pending(): Promise<void> | undefined {
|
||||
return this._pending ? this._pending.promise : undefined;
|
||||
}
|
||||
|
||||
cancelPending(): void {
|
||||
this._pending?.cancel();
|
||||
}
|
||||
|
||||
setPending(taskId: number, promise: Promise<void>, onCancel?: () => void, ): Promise<void> {
|
||||
this._pending = { taskId: taskId, cancel: () => onCancel?.(), promise };
|
||||
|
||||
promise.then(() => this.donePending(taskId), () => this.donePending(taskId));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private donePending(taskId: number): void {
|
||||
if (this._pending && taskId === this._pending.taskId) {
|
||||
|
||||
// only set pending to done if the promise finished that is associated with that taskId
|
||||
this._pending = undefined;
|
||||
|
||||
// schedule the next task now that we are free if we have any
|
||||
this.triggerNext();
|
||||
}
|
||||
}
|
||||
|
||||
private triggerNext(): void {
|
||||
if (this._next) {
|
||||
const next = this._next;
|
||||
this._next = undefined;
|
||||
|
||||
// Run next task and complete on the associated promise
|
||||
next.run().then(next.promiseResolve, next.promiseReject);
|
||||
}
|
||||
}
|
||||
|
||||
setNext(run: () => Promise<void>): Promise<void> {
|
||||
|
||||
// this is our first next task, so we create associated promise with it
|
||||
// so that we can return a promise that completes when the task has
|
||||
// completed.
|
||||
if (!this._next) {
|
||||
let promiseResolve: () => void;
|
||||
let promiseReject: (error: Error) => void;
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
promiseResolve = resolve;
|
||||
promiseReject = reject;
|
||||
});
|
||||
|
||||
this._next = {
|
||||
run,
|
||||
promise,
|
||||
promiseResolve: promiseResolve!,
|
||||
promiseReject: promiseReject!
|
||||
};
|
||||
}
|
||||
|
||||
// we have a previous next task, just overwrite it
|
||||
else {
|
||||
this._next.run = run;
|
||||
}
|
||||
|
||||
return this._next.promise;
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
Reference in New Issue
Block a user