diff --git a/webapp/packages/core-authentication/src/UserInfoResource.ts b/webapp/packages/core-authentication/src/UserInfoResource.ts index 8ec9d23768..132327173a 100644 --- a/webapp/packages/core-authentication/src/UserInfoResource.ts +++ b/webapp/packages/core-authentication/src/UserInfoResource.ts @@ -140,6 +140,8 @@ export class UserInfoResource extends CachedDataResource( callback: (value: T) => Promise | boolean, task: () => Promise, interval: number, cancelMessage?: string, + timeout?: number, ): ITask { let resolve: (value: T | PromiseLike) => void; let reject: (reason?: any) => void; + let fulfilled = false; + + let intervalTimeoutId: NodeJS.Timeout | null = null; + let timeoutId: NodeJS.Timeout | null = null; + let activeTask: Promise | null = null; + let stopped = false; const lockPromise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; + }).finally(() => { + if (intervalTimeoutId !== null) { + clearTimeout(intervalTimeoutId); + } + + if (timeoutId !== null) { + clearTimeout(timeoutId); + } + + fulfilled = true; }); - let timeoutId: NodeJS.Timeout | null; - let activeTask: Promise | null; - let stopped = false; - function stop() { - if (timeoutId) { - clearTimeout(timeoutId); + if (intervalTimeoutId !== null) { + clearTimeout(intervalTimeoutId); } stopped = true; } async function cancelTask(exception?: any) { + if (fulfilled) { + return; + } + stop(); if (activeTask instanceof Task) { @@ -44,6 +63,10 @@ export function whileTask( reject(exception); } + if (timeout !== undefined) { + timeoutId = setTimeout(() => cancelTask(new TimeoutError('Task timeout exceeded')), timeout); + } + function runTask() { activeTask = task(); activeTask @@ -56,7 +79,7 @@ export function whileTask( if (state) { resolve(value); } else if (!stopped) { - timeoutId = setTimeout(runTask, interval); + intervalTimeoutId = setTimeout(runTask, interval); } }) .catch(cancelTask); @@ -67,6 +90,6 @@ export function whileTask( runTask(); return lockPromise; }, - () => cancelTask(new Error(cancelMessage ?? 'Task was cancelled')), + () => cancelTask(new CancelError(cancelMessage ?? 'Task was cancelled')), ); }