0.2.6-dev: a background content-hash index of public/assets and public/fonts (SHA-256, 16 hex; cached by path + size + mtime in .cache/asset-hashes.json; Spine models share one hash; SP_ASSET_INDEX=0 turns it off) — host bandwidth layer 1.1; golden: unchanged
This commit is contained in:
1 parent
fb5f4493f2
commit
521dd984e7
8 files changed
+524
-10
No files matched your search
+16
-4
@@ -9,6 +9,8 @@
|
||||
// the content packs (/packs/index.json, /packs/<id>/<file> — the registry is packs.js)
|
||||
// http/media.js /media/bgm/act1 → public/assets/audio/bgm/act1.mp3 (audio addressed without its extension)
|
||||
// http/files.js one file → response: MIME, gzip + memory cache, ETag / Last-Modified / 304, Cache-Control, ranges
|
||||
// http/assetIndex.js the content hashes of public/assets and public/fonts (built in the background, cached in
|
||||
// .cache/asset-hashes.json by path + size + mtime; Spine models share one hash)
|
||||
// http/buildTag.js the build tag of the served browser runtime (/healthz `build`, public/js/ui/buildGuard.js)
|
||||
// http/routes.js the request listener: security headers, 414 / 400 / 405, GET /healthz → JSON status, else static
|
||||
// http/traffic.js the traffic counters: bytes sent per category (assets / audio / code / data) and on the
|
||||
@@ -26,7 +28,7 @@
|
||||
|
||||
import http from 'node:http';
|
||||
import { getData, loadData } from './data.js';
|
||||
import { ROOT, listenAddress, bindCandidates, serveDirs, makeLogger, parseTrustProxy } from './http/config.js';
|
||||
import { ROOT, listenAddress, bindCandidates, serveDirs, makeLogger, parseTrustProxy, assetIndexOptionsFrom } from './http/config.js';
|
||||
import { WS_MAX_PAYLOAD, createSessionStack, attachWebSocket } from './http/websocket.js';
|
||||
import { DATA_SHIM_JS, createStaticHandler } from './http/static.js';
|
||||
import { createPackRegistry } from './packs.js';
|
||||
@@ -34,6 +36,7 @@ import { MIME, COMPRESSIBLE, acceptsGzip, parseRange } from './http/files.js';
|
||||
import { BUILD_INPUTS, computeBuildTag, buildTag, resetBuildTag } from './http/buildTag.js';
|
||||
import { createRequestHandler } from './http/routes.js';
|
||||
import { createTrafficCounter } from './http/traffic.js';
|
||||
import { createAssetIndex } from './http/assetIndex.js';
|
||||
import { answerClientError } from './http/common.js';
|
||||
import { lanUrls, displayHost, isProcessEntry, runMain } from './http/boot.js';
|
||||
|
||||
@@ -53,11 +56,14 @@ export {
|
||||
* ratePerSec?: number, rateBurst?: number, maxConnections?: number, maxRooms?: number,
|
||||
* maxConnectionsPerAddr?: number, maxRoomsPerAddr?: number, maxMatchesPerAddr?: number, resyncMinGapMs?: number,
|
||||
* heavyPerSec?: number, heavyBurst?: number, trustProxy?: 'auto' | boolean, soloReconnectWindowMs?: number,
|
||||
* assetIndex?: boolean | { cacheFile?: string | null, delayMs?: number },
|
||||
* }} [opts]
|
||||
* assetIndex: the content-hash index (default on; false or SP_ASSET_INDEX=0: off — config.js assetIndexOptionsFrom)
|
||||
* @returns {Promise<{ port: number, host: string, url: string, server: http.Server, wss: import('ws').WebSocketServer,
|
||||
* lobby: import('./lobby.js').Lobby, network: import('./net.js').Network,
|
||||
* registry: import('./net.js').SessionRegistry, packs: ReturnType<typeof createPackRegistry>,
|
||||
* traffic: ReturnType<typeof createTrafficCounter>, close: () => Promise<void> }>}
|
||||
* traffic: ReturnType<typeof createTrafficCounter>, assetIndex: ReturnType<typeof createAssetIndex> | null,
|
||||
* close: () => Promise<void> }>}
|
||||
*/
|
||||
export async function startServer(opts = {}) {
|
||||
const { port, host } = listenAddress(opts);
|
||||
@@ -70,6 +76,9 @@ export async function startServer(opts = {}) {
|
||||
// content packs (docs/PACKS.md): scanned now — the start log names them — and again whenever their folders change
|
||||
const packs = createPackRegistry({ publicDir, dataDir, packsDir }, { log });
|
||||
packs.refresh(true);
|
||||
// the content hashes of the art (built in the background once listening)
|
||||
const indexOptions = assetIndexOptionsFrom(opts, publicDir);
|
||||
const assetIndex = indexOptions ? createAssetIndex({ publicDir, log, ...indexOptions }) : null;
|
||||
const serveStatic = createStaticHandler({ publicDir, dataDir, sharedDir, packsDir, packs, log });
|
||||
const startedAt = Date.now();
|
||||
// The tag is per process (see buildTag): read the browser runtime once, here, not on every /healthz.
|
||||
@@ -77,7 +86,7 @@ export async function startServer(opts = {}) {
|
||||
buildTag();
|
||||
|
||||
const traffic = createTrafficCounter();
|
||||
const server = http.createServer(createRequestHandler({ serveStatic, health: { startedAt, network, registry, lobby, traffic }, log }));
|
||||
const server = http.createServer(createRequestHandler({ serveStatic, health: { startedAt, network, registry, lobby, traffic, assetIndex }, log }));
|
||||
server.on('clientError', answerClientError);
|
||||
const wss = attachWebSocket(server, { network, log, traffic });
|
||||
|
||||
@@ -112,9 +121,11 @@ export async function startServer(opts = {}) {
|
||||
boundHost = bound;
|
||||
} catch (e) {
|
||||
network.close(); // stop heartbeat/sweep timers of the half-built server
|
||||
assetIndex?.close();
|
||||
throw e;
|
||||
}
|
||||
server.on('error', (e) => log.error('[http] server error', e));
|
||||
assetIndex?.start();
|
||||
|
||||
const addr = server.address();
|
||||
const actualPort = typeof addr === 'object' && addr ? addr.port : port;
|
||||
@@ -126,6 +137,7 @@ export async function startServer(opts = {}) {
|
||||
closing = (async () => {
|
||||
try { lobby.shutdown('shutdown'); } catch (e) { log.error('[shutdown] lobby', e); }
|
||||
network.close();
|
||||
assetIndex?.close();
|
||||
await new Promise((resolve) => {
|
||||
server.close(() => resolve());
|
||||
server.closeIdleConnections?.();
|
||||
@@ -136,7 +148,7 @@ export async function startServer(opts = {}) {
|
||||
return closing;
|
||||
}
|
||||
|
||||
return { port: actualPort, host: boundHost, url, server, wss, lobby, network, registry, packs, traffic, close };
|
||||
return { port: actualPort, host: boundHost, url, server, wss, lobby, network, registry, packs, traffic, assetIndex, close };
|
||||
}
|
||||
|
||||
// `node server/index.js` / npm start: listen, print the banner, stop on SIGINT / SIGTERM (http/boot.js).
|
||||
|
||||
Reference in new issue
Block a user