aps-agent/scripts/storage.test.mjs

75 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

/**
* 落库用例(任务 A3.7):会话、消息与幂等键要在进程重启后仍然可查。
*
* 用同一个 SQLite 文件起两次服务,模拟「平台重启」。
*/
import assert from 'node:assert/strict';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { test } from 'node:test';
async function startWithDatabase(dbPath) {
const { startServer } = await import('../server/dist/index.js');
return startServer({ host: '127.0.0.1', port: 0, version: 'test', databasePath: dbPath, engine: 'fake' });
}
const postJson = (base, path, body) =>
fetch(`${base}${path}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
test('会话、消息与幂等键在重启后可查', async () => {
const dir = await mkdtemp(join(tmpdir(), 'aps-storage-'));
const dbPath = join(dir, 'aps.sqlite');
try {
let sessionId = '';
let firstRunId = '';
{
const server = await startWithDatabase(dbPath);
try {
const created = await (await postJson(server.url, '/v1/sessions', { scope: 'project', projectId: 'p-default', title: '持久化用例' })).json();
sessionId = created.session.sessionId;
const accepted = await (
await postJson(server.url, `/v1/sessions/${sessionId}/messages`, { text: '试排一版看看', idempotencyKey: 'idem-storage-0001' })
).json();
firstRunId = accepted.runId;
await new Promise((resolve) => setTimeout(resolve, 300));
} finally {
await server.close();
}
}
// 重启:同一个库文件,新的服务实例
{
const server = await startWithDatabase(dbPath);
try {
const sessions = await (await fetch(`${server.url}/v1/sessions`)).json();
assert.equal(sessions.sessions.length, 1, '重启后应还能列出会话');
assert.equal(sessions.sessions[0].sessionId, sessionId);
assert.equal(sessions.sessions[0].title, '持久化用例');
const detail = await (await fetch(`${server.url}/v1/sessions/${sessionId}`)).json();
assert.ok(detail.messages.length >= 2, `重启后应还能读到消息,实际 ${detail.messages.length} 条`);
assert.equal(detail.messages[0].role, 'user');
assert.equal(detail.messages.at(-1).role, 'assistant');
// 幂等键也持久化了:同一 key 重试仍返回同一个 run
const retry = await (
await postJson(server.url, `/v1/sessions/${sessionId}/messages`, { text: '试排一版看看', idempotencyKey: 'idem-storage-0001' })
).json();
assert.equal(retry.runId, firstRunId, '重启后重试应命中同一条受理记录');
} finally {
await server.close();
}
}
} finally {
await rm(dir, { recursive: true, force: true });
}
});
test('默认数据库路径来自配置(~/.aps/aps.sqlite)', async () => {
const { loadConfig } = await import('@aps/server/config');
const config = loadConfig({ env: {}, homeDir: 'C:/Users/example' });
assert.equal(config.database.path.replace(/\\/g, '/'), 'C:/Users/example/.aps/aps.sqlite');
});