mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
perf(api): bound worker pools and add telemetry
Share one configured PostgreSQL pool across worker repositories and make API and worker connection budgets explicit. Add privacy-safe aggregate request, query, pool, sync, and outbox telemetry, a loopback-only representative load fixture, bounded worker shutdown, and focused regression and integration coverage. Document the database-wide budget formula and defer pg_stat_statements activation to a reviewed migration and planned restart.
This commit is contained in:
1 parent
a13bbc3f65
commit
5c973c4ac5
25 files changed
+471
-16
No files matched your search
@@ -0,0 +1,30 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { WorkerLifecycle } from '../src/workers/lifecycle.js';
|
||||
|
||||
function deferred<T>() { let resolve!: (value: T) => void; const promise = new Promise<T>((next) => { resolve = next; }); return { promise, resolve }; }
|
||||
|
||||
describe('WorkerLifecycle', () => {
|
||||
it('reuses one shutdown promise, awaits the active tick, and closes once', async () => {
|
||||
const tick = deferred<void>(); const closePool = vi.fn(async () => undefined);
|
||||
const lifecycle = new WorkerLifecycle({ pollIntervalMs: 60_000, runTick: () => tick.promise, closePool, onTickFailure: vi.fn(), graceMs: 50 });
|
||||
lifecycle.start(); const first = lifecycle.shutdown(); const second = lifecycle.shutdown();
|
||||
expect(second).toBe(first); expect(closePool).not.toHaveBeenCalled();
|
||||
tick.resolve(); await expect(first).resolves.toBe(0); expect(closePool).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns nonzero when an active tick exceeds the one total deadline', async () => {
|
||||
vi.useFakeTimers();
|
||||
const lifecycle = new WorkerLifecycle({ pollIntervalMs: 60_000, runTick: () => new Promise<void>(() => undefined), closePool: vi.fn(async () => undefined), onTickFailure: vi.fn(), graceMs: 10 });
|
||||
lifecycle.start(); const shutdown = lifecycle.shutdown(); await vi.advanceTimersByTimeAsync(10);
|
||||
await expect(shutdown).resolves.toBe(1); vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('returns nonzero and closes once when pool shutdown rejects or hangs', async () => {
|
||||
const rejected = new WorkerLifecycle({ pollIntervalMs: 60_000, runTick: async () => undefined, closePool: vi.fn(async () => { throw new Error('close failed'); }), onTickFailure: vi.fn(), graceMs: 50 });
|
||||
rejected.start(); await expect(rejected.shutdown()).resolves.toBe(1);
|
||||
vi.useFakeTimers(); const closePool = vi.fn(() => new Promise<void>(() => undefined));
|
||||
const hung = new WorkerLifecycle({ pollIntervalMs: 60_000, runTick: async () => undefined, closePool, onTickFailure: vi.fn(), graceMs: 10 });
|
||||
hung.start(); const shutdown = hung.shutdown(); await vi.advanceTimersByTimeAsync(10);
|
||||
await expect(shutdown).resolves.toBe(1); expect(closePool).toHaveBeenCalledTimes(1); vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user