From 2c94b73460452d55a4d0a5542509d1de1d9c071b Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Wed, 27 Oct 2021 21:35:57 +0200 Subject: chore(web): refactor PendingTask --- language-web/src/main/js/editor/PendingRequest.ts | 55 -------------------- .../src/main/js/editor/XtextWebSocketClient.ts | 18 ++++--- language-web/src/main/js/utils/PendingTask.ts | 60 ++++++++++++++++++++++ 3 files changed, 70 insertions(+), 63 deletions(-) delete mode 100644 language-web/src/main/js/editor/PendingRequest.ts create mode 100644 language-web/src/main/js/utils/PendingTask.ts (limited to 'language-web') diff --git a/language-web/src/main/js/editor/PendingRequest.ts b/language-web/src/main/js/editor/PendingRequest.ts deleted file mode 100644 index 49d4c36c..00000000 --- a/language-web/src/main/js/editor/PendingRequest.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { getLogger } from '../logging'; - -const REQUEST_TIMEOUT_MS = 1000; - -const log = getLogger('PendingRequest'); - -export class PendingRequest { - private readonly resolveCallback: (value: unknown) => void; - - private readonly rejectCallback: (reason?: unknown) => void; - - private readonly timeoutCallback: () => void; - - private resolved = false; - - private timeoutId: NodeJS.Timeout; - - constructor( - resolve: (value: unknown) => void, - reject: (reason?: unknown) => void, - timeout: () => void, - ) { - this.resolveCallback = resolve; - this.rejectCallback = reject; - this.timeoutCallback = timeout; - this.timeoutId = setTimeout(() => { - if (!this.resolved) { - this.reject(new Error('Request timed out')); - this.timeoutCallback(); - } - }, REQUEST_TIMEOUT_MS); - } - - resolve(value: unknown): void { - if (this.resolved) { - log.warn('Trying to resolve already resolved promise'); - return; - } - this.markResolved(); - this.resolveCallback(value); - } - - reject(reason?: unknown): void { - if (this.resolved) { - log.warn('Trying to reject already resolved promise'); - } - this.markResolved(); - this.rejectCallback(reason); - } - - private markResolved() { - this.resolved = true; - clearTimeout(this.timeoutId); - } -} diff --git a/language-web/src/main/js/editor/XtextWebSocketClient.ts b/language-web/src/main/js/editor/XtextWebSocketClient.ts index 489ac03d..5b775500 100644 --- a/language-web/src/main/js/editor/XtextWebSocketClient.ts +++ b/language-web/src/main/js/editor/XtextWebSocketClient.ts @@ -1,7 +1,7 @@ import { nanoid } from 'nanoid'; import { getLogger } from '../logging'; -import { PendingRequest } from './PendingRequest'; +import { PendingTask } from '../utils/PendingTask'; import { Timer } from '../utils/Timer'; import { isErrorResponse, @@ -23,6 +23,8 @@ const BACKGROUND_IDLE_TIMEOUT_MS = 5 * 60 * 1000; const PING_TIMEOUT_MS = 10 * 1000; +const REQUEST_TIMEOUT_MS = 1000; + const log = getLogger('XtextWebSocketClient'); type ReconnectHandler = () => Promise; @@ -49,7 +51,7 @@ export class XtextWebSocketClient { connection!: WebSocket; - pendingRequests = new Map(); + pendingRequests = new Map>(); onReconnect: ReconnectHandler; @@ -223,14 +225,14 @@ export class XtextWebSocketClient { id: messageId, request, } as IXtextWebRequest); - const promise = new Promise((resolve, reject) => { - this.pendingRequests.set(messageId, new PendingRequest(resolve, reject, () => { + log.trace('Sending message', message); + return new Promise((resolve, reject) => { + const task = new PendingTask(resolve, reject, REQUEST_TIMEOUT_MS, () => { this.removePendingRequest(messageId); - })); + }); + this.pendingRequests.set(messageId, task); + this.connection.send(message); }); - log.trace('Sending message', message); - this.connection.send(message); - return promise; } private handleMessage(messageStr: unknown) { diff --git a/language-web/src/main/js/utils/PendingTask.ts b/language-web/src/main/js/utils/PendingTask.ts new file mode 100644 index 00000000..aa2b11b0 --- /dev/null +++ b/language-web/src/main/js/utils/PendingTask.ts @@ -0,0 +1,60 @@ +import { getLogger } from '../logging'; + +const log = getLogger('PendingTask'); + +export class PendingTask { + private readonly resolveCallback: (value: T) => void; + + private readonly rejectCallback: (reason?: unknown) => void; + + private resolved = false; + + private timeout: NodeJS.Timeout | null; + + constructor( + resolveCallback: (value: T) => void, + rejectCallback: (reason?: unknown) => void, + timeoutMs?: number, + timeoutCallback?: () => void, + ) { + this.resolveCallback = resolveCallback; + this.rejectCallback = rejectCallback; + if (timeoutMs) { + this.timeout = setTimeout(() => { + if (!this.resolved) { + this.reject(new Error('Request timed out')); + if (timeoutCallback) { + timeoutCallback(); + } + } + }, timeoutMs); + } else { + this.timeout = null; + } + } + + resolve(value: T): void { + if (this.resolved) { + log.warn('Trying to resolve already resolved promise'); + return; + } + this.markResolved(); + this.resolveCallback(value); + } + + reject(reason?: unknown): void { + if (this.resolved) { + log.warn('Trying to reject already resolved promise'); + return; + } + this.markResolved(); + this.rejectCallback(reason); + } + + private markResolved() { + this.resolved = true; + if (this.timeout !== null) { + clearTimeout(this.timeout); + } + } +} -- cgit v1.2.3-54-g00ecf