aboutsummaryrefslogtreecommitdiffstats
path: root/language-web
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-27 21:35:57 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-10-31 19:26:13 +0100
commit2c94b73460452d55a4d0a5542509d1de1d9c071b (patch)
treefc25067e91109378ce4f09c66e7a9d5f6dba010c /language-web
parentchore(web): simplify websocket state machine (diff)
downloadrefinery-2c94b73460452d55a4d0a5542509d1de1d9c071b.tar.gz
refinery-2c94b73460452d55a4d0a5542509d1de1d9c071b.tar.zst
refinery-2c94b73460452d55a4d0a5542509d1de1d9c071b.zip
chore(web): refactor PendingTask
Diffstat (limited to 'language-web')
-rw-r--r--language-web/src/main/js/editor/PendingRequest.ts55
-rw-r--r--language-web/src/main/js/editor/XtextWebSocketClient.ts18
-rw-r--r--language-web/src/main/js/utils/PendingTask.ts60
3 files changed, 70 insertions, 63 deletions
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 @@
1import { getLogger } from '../logging';
2
3const REQUEST_TIMEOUT_MS = 1000;
4
5const log = getLogger('PendingRequest');
6
7export class PendingRequest {
8 private readonly resolveCallback: (value: unknown) => void;
9
10 private readonly rejectCallback: (reason?: unknown) => void;
11
12 private readonly timeoutCallback: () => void;
13
14 private resolved = false;
15
16 private timeoutId: NodeJS.Timeout;
17
18 constructor(
19 resolve: (value: unknown) => void,
20 reject: (reason?: unknown) => void,
21 timeout: () => void,
22 ) {
23 this.resolveCallback = resolve;
24 this.rejectCallback = reject;
25 this.timeoutCallback = timeout;
26 this.timeoutId = setTimeout(() => {
27 if (!this.resolved) {
28 this.reject(new Error('Request timed out'));
29 this.timeoutCallback();
30 }
31 }, REQUEST_TIMEOUT_MS);
32 }
33
34 resolve(value: unknown): void {
35 if (this.resolved) {
36 log.warn('Trying to resolve already resolved promise');
37 return;
38 }
39 this.markResolved();
40 this.resolveCallback(value);
41 }
42
43 reject(reason?: unknown): void {
44 if (this.resolved) {
45 log.warn('Trying to reject already resolved promise');
46 }
47 this.markResolved();
48 this.rejectCallback(reason);
49 }
50
51 private markResolved() {
52 this.resolved = true;
53 clearTimeout(this.timeoutId);
54 }
55}
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 @@
1import { nanoid } from 'nanoid'; 1import { nanoid } from 'nanoid';
2 2
3import { getLogger } from '../logging'; 3import { getLogger } from '../logging';
4import { PendingRequest } from './PendingRequest'; 4import { PendingTask } from '../utils/PendingTask';
5import { Timer } from '../utils/Timer'; 5import { Timer } from '../utils/Timer';
6import { 6import {
7 isErrorResponse, 7 isErrorResponse,
@@ -23,6 +23,8 @@ const BACKGROUND_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
23 23
24const PING_TIMEOUT_MS = 10 * 1000; 24const PING_TIMEOUT_MS = 10 * 1000;
25 25
26const REQUEST_TIMEOUT_MS = 1000;
27
26const log = getLogger('XtextWebSocketClient'); 28const log = getLogger('XtextWebSocketClient');
27 29
28type ReconnectHandler = () => Promise<void>; 30type ReconnectHandler = () => Promise<void>;
@@ -49,7 +51,7 @@ export class XtextWebSocketClient {
49 51
50 connection!: WebSocket; 52 connection!: WebSocket;
51 53
52 pendingRequests = new Map<string, PendingRequest>(); 54 pendingRequests = new Map<string, PendingTask<unknown>>();
53 55
54 onReconnect: ReconnectHandler; 56 onReconnect: ReconnectHandler;
55 57
@@ -223,14 +225,14 @@ export class XtextWebSocketClient {
223 id: messageId, 225 id: messageId,
224 request, 226 request,
225 } as IXtextWebRequest); 227 } as IXtextWebRequest);
226 const promise = new Promise((resolve, reject) => { 228 log.trace('Sending message', message);
227 this.pendingRequests.set(messageId, new PendingRequest(resolve, reject, () => { 229 return new Promise((resolve, reject) => {
230 const task = new PendingTask(resolve, reject, REQUEST_TIMEOUT_MS, () => {
228 this.removePendingRequest(messageId); 231 this.removePendingRequest(messageId);
229 })); 232 });
233 this.pendingRequests.set(messageId, task);
234 this.connection.send(message);
230 }); 235 });
231 log.trace('Sending message', message);
232 this.connection.send(message);
233 return promise;
234 } 236 }
235 237
236 private handleMessage(messageStr: unknown) { 238 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 @@
1import { getLogger } from '../logging';
2
3const log = getLogger('PendingTask');
4
5export class PendingTask<T> {
6 private readonly resolveCallback: (value: T) => void;
7
8 private readonly rejectCallback: (reason?: unknown) => void;
9
10 private resolved = false;
11
12 private timeout: NodeJS.Timeout | null;
13
14 constructor(
15 resolveCallback: (value: T) => void,
16 rejectCallback: (reason?: unknown) => void,
17 timeoutMs?: number,
18 timeoutCallback?: () => void,
19 ) {
20 this.resolveCallback = resolveCallback;
21 this.rejectCallback = rejectCallback;
22 if (timeoutMs) {
23 this.timeout = setTimeout(() => {
24 if (!this.resolved) {
25 this.reject(new Error('Request timed out'));
26 if (timeoutCallback) {
27 timeoutCallback();
28 }
29 }
30 }, timeoutMs);
31 } else {
32 this.timeout = null;
33 }
34 }
35
36 resolve(value: T): void {
37 if (this.resolved) {
38 log.warn('Trying to resolve already resolved promise');
39 return;
40 }
41 this.markResolved();
42 this.resolveCallback(value);
43 }
44
45 reject(reason?: unknown): void {
46 if (this.resolved) {
47 log.warn('Trying to reject already resolved promise');
48 return;
49 }
50 this.markResolved();
51 this.rejectCallback(reason);
52 }
53
54 private markResolved() {
55 this.resolved = true;
56 if (this.timeout !== null) {
57 clearTimeout(this.timeout);
58 }
59 }
60}