Restrict plugin lookups and reuse cached chat reads (Refs #98)

This commit is contained in:
2026-10-17 10:31:13 -04:00
parent b9bc897d6e
commit f3b9699317
8 changed files with 311 additions and 10 deletions
+23
View File
@@ -16,6 +16,7 @@ const at = (seconds: number) => new Date(baseline + seconds * 1000).toISOString(
beforeEach(async () => {
vi.resetModules();
vi.useFakeTimers({ toFake: ['Date'] });
baseline = Math.floor(Date.now() / 1000) * 1000 - 600_000;
fixture = await newFixture([SERVER, T6_SERVER]);
const { seedServerRegistry } = await import('../../src/lib/server/fleet/servers.js');
@@ -26,6 +27,7 @@ beforeEach(async () => {
afterEach(async () => {
vi.restoreAllMocks();
vi.useRealTimers();
await fixture.cleanup();
});
@@ -70,6 +72,10 @@ async function get(server = SERVER) {
return GET({ params: { name: server } });
}
function advanceTime(milliseconds = 15_000) {
vi.setSystemTime(Date.now() + milliseconds);
}
describe('server chat API', () => {
it('buffers partial UTF-8 lines and avoids context queries when the log is unchanged', async () => {
await report('game_start', 0);
@@ -78,6 +84,7 @@ describe('server chat API', () => {
expect((await (await get()).json()).entries).toHaveLength(1);
const { db } = await import('../../src/lib/server/db/index.js');
const prepare = vi.spyOn(db(), 'prepare');
advanceTime();
await get();
expect(prepare.mock.calls.some(([sql]) => sql.includes('FROM telemetry_requests'))).toBe(
false
@@ -90,9 +97,11 @@ describe('server chat API', () => {
const line = Buffer.from('61:00 say;abc;0;Player;café\n');
await appendFile(path, line.subarray(0, -2)); // Split inside é, before the newline.
await utimes(path, new Date(at(60)), new Date(at(60)));
advanceTime();
expect((await (await get()).json()).entries).toHaveLength(1);
await appendFile(path, line.subarray(-2));
await utimes(path, new Date(at(60)), new Date(at(60)));
advanceTime();
const body = await (await get()).json();
expect(body.entries.map((entry: ChatMessageEntry) => entry.message.message)).toEqual([
'first',
@@ -110,6 +119,7 @@ describe('server chat API', () => {
const path = join(fixture.t5, SERVER, 'logs/games_sp.log');
await appendFile(path, '61:00 say;abc;0;Player;retry me\n');
await utimes(path, new Date(at(60)), new Date(at(60)));
advanceTime();
const { db } = await import('../../src/lib/server/db/index.js');
const handle = db(),
original = handle.prepare.bind(handle);
@@ -121,6 +131,7 @@ describe('server chat API', () => {
vi.spyOn(console, 'error').mockImplementation(() => {});
expect((await get()).status).toBe(500);
prepare.mockRestore();
advanceTime();
expect(
(await (await get()).json()).entries.map(
(entry: ChatMessageEntry) => entry.message.message
@@ -142,9 +153,14 @@ describe('server chat API', () => {
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(1);
db().prepare('UPDATE servers SET last_players=0 WHERE name=?').run(SERVER);
await log(['60:50 say;abc;0;Player;playing', '61:00 say;abc;0;Player;goodbye']);
expect((await (await get()).json()).entries).toHaveLength(1);
expect(read).toHaveBeenCalledTimes(1);
await collectFleetChat();
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(2);
expect((await (await get()).json()).entries).toHaveLength(2);
expect(read).toHaveBeenCalledTimes(2);
db()
.prepare("UPDATE servers SET last_players=1,container_state='stopped' WHERE name=?")
.run(SERVER);
@@ -280,6 +296,8 @@ describe('server chat API', () => {
});
it('clears at a new match before it writes to the log and keeps the old chat with its match', async () => {
const logs = await import('../../src/lib/server/fleet/logs.js');
const read = vi.spyOn(logs, 'readLogChunk');
await report('game_start', 0);
await report('round_change', 20, 4);
await log(['60:30 say;abc;0;Player;old match'], 30);
@@ -287,8 +305,10 @@ describe('server chat API', () => {
await report('game_end', 60, 4);
await report('game_start', 80);
expect((await (await get()).json()).entries).toEqual([]);
expect(read).toHaveBeenCalledTimes(1);
await report('heartbeat', 90, 2);
await log(['60:30 say;abc;0;Player;old match', '61:40 say;abc;0;Player;new match'], 100);
advanceTime();
const body = await (await get()).json();
expect(body.entries.map((entry: ChatMessageEntry) => entry.message.message)).toEqual([
'new match'
@@ -311,8 +331,10 @@ describe('server chat API', () => {
await report('game_start', 0);
await report('heartbeat', 20, 4);
await log(['60:30 say;abc;0;Player;old match'], 30);
advanceTime();
expect((await (await get()).json()).entries).toHaveLength(1);
await log(['60:30 say;abc;0;Player;old match', boundary], 60);
advanceTime();
expect((await (await get()).json()).entries, boundary).toEqual([]);
}
});
@@ -333,6 +355,7 @@ describe('server chat API', () => {
.map((entry: ChatMessageEntry) => entry.message.message)
).toEqual(['new match']);
await log(['80:00 say;abc;0;Player;old match', '0:00 InitGame:'], 60);
advanceTime();
expect(
(await (await get()).json()).entries.some(
(entry: ContextualChatEntry) => entry.type === 'message'