mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Share bounded database pools across API repositories, consolidate sync and chat queries, and make mobile refreshes cache-aware and foreground-aware. Add focused regression coverage, client freshness documentation, and repository agent role configuration.
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import { Pool } from 'pg';
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import {
|
|
DEFAULT_POOL_MAX,
|
|
closeResolvedPool,
|
|
createDatabasePool,
|
|
resolvePool,
|
|
} from '../src/db/pool.js';
|
|
|
|
const url = 'postgres://user:pass@127.0.0.1:5432/sauci_test';
|
|
|
|
afterEach(() => vi.restoreAllMocks());
|
|
|
|
describe('database pool', () => {
|
|
it('bounds the shared pool and only forwards timeouts that were configured', () => {
|
|
// A process-wide pool is the whole point of the change: an unbounded default
|
|
// multiplied by one pool per repository is what the self-hosted database had
|
|
// to absorb before.
|
|
const bounded = createDatabasePool(url, { max: 4, idleTimeoutMillis: 1_000, connectionTimeoutMillis: 2_000 });
|
|
expect(bounded.options.max).toBe(4);
|
|
expect(bounded.options.idleTimeoutMillis).toBe(1_000);
|
|
expect(bounded.options.connectionTimeoutMillis).toBe(2_000);
|
|
|
|
const defaults = createDatabasePool(url);
|
|
expect(defaults.options.max).toBe(DEFAULT_POOL_MAX);
|
|
|
|
return Promise.all([bounded.end(), defaults.end()]);
|
|
});
|
|
|
|
it('owns a pool it built from a URL and never ends one it was handed', async () => {
|
|
// Repositories in the API process share one pool, so closing any single
|
|
// repository must not take the connections out from under the others. Tests
|
|
// still construct from a URL and must be able to close what they created.
|
|
const owned = resolvePool(url);
|
|
expect(owned.owned).toBe(true);
|
|
const ownedEnd = vi.spyOn(owned.pool, 'end');
|
|
await closeResolvedPool(owned.pool, owned.owned);
|
|
expect(ownedEnd).toHaveBeenCalledTimes(1);
|
|
|
|
const shared = new Pool({ connectionString: url });
|
|
const borrowed = resolvePool(shared);
|
|
expect(borrowed.owned).toBe(false);
|
|
expect(borrowed.pool).toBe(shared);
|
|
const sharedEnd = vi.spyOn(shared, 'end');
|
|
await closeResolvedPool(borrowed.pool, borrowed.owned);
|
|
expect(sharedEnd).not.toHaveBeenCalled();
|
|
await shared.end();
|
|
});
|
|
});
|