Route stats background mode through isolated daemon and defer in-app startup to live daemon (#58)

This commit is contained in:
2026-04-26 19:26:01 -07:00
committed by GitHub
parent d8934647a9
commit 53aa58d044
11 changed files with 333 additions and 20 deletions

View File

@@ -0,0 +1,86 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { createEnsureStatsServerUrlHandler } from './stats-server-routing';
function createHarness(options?: {
state?: { pid: number; port: number; startedAtMs: number } | null;
processAlive?: boolean;
localServerStarted?: boolean;
}) {
const calls: string[] = [];
let localServerStarted = options?.localServerStarted ?? false;
const handler = createEnsureStatsServerUrlHandler({
currentPid: 100,
readBackgroundState: () => {
calls.push('readBackgroundState');
return options?.state ?? null;
},
removeBackgroundState: () => {
calls.push('removeBackgroundState');
},
isProcessAlive: () => {
calls.push('isProcessAlive');
return options?.processAlive ?? true;
},
hasLocalStatsServer: () => localServerStarted,
startLocalStatsServer: () => {
calls.push('startLocalStatsServer');
localServerStarted = true;
},
getConfiguredPort: () => 6969,
});
return {
calls,
handler,
};
}
test('stats server routing defers to a live background daemon from another process', () => {
const { calls, handler } = createHarness({
state: { pid: 200, port: 7979, startedAtMs: 1 },
processAlive: true,
});
assert.deepEqual(handler(), { url: 'http://127.0.0.1:7979', source: 'foreign' });
assert.deepEqual(calls, ['readBackgroundState', 'isProcessAlive']);
});
test('stats server routing clears dead daemon state and starts local server', () => {
const { calls, handler } = createHarness({
state: { pid: 200, port: 7979, startedAtMs: 1 },
processAlive: false,
});
assert.deepEqual(handler(), { url: 'http://127.0.0.1:6969', source: 'local' });
assert.deepEqual(calls, [
'readBackgroundState',
'isProcessAlive',
'removeBackgroundState',
'startLocalStatsServer',
]);
});
test('stats server routing clears self-owned stale state and starts local server', () => {
const { calls, handler } = createHarness({
state: { pid: 100, port: 7979, startedAtMs: 1 },
processAlive: true,
});
assert.deepEqual(handler(), { url: 'http://127.0.0.1:6969', source: 'local' });
assert.deepEqual(calls, [
'readBackgroundState',
'removeBackgroundState',
'startLocalStatsServer',
]);
});
test('stats server routing reuses a started local stats server', () => {
const { calls, handler } = createHarness({
state: null,
localServerStarted: true,
});
assert.deepEqual(handler(), { url: 'http://127.0.0.1:6969', source: 'local' });
assert.deepEqual(calls, ['readBackgroundState', 'removeBackgroundState']);
});

View File

@@ -0,0 +1,41 @@
import type { BackgroundStatsServerState } from './stats-daemon';
type EnsureStatsServerUrlDeps = {
currentPid: number;
readBackgroundState: () => BackgroundStatsServerState | null;
removeBackgroundState: () => void;
isProcessAlive: (pid: number) => boolean;
hasLocalStatsServer: () => boolean;
startLocalStatsServer: () => void;
getConfiguredPort: () => number;
};
function formatStatsServerUrl(port: number): string {
return `http://127.0.0.1:${port}`;
}
export type EnsureStatsServerUrlResult =
| { url: string; source: 'foreign' }
| { url: string; source: 'local' };
export function createEnsureStatsServerUrlHandler(
deps: EnsureStatsServerUrlDeps,
): () => EnsureStatsServerUrlResult {
return () => {
const state = deps.readBackgroundState();
if (!state) {
deps.removeBackgroundState();
} else if (state.pid === deps.currentPid && !deps.hasLocalStatsServer()) {
deps.removeBackgroundState();
} else if (!deps.isProcessAlive(state.pid)) {
deps.removeBackgroundState();
} else if (state.pid !== deps.currentPid) {
return { url: formatStatsServerUrl(state.port), source: 'foreign' };
}
if (!deps.hasLocalStatsServer()) {
deps.startLocalStatsServer();
}
return { url: formatStatsServerUrl(deps.getConfiguredPort()), source: 'local' };
};
}