Files
qinglong/packages/ql3-local-sqlite/test/taskRunOutcomeWindowReader.test.cjs

126 lines
3.4 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { DatabaseSync } = require('node:sqlite');
const { test } = require('node:test');
const {
migrateLocalSqlitePath,
openLocalSqliteRuntimeDatabase,
} = require('../dist');
const {
openLocalSqliteMcpReadDatabase,
} = require('@qinglong/local-sqlite/mcp-read-database');
const {
LocalSqliteTaskRunOutcomeWindowReader,
} = require('@qinglong/local-sqlite/task-run-outcome-window');
function run(id, projectId, taskId, status, createdAtMs) {
return {
id,
projectId,
taskId,
taskRevision: 'revision-1',
taskName: id,
triggerType: 'manual',
executionOrigin: 'manual',
executionOwner: 'runtime',
triggeredBy: 'test',
status,
version: 0,
eventSequence: 0,
priority: 0,
createdAtMs,
};
}
test('reads one fixed Project Task outcome window through the existing indexed SQLite authority', async (t) => {
assert.equal(typeof LocalSqliteTaskRunOutcomeWindowReader, 'function');
assert.equal(
require('@qinglong/local-sqlite').LocalSqliteTaskRunOutcomeWindowReader,
undefined,
);
const directory = fs.mkdtempSync(
path.join(os.tmpdir(), 'ql3-outcome-window-'),
);
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
const options = {
databasePath: path.join(directory, 'qinglong3.sqlite'),
profile: 'edge',
};
await migrateLocalSqlitePath(options);
const runtime = await openLocalSqliteRuntimeDatabase(options);
await runtime.runRepository.transaction(async (transaction) => {
for (const value of [
run('run-old-success', 'default', 'task-a', 'succeeded', 10),
run('run-failure', 'default', 'task-a', 'failed', 20),
run('run-running', 'default', 'task-a', 'running', 30),
run('run-other-task', 'default', 'task-b', 'failed', 40),
run('run-other-project', 'other', 'task-a', 'failed', 50),
]) {
await transaction.insertRun(value);
}
});
await runtime.close();
const database = await openLocalSqliteMcpReadDatabase(options);
t.after(() => database.close());
const rows = await database.runs.listRecentRunsByTask({
projectId: 'default',
taskId: 'task-a',
limit: 3,
});
assert.deepEqual(rows, [
{
id: 'run-running',
projectId: 'default',
taskId: 'task-a',
status: 'running',
createdAtMs: 30,
},
{
id: 'run-failure',
projectId: 'default',
taskId: 'task-a',
status: 'failed',
createdAtMs: 20,
},
{
id: 'run-old-success',
projectId: 'default',
taskId: 'task-a',
status: 'succeeded',
createdAtMs: 10,
},
]);
await assert.rejects(
database.runs.listRecentRunsByTask({
projectId: 'default',
taskId: 'task-a',
limit: 66,
}),
TypeError,
);
await database.close();
const client = new DatabaseSync(options.databasePath, { readOnly: true });
t.after(() => {
if (client.isOpen) client.close();
});
const plan = client
.prepare(
`EXPLAIN QUERY PLAN
SELECT "id", "project_id", "task_id", "status", "created_at_ms"
FROM "Runs"
WHERE "project_id" = ? AND "task_id" = ?
ORDER BY "created_at_ms" DESC, "id" DESC
LIMIT ?`,
)
.all('default', 'task-a', 65);
assert.match(
plan.map((entry) => entry.detail).join('\n'),
/ql3_local_runs_task_created_idx/u,
);
});