From 9311bd64ea6119dfb9058b272b7e3e1c973fb334 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Tue, 30 May 2023 21:16:11 +0800 Subject: [PATCH] Update --- db.ts | 12 ++++++++++++ db_test.ts | 11 +++++++++++ routes/api/task.ts | 19 +++++++++++++++---- server.ts | 5 ++++- static/common.css | 1 + task_manager.ts | 28 +++++++++++++++++++++------- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/db.ts b/db.ts index 17d454d..7eefc29 100644 --- a/db.ts +++ b/db.ts @@ -371,6 +371,18 @@ export class EhDb { task.details, ], ); + if (task.details === null) { + return this.db.queryEntries( + "SELECT * FROM task WHERE type = ? AND gid = ? AND token = ? AND pn = ? AND pid = ?;", + [ + task.type, + task.gid, + task.token, + task.pn, + task.pid, + ], + )[0]; + } return this.db.queryEntries( "SELECT * FROM task WHERE type = ? AND gid = ? AND token = ? AND pn = ? AND pid = ? AND details = ?;", [ diff --git a/db_test.ts b/db_test.ts index 282e3a6..76db8f5 100644 --- a/db_test.ts +++ b/db_test.ts @@ -19,6 +19,17 @@ Deno.test("DbTest", async () => { details: null, }), ); + console.log( + await db.add_task({ + gid: 1, + token: "dd", + pid: 1, + pn: 1, + type: TaskType.ExportZip, + id: 0, + details: "test", + }), + ); const gmeta: GMeta = { gid: 1, token: "test", diff --git a/routes/api/task.ts b/routes/api/task.ts index cc74d09..703d03a 100644 --- a/routes/api/task.ts +++ b/routes/api/task.ts @@ -6,11 +6,13 @@ export const handler: Handlers = { GET(req, _ctx) { const t = get_task_manager(); const { socket, response } = Deno.upgradeWebSocket(req); - const new_task_handle = (e: CustomEvent) => { - socket.send(JSON.stringify({ type: "new_task", detail: e.detail })); + const task_handle = (e: CustomEvent) => { + socket.send(JSON.stringify({ type: e.type, detail: e.detail })); }; const removeListener = () => { - t.removeEventListener("new_task", new_task_handle); + t.removeEventListener("new_task", task_handle); + t.removeEventListener("task_started", task_handle); + t.removeEventListener("task_finished", task_handle); }; socket.onclose = () => { removeListener(); @@ -24,13 +26,22 @@ export const handler: Handlers = { const d = JSON.parse(e.data); if (d.type == "close") { socket.close(); + } else if (d.type == "new_download_task") { + const gid = d.gid; + const token = d.token; + if (typeof gid !== "number" || typeof token !== "string") { + return; + } + t.add_download_task(gid, token); } } catch (_) { null; } }; socket.onopen = () => { - t.addEventListener("new_task", new_task_handle); + t.addEventListener("new_task", task_handle); + t.addEventListener("task_started", task_handle); + t.addEventListener("task_finished", task_handle); }; return response; }, diff --git a/server.ts b/server.ts index c61d3a3..ced7afa 100644 --- a/server.ts +++ b/server.ts @@ -1,7 +1,7 @@ import { RenderFunction, start } from "$fresh/server.ts"; import { load_settings } from "./config.ts"; import manifest from "./fresh.gen.ts"; -import { TaskManager } from "./task_manager.ts"; +import { AlreadyClosedError, TaskManager } from "./task_manager.ts"; import twindPlugin from "$fresh/plugins/twind.ts"; import twindConfig from "./twind.config.ts"; import { load_translation } from "./server/i18ns.ts"; @@ -30,6 +30,9 @@ export async function startServer(path: string) { cfg_path = path; const cfg = await load_settings(path); task_manager = new TaskManager(cfg); + task_manager.run(true).catch((e) => { + if (!(e instanceof AlreadyClosedError)) throw e; + }); await load_translation(task_manager.aborts); return start(manifest, { signal: task_manager.aborts, diff --git a/static/common.css b/static/common.css index 2434a4e..d646a31 100644 --- a/static/common.css +++ b/static/common.css @@ -7,6 +7,7 @@ left: -64px; transition: all 0.5s ease; height: 100vh; + max-width: 64px; } .nav-menu.open { diff --git a/task_manager.ts b/task_manager.ts index b2ae239..04e8b24 100644 --- a/task_manager.ts +++ b/task_manager.ts @@ -16,7 +16,9 @@ export class AlreadyClosedError extends Error { } type EventMap = { - new_task: CustomEvent; + new_task: Task; + task_started: Task; + task_finished: Task; }; export class TaskManager extends EventTarget { @@ -39,6 +41,11 @@ export class TaskManager extends EventTarget { this.max_task_count = cfg.max_task_count; add_exit_handler(this); } + async #add_task(task: Task) { + const r = await this.db.add_task(task); + this.dispatchEvent(new CustomEvent("new_task", { detail: r })); + return r; + } #check_closed() { if (this.#closed) throw new AlreadyClosedError(); } @@ -48,7 +55,7 @@ export class TaskManager extends EventTarget { // @ts-ignore Checked type addEventListener( type: T, - callback: (e: EventMap[T]) => void | Promise, + callback: (e: CustomEvent) => void | Promise, options?: boolean | AddEventListenerOptions, ): void { super.addEventListener(type, callback, options); @@ -75,7 +82,7 @@ export class TaskManager extends EventTarget { type: TaskType.Download, details: null, }; - return await this.db.add_task(task); + return await this.#add_task(task); } async add_export_zip_task(gid: number, output?: string) { const cfg: ExportZipConfig = { output }; @@ -88,7 +95,7 @@ export class TaskManager extends EventTarget { type: TaskType.ExportZip, details: JSON.stringify(cfg), }; - return await this.db.add_task(task); + return await this.#add_task(task); } async check_task(task: Task) { this.#check_closed(); @@ -118,6 +125,9 @@ export class TaskManager extends EventTarget { if (status.status == PromiseStatus.Fulfilled && status.value) { removed_task.push(id); await this.db.delete_task(status.value); + this.dispatchEvent( + new CustomEvent("task_finished", { detail: status.value }), + ); } else if (status.status == PromiseStatus.Rejected) { if (status.reason && !this.aborted) console.log(status.reason); removed_task.push(id); @@ -147,7 +157,7 @@ export class TaskManager extends EventTarget { // @ts-ignore Checked type removeEventListener( type: T, - callback: (e: EventMap[T]) => void | Promise, + callback: (e: CustomEvent) => void | Promise, options?: boolean | EventListenerOptions, ): void { super.removeEventListener( @@ -156,7 +166,7 @@ export class TaskManager extends EventTarget { options, ); } - async run() { + async run(forever = false) { if (this.aborted || this.force_aborted) throw new AlreadyClosedError(); this.#check_closed(); while (1) { @@ -178,7 +188,10 @@ export class TaskManager extends EventTarget { const checked = await this.check_task(task); if (checked) this.run_task(checked); } - if (this.running_tasks.size == 0) break; + if (this.running_tasks.size == 0) { + if (!forever) break; + await sleep(1000); + } } } run_task(task: Task) { @@ -210,6 +223,7 @@ export class TaskManager extends EventTarget { ), ); } + this.dispatchEvent(new CustomEvent("task_started", { detail: task })); } async waiting_unfinished_task() { while (1) {