diff --git a/packages/server/src/route/comic.ts b/packages/server/src/route/comic.ts index 23ac39c..6b30b0b 100644 --- a/packages/server/src/route/comic.ts +++ b/packages/server/src/route/comic.ts @@ -3,71 +3,13 @@ import Router from "koa-router"; import { createReadableStreamFromZip, entriesByNaturalOrder, readZip } from "../util/zipwrap.ts"; import type { ContentContext } from "./context.ts"; import { since_last_modified } from "./util.ts"; -import type { ZipReader } from "@zip.js/zip.js"; -import type { FileHandle } from "node:fs/promises"; import { Readable } from "node:stream"; -/** - * zip stream cache. - */ -const ZipStreamCache = new Map, - refCount: number, -}>(); - - -function markUseZip(path: string) { - const ret = ZipStreamCache.get(path); - if (ret) { - ret.refCount++; - } - return ret !== undefined; -} - -async function acquireZip(path: string, marked = false) { - const ret = ZipStreamCache.get(path); - if (!ret) { - const obj = await readZip(path); - const check = ZipStreamCache.get(path); - if (check) { - check.refCount++; - // if the cache is updated, release the previous one. - releaseZip(path); - return check.reader; - } - // if the cache is not updated, set the new one. - ZipStreamCache.set(path, { - reader: obj.reader, - refCount: 1, - }); - return obj.reader; - } - if (!marked) { - ret.refCount++; - } - return ret.reader; -} - -function releaseZip(path: string) { - const obj = ZipStreamCache.get(path); - if (obj === undefined) { - console.warn(`warning! duplicate release at ${path}`); - return; - } - if (obj.refCount === 1) { - const { reader } = obj; - reader.close(); - ZipStreamCache.delete(path); - } else { - obj.refCount--; - } -} async function renderZipImage(ctx: Context, path: string, page: number) { const image_ext = ["gif", "png", "jpeg", "bmp", "webp", "jpg", "avif"]; - const marked = markUseZip(path); - const zip = await acquireZip(path, marked); - const entries = (await entriesByNaturalOrder(zip)).filter((x) => { + const zip = await readZip(path); + const entries = (await entriesByNaturalOrder(zip.reader)).filter((x) => { const ext = x.filename.split(".").pop(); return ext !== undefined && image_ext.includes(ext); }); @@ -77,7 +19,7 @@ async function renderZipImage(ctx: Context, path: string, page: number) { if (since_last_modified(ctx, last_modified)) { return; } - const read_stream = await createReadableStreamFromZip(zip, entry); + const read_stream = await createReadableStreamFromZip(zip.reader, entry); const nodeReadableStream = new Readable(); nodeReadableStream._read = () => { }; @@ -91,14 +33,13 @@ async function renderZipImage(ctx: Context, path: string, page: number) { })); nodeReadableStream.on("error", (err) => { console.error("readalbe stream error",err); - setTimeout(()=>{ - releaseZip(path) - },100); + ctx.status = 500; + ctx.body = "Internal Server Error"; + zip.reader.close(); + return; }); nodeReadableStream.on("close", () => { - setTimeout(()=>{ - releaseZip(path); - },100); + zip.reader.close(); }); ctx.body = nodeReadableStream; diff --git a/packages/server/src/util/zipwrap.ts b/packages/server/src/util/zipwrap.ts index 30facc0..5f0ece2 100644 --- a/packages/server/src/util/zipwrap.ts +++ b/packages/server/src/util/zipwrap.ts @@ -21,6 +21,7 @@ class FileReader extends Reader { // not implemented yet (this.fd as unknown as EventEmitter).on("close", () => { console.warn(`file handle closed: ${this.path}`); + this.fd?.close(); this.fd = undefined; }); }