Skip to content

Commit c002d4b

Browse files
authored
Merge pull request #1194 from writer/AB-714
feat(ui): prevent socket to be closed after a background job - AB-714
2 parents 37edf18 + 9253e4a commit c002d4b

3 files changed

Lines changed: 27 additions & 4 deletions

File tree

src/ui/src/builder/BuilderApp.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ const collaborationManager = inject(injectionKeys.collaborationManager);
189189
const tracking = useWriterTracking(wf);
190190
const toasts = useToasts();
191191
192-
provide(injectionKeys.socketTimeout, useSocketTimeout(wf, 10));
192+
const SOCKET_TIMEOUT_MIN =
193+
Number(localStorage.getItem("socketTimeoutMin")) || 10;
194+
provide(injectionKeys.socketTimeout, useSocketTimeout(wf, SOCKET_TIMEOUT_MIN));
193195
194196
const noteEl = useTemplateRef("noteEl");
195197
const rendererEl = useTemplateRef("rendererEl");

src/ui/src/builder/useSocketTimeout.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { nextTick } from "vue";
1111
import { useSocketTimeout } from "./useSocketTimeout";
1212
import { buildMockCore } from "@/tests/mocks";
13+
import { flushPromises } from "@vue/test-utils";
1314

1415
// Mock dependencies
1516
vi.mock("@/composables/useLogger", () => ({
@@ -89,7 +90,7 @@ describe("useSocketTimeout", () => {
8990
expect(schedule()).toBe(true);
9091
});
9192

92-
it("should not schedule timeout if frontend message exists", () => {
93+
it("should not schedule timeout if frontend message exists", async () => {
9394
mockCore.frontendMessageMap.value.set(1, { type: "event" });
9495
const { schedule, onVisibilityChange } = useSocketTimeout(
9596
mockCore.core,
@@ -99,6 +100,12 @@ describe("useSocketTimeout", () => {
99100
onVisibilityChange();
100101

101102
expect(schedule()).toBe(false);
103+
expect(vi.getTimerCount()).toBe(0);
104+
105+
// even if the task finished in background
106+
mockCore.frontendMessageMap.value.clear();
107+
await flushPromises();
108+
expect(vi.getTimerCount()).toBe(0);
102109
});
103110

104111
it("should clear schedule when clearSchedule is called", () => {

src/ui/src/builder/useSocketTimeout.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const WEBSOCKET_INACTIVITY_CLOSE_CODE = 4000;
1212
export function useSocketTimeout(wf: Core, timeoutMin: number) {
1313
const timeoutMs = timeoutMin * 60 * 1_000;
1414
const logger = useLogger();
15+
const abort = useAbortController();
1516

1617
let timer = undefined;
1718

@@ -51,8 +52,6 @@ export function useSocketTimeout(wf: Core, timeoutMin: number) {
5152
() => !prevent.value && !isMessagePending.value,
5253
);
5354

54-
const abort = useAbortController();
55-
5655
function schedule() {
5756
if (!canCloseSocket.value || document.visibilityState !== "hidden")
5857
return false;
@@ -77,13 +76,16 @@ export function useSocketTimeout(wf: Core, timeoutMin: number) {
7776
timer = undefined;
7877
}
7978

79+
// cancel closing socket timer
8080
watch(canCloseSocket, () => {
8181
if (!canCloseSocket.value) {
8282
clearSchedule();
8383
} else if (document.visibilityState === "hidden") {
8484
schedule(); // Reschedule now that activity is complete
8585
}
8686
});
87+
88+
// reflect `preventTasks` changes in session storage
8789
watch(
8890
preventTasks,
8991
() => {
@@ -92,6 +94,17 @@ export function useSocketTimeout(wf: Core, timeoutMin: number) {
9294
{ deep: true },
9395
);
9496

97+
// prevent closing socket when blueprint finish in background
98+
watch(isMessagePending, (hasPending, hadPending) => {
99+
const hadCompletedJob = hadPending && !hasPending;
100+
if (hadCompletedJob && document.visibilityState === "hidden") {
101+
logger.log(
102+
`[SocketTimeout] Preventing socket to be closed due to finished task in background...`,
103+
);
104+
preventTasks.value.add("pendingMessageInBackground");
105+
}
106+
});
107+
95108
async function reconnect() {
96109
logger.info(`[SocketTimeout] Attempting to reconnect socket...`);
97110
reconnecting.value = true;
@@ -112,6 +125,7 @@ export function useSocketTimeout(wf: Core, timeoutMin: number) {
112125

113126
function onVisibilityChange() {
114127
if (document.visibilityState === "visible") {
128+
preventTasks.value.delete("pendingMessageInBackground");
115129
clearSchedule();
116130
} else if (canCloseSocket.value) {
117131
schedule();

0 commit comments

Comments
 (0)