diff --git a/composables/task.ts b/composables/task.ts index 7a0c8f2..77515ef 100644 --- a/composables/task.ts +++ b/composables/task.ts @@ -2,45 +2,74 @@ import type { TaskMessage } from "~/server/internal/tasks"; import { WebSocketHandler } from "./ws"; const websocketHandler = new WebSocketHandler("/api/v1/task"); +const taskStates: { [key: string]: Ref } = {}; + +function handleUpdateMessage(msg: TaskMessage) { + const taskStates = useTaskStates(); + const state = taskStates[msg.id]; + if (!state) return; + if (!state.value || msg.reset) { + state.value = msg; + return; + } + state.value.log.push(...msg.log); + + Object.assign(state.value, { ...msg, log: state.value.log }); +} websocketHandler.listen((message) => { - const msg = JSON.parse(message) as TaskMessage; - const taskStates = useTaskStates(); - const state = taskStates.value[msg.id]; - if (!state) return; - state.value = msg; + try { + // If it's an object, it's an update message + const msg = JSON.parse(message) as TaskMessage; + handleUpdateMessage(msg); + } catch { + // Otherwise it's control message + const taskStates = useTaskStates(); + + const [action, ...data] = message.split("/"); + + switch (action) { + case "connect": + const taskReady = useTaskReady(); + taskReady.value = true; + break; + case "disconnect": + const disconnectTaskId = data[0]; + delete taskStates[disconnectTaskId]; + console.log(`disconnected from ${disconnectTaskId}`); + break; + case "error": + const [taskId, title, description] = data; + taskStates[taskId].value ??= { + id: taskId, + name: "Unknown task", + success: false, + progress: 0, + error: undefined, + log: [], + }; + taskStates[taskId].value.error = { title, description }; + break; + } + } }); -const useTaskStates = () => - useState<{ [key: string]: Ref }>("task-states", () => ({ - connect: useState("task-connect", () => ({ - id: "connect", - name: "Connect", - success: false, - progress: 0, - log: [], - error: undefined, - })), - })); +const useTaskStates = () => taskStates; -export const useTaskReady = () => { +export const useTaskReady = () => useState("taskready", () => false); + +export const useTask = (taskId: string): Ref => { + if (import.meta.server) return ref(undefined); const taskStates = useTaskStates(); - return taskStates.value["connect"]; -}; + if ( + taskStates[taskId] && + taskStates[taskId].value && + !taskStates[taskId].value.error + ) + return taskStates[taskId]; -export const useTask = (taskId: string): Ref => { - if (import.meta.server) return {} as unknown as Ref; - const taskStates = useTaskStates(); - if (taskStates.value[taskId]) return taskStates.value[taskId]; - - taskStates.value[taskId] = useState(`task-${taskId}`, () => ({ - id: taskId, - name: "loading...", - success: false, - progress: 0, - error: undefined, - log: [], - })); + taskStates[taskId] = ref(undefined); + console.log("connecting to " + taskId); websocketHandler.send(`connect/${taskId}`); - return taskStates.value[taskId]; + return taskStates[taskId]; }; diff --git a/pages/admin/task/[id]/index.vue b/pages/admin/task/[id]/index.vue index 36833a8..fee6e7f 100644 --- a/pages/admin/task/[id]/index.vue +++ b/pages/admin/task/[id]/index.vue @@ -1,7 +1,7 @@