From fbd86a7cc3c791a161f150f3e2a07d7432a5b39c Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Wed, 13 Sep 2023 20:08:55 +0200 Subject: fix(frontend): keep live while model generation Do not close the connection in a background tab if the model generation is still running, because closing the connection will immediately cancel generation. --- subprojects/frontend/src/xtext/XtextClient.ts | 9 +++++ .../frontend/src/xtext/XtextWebSocketClient.ts | 6 ++++ subprojects/frontend/src/xtext/webSocketMachine.ts | 40 +++++++++++++++++++--- 3 files changed, 51 insertions(+), 4 deletions(-) (limited to 'subprojects/frontend') diff --git a/subprojects/frontend/src/xtext/XtextClient.ts b/subprojects/frontend/src/xtext/XtextClient.ts index 77980d35..4df4f57a 100644 --- a/subprojects/frontend/src/xtext/XtextClient.ts +++ b/subprojects/frontend/src/xtext/XtextClient.ts @@ -9,6 +9,7 @@ import type { CompletionResult, } from '@codemirror/autocomplete'; import type { Transaction } from '@codemirror/state'; +import { type IReactionDisposer, reaction } from 'mobx'; import type PWAStore from '../PWAStore'; import type EditorStore from '../editor/EditorStore'; @@ -43,6 +44,8 @@ export default class XtextClient { private readonly modelGenerationService: ModelGenerationService; + private readonly keepAliveDisposer: IReactionDisposer; + constructor( private readonly store: EditorStore, private readonly pwaStore: PWAStore, @@ -65,6 +68,11 @@ export default class XtextClient { store, this.updateService, ); + this.keepAliveDisposer = reaction( + () => store.generating, + (generating) => this.webSocketClient.setKeepAlive(generating), + { fireImmediately: true }, + ); } start(): void { @@ -157,6 +165,7 @@ export default class XtextClient { } dispose(): void { + this.keepAliveDisposer(); this.webSocketClient.disconnect(); } } diff --git a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts index 963c1d4c..bb84223c 100644 --- a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts +++ b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts @@ -270,6 +270,12 @@ export default class XtextWebSocketClient { return promise; } + setKeepAlive(keepAlive: boolean): void { + this.interpreter.send({ + type: keepAlive ? 'GENERATION_STARTED' : 'GENERATION_ENDED', + }); + } + private updateVisibility(): void { this.interpreter.send(document.hidden ? 'TAB_HIDDEN' : 'TAB_VISIBLE'); } diff --git a/subprojects/frontend/src/xtext/webSocketMachine.ts b/subprojects/frontend/src/xtext/webSocketMachine.ts index 2fb1f52f..9113286f 100644 --- a/subprojects/frontend/src/xtext/webSocketMachine.ts +++ b/subprojects/frontend/src/xtext/webSocketMachine.ts @@ -27,6 +27,8 @@ export type WebSocketEvent = | { type: 'PAGE_RESUME' } | { type: 'ONLINE' } | { type: 'OFFLINE' } + | { type: 'GENERATION_STARTED' } + | { type: 'GENERATION_ENDED' } | { type: 'ERROR'; message: string }; export default createMachine( @@ -105,7 +107,7 @@ export default createMachine( initial: 'opening', states: { opening: { - always: [{ target: '#timedOut', in: '#tabHidden' }], + always: [{ target: '#timedOut', in: '#mayDisconnect' }], after: { OPEN_TIMEOUT: { actions: 'raiseTimeoutError', @@ -143,7 +145,7 @@ export default createMachine( initial: 'active', states: { active: { - always: [{ target: 'inactive', in: '#tabHidden' }], + always: [{ target: 'inactive', in: '#mayDisconnect' }], }, inactive: { always: [{ target: 'active', in: '#tabVisible' }], @@ -173,14 +175,44 @@ export default createMachine( visibleOrUnknown: { id: 'tabVisible', on: { - TAB_HIDDEN: 'hidden', + TAB_HIDDEN: [ + { target: 'hidden.mayDisconnect', in: '#generationIdle' }, + { target: 'hidden.keepAlive', in: '#generationRunning' }, + ], }, }, hidden: { - id: 'tabHidden', on: { TAB_VISIBLE: 'visibleOrUnknown', }, + initial: 'mayDisconnect', + states: { + mayDisconnect: { + id: 'mayDisconnect', + always: { target: 'keepAlive', in: '#generationRunning' }, + }, + keepAlive: { + id: 'keepAlive', + always: { target: 'mayDisconnect', in: '#generationIdle' }, + }, + }, + }, + }, + }, + generation: { + initial: 'idle', + states: { + idle: { + id: 'generationIdle', + on: { + GENERATION_STARTED: 'running', + }, + }, + running: { + id: 'generationRunning', + on: { + GENERATION_ENDED: 'idle', + }, }, }, }, -- cgit v1.2.3-54-g00ecf