diff options
Diffstat (limited to 'language-web/src/main/js/xtext/XtextWebSocketClient.ts')
-rw-r--r-- | language-web/src/main/js/xtext/XtextWebSocketClient.ts | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/language-web/src/main/js/xtext/XtextWebSocketClient.ts b/language-web/src/main/js/xtext/XtextWebSocketClient.ts index 488e4b3b..2ce20a54 100644 --- a/language-web/src/main/js/xtext/XtextWebSocketClient.ts +++ b/language-web/src/main/js/xtext/XtextWebSocketClient.ts | |||
@@ -4,12 +4,13 @@ import { getLogger } from '../utils/logger'; | |||
4 | import { PendingTask } from '../utils/PendingTask'; | 4 | import { PendingTask } from '../utils/PendingTask'; |
5 | import { Timer } from '../utils/Timer'; | 5 | import { Timer } from '../utils/Timer'; |
6 | import { | 6 | import { |
7 | isErrorResponse, | 7 | xtextWebErrorResponse, |
8 | isOkResponse, | 8 | XtextWebRequest, |
9 | isPushMessage, | 9 | xtextWebOkResponse, |
10 | IXtextWebRequest, | 10 | xtextWebPushMessage, |
11 | XtextWebPushService, | ||
11 | } from './xtextMessages'; | 12 | } from './xtextMessages'; |
12 | import { isPongResult } from './xtextServiceResults'; | 13 | import { pongResult } from './xtextServiceResults'; |
13 | 14 | ||
14 | const XTEXT_SUBPROTOCOL_V1 = 'tools.refinery.language.web.xtext.v1'; | 15 | const XTEXT_SUBPROTOCOL_V1 = 'tools.refinery.language.web.xtext.v1'; |
15 | 16 | ||
@@ -32,7 +33,7 @@ export type ReconnectHandler = () => void; | |||
32 | export type PushHandler = ( | 33 | export type PushHandler = ( |
33 | resourceId: string, | 34 | resourceId: string, |
34 | stateId: string, | 35 | stateId: string, |
35 | service: string, | 36 | service: XtextWebPushService, |
36 | data: unknown, | 37 | data: unknown, |
37 | ) => void; | 38 | ) => void; |
38 | 39 | ||
@@ -192,11 +193,12 @@ export class XtextWebSocketClient { | |||
192 | const ping = nanoid(); | 193 | const ping = nanoid(); |
193 | log.trace('Ping', ping); | 194 | log.trace('Ping', ping); |
194 | this.send({ ping }).then((result) => { | 195 | this.send({ ping }).then((result) => { |
195 | if (isPongResult(result) && result.pong === ping) { | 196 | const parsedPongResult = pongResult.safeParse(result); |
197 | if (parsedPongResult.success && parsedPongResult.data.pong === ping) { | ||
196 | log.trace('Pong', ping); | 198 | log.trace('Pong', ping); |
197 | this.pingTimer.schedule(); | 199 | this.pingTimer.schedule(); |
198 | } else { | 200 | } else { |
199 | log.error('Invalid pong'); | 201 | log.error('Invalid pong:', parsedPongResult, 'expected:', ping); |
200 | this.forceReconnectOnError(); | 202 | this.forceReconnectOnError(); |
201 | } | 203 | } |
202 | }).catch((error) => { | 204 | }).catch((error) => { |
@@ -222,7 +224,7 @@ export class XtextWebSocketClient { | |||
222 | const message = JSON.stringify({ | 224 | const message = JSON.stringify({ |
223 | id: messageId, | 225 | id: messageId, |
224 | request, | 226 | request, |
225 | } as IXtextWebRequest); | 227 | } as XtextWebRequest); |
226 | log.trace('Sending message', message); | 228 | log.trace('Sending message', message); |
227 | return new Promise((resolve, reject) => { | 229 | return new Promise((resolve, reject) => { |
228 | const task = new PendingTask(resolve, reject, REQUEST_TIMEOUT_MS, () => { | 230 | const task = new PendingTask(resolve, reject, REQUEST_TIMEOUT_MS, () => { |
@@ -248,23 +250,42 @@ export class XtextWebSocketClient { | |||
248 | this.forceReconnectOnError(); | 250 | this.forceReconnectOnError(); |
249 | return; | 251 | return; |
250 | } | 252 | } |
251 | if (isOkResponse(message)) { | 253 | const okResponse = xtextWebOkResponse.safeParse(message); |
252 | this.resolveRequest(message.id, message.response); | 254 | if (okResponse.success) { |
253 | } else if (isErrorResponse(message)) { | 255 | const { id, response } = okResponse.data; |
254 | this.rejectRequest(message.id, new Error(`${message.error} error: ${message.message}`)); | 256 | this.resolveRequest(id, response); |
255 | if (message.error === 'server') { | 257 | return; |
256 | log.error('Reconnecting due to server error: ', message.message); | 258 | } |
259 | const errorResponse = xtextWebErrorResponse.safeParse(message); | ||
260 | if (errorResponse.success) { | ||
261 | const { id, error, message: errorMessage } = errorResponse.data; | ||
262 | this.rejectRequest(id, new Error(`${error} error: ${errorMessage}`)); | ||
263 | if (error === 'server') { | ||
264 | log.error('Reconnecting due to server error: ', errorMessage); | ||
257 | this.forceReconnectOnError(); | 265 | this.forceReconnectOnError(); |
258 | } | 266 | } |
259 | } else if (isPushMessage(message)) { | 267 | return; |
260 | this.onPush( | 268 | } |
261 | message.resource, | 269 | const pushMessage = xtextWebPushMessage.safeParse(message); |
262 | message.stateId, | 270 | if (pushMessage.success) { |
263 | message.service, | 271 | const { |
264 | message.push, | 272 | resource, |
265 | ); | 273 | stateId, |
274 | service, | ||
275 | push, | ||
276 | } = pushMessage.data; | ||
277 | this.onPush(resource, stateId, service, push); | ||
266 | } else { | 278 | } else { |
267 | log.error('Unexpected websocket message', message); | 279 | log.error( |
280 | 'Unexpected websocket message:', | ||
281 | message, | ||
282 | 'not ok response because:', | ||
283 | okResponse.error, | ||
284 | 'not error response because:', | ||
285 | errorResponse.error, | ||
286 | 'not push message because:', | ||
287 | pushMessage.error, | ||
288 | ); | ||
268 | this.forceReconnectOnError(); | 289 | this.forceReconnectOnError(); |
269 | } | 290 | } |
270 | } | 291 | } |