This commit is contained in:
2023-05-30 21:16:11 +08:00
parent 7cfb63ecbf
commit 9311bd64ea
6 changed files with 64 additions and 12 deletions

12
db.ts
View File

@@ -371,6 +371,18 @@ export class EhDb {
task.details,
],
);
if (task.details === null) {
return this.db.queryEntries<Task>(
"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<Task>(
"SELECT * FROM task WHERE type = ? AND gid = ? AND token = ? AND pn = ? AND pid = ? AND details = ?;",
[

View File

@@ -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",

View File

@@ -6,11 +6,13 @@ export const handler: Handlers<Task[]> = {
GET(req, _ctx) {
const t = get_task_manager();
const { socket, response } = Deno.upgradeWebSocket(req);
const new_task_handle = (e: CustomEvent<Task>) => {
socket.send(JSON.stringify({ type: "new_task", detail: e.detail }));
const task_handle = (e: CustomEvent<Task>) => {
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<Task[]> = {
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;
},

View File

@@ -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,

View File

@@ -7,6 +7,7 @@
left: -64px;
transition: all 0.5s ease;
height: 100vh;
max-width: 64px;
}
.nav-menu.open {

View File

@@ -16,7 +16,9 @@ export class AlreadyClosedError extends Error {
}
type EventMap = {
new_task: CustomEvent<Task>;
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<T extends keyof EventMap>(
type: T,
callback: (e: EventMap[T]) => void | Promise<void>,
callback: (e: CustomEvent<EventMap[T]>) => void | Promise<void>,
options?: boolean | AddEventListenerOptions,
): void {
super.addEventListener(type, <EventListener> 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<T extends keyof EventMap>(
type: T,
callback: (e: EventMap[T]) => void | Promise<void>,
callback: (e: CustomEvent<EventMap[T]>) => void | Promise<void>,
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) {