Keep native collection launches responsive

This commit is contained in:
2026-10-05 10:48:38 -04:00
parent dbd2940d29
commit 1405114a14
26 changed files with 998 additions and 123 deletions
@@ -0,0 +1,38 @@
import { parentPort } from 'node:worker_threads';
import { posix } from 'node:path';
import { db } from '../db/index.js';
import { relDestForKind } from '../config.js';
import { captureRecipe, summarizeRecipe } from '../fleet/launch-recipes.js';
import { sha256Buffer } from '../fleet/files.js';
import type { NativeLaunchInput } from './launch-preparation.js';
parentPort!.on('message', ({ id, input }: { id: number; input: NativeLaunchInput }) => {
try {
// All file versions and composed configuration belong to one snapshot.
const recipe = db().transaction(() => ({ ...captureRecipe(input.game, input.mapSlug),
native: input.native, image: input.instance.image }))();
const instance = input.instance;
const payload = {
name: instance.server, game: recipe.game, libraryId: instance.library_id, image: instance.image,
port: instance.port, bindAddress: instance.bind_address, rconPassword: input.rconPassword,
env: { PLUTAINER_SERVER_NAME: instance.server, PLUTAINER_PORT: String(instance.port),
PLUTAINER_GAME: recipe.game === 't6' ? 't6zm' : 't5sp', PLUTAINER_CONFIG_FILE: recipe.configFile,
PLUTAINER_MAP_ROTATE: 'false',
PLUTAINER_EXTRA_ARGS: `+exec electric_cherry_map.cfg +set tws_server_id ${instance.server} +map_rotate`,
PLUTO_SERVER_KEY: input.serverKey },
files: recipe.files.map(file => ({ path: posix.join(relDestForKind(file.kind, recipe.game), file.path),
contentBase64: file.content, sha256: file.sha256 })),
...(input.rebuild ? { nextGeneration: instance.generation + 1 } : {})
};
const encode = (value: unknown) => new TextEncoder().encode(JSON.stringify(value));
const recipeJson = encode(recipe);
const payloadJson = encode(payload);
const plan = { ...recipe, files: recipe.files.map(({ content: _content, ...file }) => file) };
const recipeSummary = JSON.stringify(summarizeRecipe(plan, sha256Buffer(Buffer.from(recipeJson.buffer))));
// Transfer ownership of the encoded bytes; do not clone giant strings or objects.
parentPort!.postMessage({ id, value: { recipe: plan, recipeSummary, recipeJson, payloadJson } },
[recipeJson.buffer, payloadJson.buffer]);
} catch (error) {
parentPort!.postMessage({ id, error: error instanceof Error ? error.message : 'Launch preparation failed.' });
}
});