From 53c39cc3a72ffb6f588c2fe5f46a0a8ee57e551d Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 31 Aug 2025 14:22:18 +1000 Subject: [PATCH 1/4] feat: pre-allocate streams for high-latency downloads --- nuxt.config.ts | 6 +++-- server/api/v2/client/chunk.post.ts | 36 +++++++++++++++++------------- server/middleware/latency.ts | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index 49cc4e37..534f54af 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -74,7 +74,8 @@ export default defineNuxtConfig({ vite: { plugins: [ - tailwindcss(), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tailwindcss() as any, // only used in dev server, not build because nitro sucks // see build hook below viteStaticCopy({ @@ -84,7 +85,8 @@ export default defineNuxtConfig({ dest: "twemoji", }, ], - }), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }) as any, ], }, diff --git a/server/api/v2/client/chunk.post.ts b/server/api/v2/client/chunk.post.ts index 84022038..bb2d0229 100644 --- a/server/api/v2/client/chunk.post.ts +++ b/server/api/v2/client/chunk.post.ts @@ -9,7 +9,7 @@ const GetChunk = type({ files: type({ filename: "string", chunkIndex: "number", - }).array(), + }).array().atLeastLength(1).atMostLength(256), }).configure(throwingArktype); export default defineEventHandler(async (h3) => { @@ -46,21 +46,27 @@ export default defineEventHandler(async (h3) => { streamFiles.map((e) => e.end - e.start).join(","), ); // Non-standard header, but we're cool like that 😎 - for (const file of streamFiles) { - const gameReadStream = await libraryManager.readFile( - context.libraryId, - context.libraryPath, - context.versionName, - file.filename, - { start: file.start, end: file.end }, - ); - if (!gameReadStream) - throw createError({ - statusCode: 500, - statusMessage: "Failed to create read stream", - }); + const streams = await Promise.all( + streamFiles.map(async (file) => { + const gameReadStream = await libraryManager.readFile( + context.libraryId, + context.libraryPath, + context.versionName, + file.filename, + { start: file.start, end: file.end }, + ); + if (!gameReadStream) + throw createError({ + statusCode: 500, + statusMessage: "Failed to create read stream", + }); + return { ...file, stream: gameReadStream }; + }), + ); + + for (const file of streams) { let length = 0; - await gameReadStream.pipeTo( + await file.stream.pipeTo( new WritableStream({ write(chunk) { h3.node.res.write(chunk); diff --git a/server/middleware/latency.ts b/server/middleware/latency.ts index cfa25086..6ca9ef60 100644 --- a/server/middleware/latency.ts +++ b/server/middleware/latency.ts @@ -1,3 +1,3 @@ export default defineEventHandler(async () => { - // await new Promise((r) => setTimeout(r, 700)); + await new Promise((r) => setTimeout(r, 1400)); }); From 6335fd0c06cd9c022d8257f0eb7d35db3536c4ad Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 31 Aug 2025 14:34:10 +1000 Subject: [PATCH 2/4] fix: update drop-base --- drop-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drop-base b/drop-base index 4c42edf5..06bea063 160000 --- a/drop-base +++ b/drop-base @@ -1 +1 @@ -Subproject commit 4c42edf5adfa755c33bc8ce7bf1ddec87a0963a8 +Subproject commit 06bea063633ed4bf7513e29ad7149bc067561199 From d743cbd4d05f8513262262e5c04df293d5a40236 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 31 Aug 2025 14:45:40 +1000 Subject: [PATCH 3/4] fix: remove debug latency --- server/middleware/latency.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/middleware/latency.ts b/server/middleware/latency.ts index 6ca9ef60..14cf5f75 100644 --- a/server/middleware/latency.ts +++ b/server/middleware/latency.ts @@ -1,3 +1,3 @@ export default defineEventHandler(async () => { - await new Promise((r) => setTimeout(r, 1400)); + // await new Promise((r) => setTimeout(r, 1400)); }); From e7ca957cbca34b7f2e39d6cb969d07da0dc22120 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 31 Aug 2025 14:49:23 +1000 Subject: [PATCH 4/4] fix: lint --- nuxt.config.ts | 2 +- server/api/v2/client/chunk.post.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index 534f54af..e88def9a 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -85,7 +85,7 @@ export default defineNuxtConfig({ dest: "twemoji", }, ], - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any }) as any, ], }, diff --git a/server/api/v2/client/chunk.post.ts b/server/api/v2/client/chunk.post.ts index bb2d0229..648961bd 100644 --- a/server/api/v2/client/chunk.post.ts +++ b/server/api/v2/client/chunk.post.ts @@ -9,7 +9,10 @@ const GetChunk = type({ files: type({ filename: "string", chunkIndex: "number", - }).array().atLeastLength(1).atMostLength(256), + }) + .array() + .atLeastLength(1) + .atMostLength(256), }).configure(throwingArktype); export default defineEventHandler(async (h3) => {