Preallocate download streams (#229)

* feat: pre-allocate streams for high-latency downloads

* fix: update drop-base

* fix: remove debug latency

* fix: lint
This commit is contained in:
DecDuck
2025-08-31 14:50:56 +10:00
committed by GitHub
parent aa1de921ee
commit a520d52ad3
4 changed files with 30 additions and 19 deletions

View File

@ -74,7 +74,8 @@ export default defineNuxtConfig({
vite: { vite: {
plugins: [ plugins: [
tailwindcss(), // eslint-disable-next-line @typescript-eslint/no-explicit-any
tailwindcss() as any,
// only used in dev server, not build because nitro sucks // only used in dev server, not build because nitro sucks
// see build hook below // see build hook below
viteStaticCopy({ viteStaticCopy({
@ -84,7 +85,8 @@ export default defineNuxtConfig({
dest: "twemoji", dest: "twemoji",
}, },
], ],
}), // eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
], ],
}, },

View File

@ -9,7 +9,10 @@ const GetChunk = type({
files: type({ files: type({
filename: "string", filename: "string",
chunkIndex: "number", chunkIndex: "number",
}).array(), })
.array()
.atLeastLength(1)
.atMostLength(256),
}).configure(throwingArktype); }).configure(throwingArktype);
export default defineEventHandler(async (h3) => { export default defineEventHandler(async (h3) => {
@ -46,21 +49,27 @@ export default defineEventHandler(async (h3) => {
streamFiles.map((e) => e.end - e.start).join(","), streamFiles.map((e) => e.end - e.start).join(","),
); // Non-standard header, but we're cool like that 😎 ); // Non-standard header, but we're cool like that 😎
for (const file of streamFiles) { const streams = await Promise.all(
const gameReadStream = await libraryManager.readFile( streamFiles.map(async (file) => {
context.libraryId, const gameReadStream = await libraryManager.readFile(
context.libraryPath, context.libraryId,
context.versionName, context.libraryPath,
file.filename, context.versionName,
{ start: file.start, end: file.end }, file.filename,
); { start: file.start, end: file.end },
if (!gameReadStream) );
throw createError({ if (!gameReadStream)
statusCode: 500, throw createError({
statusMessage: "Failed to create read stream", statusCode: 500,
}); statusMessage: "Failed to create read stream",
});
return { ...file, stream: gameReadStream };
}),
);
for (const file of streams) {
let length = 0; let length = 0;
await gameReadStream.pipeTo( await file.stream.pipeTo(
new WritableStream({ new WritableStream({
write(chunk) { write(chunk) {
h3.node.res.write(chunk); h3.node.res.write(chunk);

View File

@ -1,3 +1,3 @@
export default defineEventHandler(async () => { export default defineEventHandler(async () => {
// await new Promise((r) => setTimeout(r, 700)); // await new Promise((r) => setTimeout(r, 1400));
}); });