Read chat logs incrementally and drain retention (Refs #62)
This commit is contained in:
@@ -39,6 +39,37 @@ async function setup() {
|
||||
}
|
||||
|
||||
describe('routine host observation retention', () => {
|
||||
it('drains more than one batch while yielding and preserving recent or failed operations', async () => {
|
||||
const api = await setup();
|
||||
const { drainRetention } = await import('../../src/lib/server/retention.js');
|
||||
const retained = [api.add('logs.read', { age: 0 }), api.add('logs.read', { state: 'failed' }), api.add('instance.restart')];
|
||||
api.handle.transaction(() => {
|
||||
const insert = api.handle.prepare(`INSERT INTO ec_host_operations
|
||||
(id,host_id,kind,payload,state,created_at,updated_at,observation_success)
|
||||
VALUES(?,?,'logs.read','{}','completed',?,?,1)`);
|
||||
for (let i = 0; i < 1501; i++) insert.run(`read-${i}`, api.host.id, at(2 * day), at(2 * day));
|
||||
})();
|
||||
let yielded = false;
|
||||
setImmediate(() => { yielded = true; });
|
||||
expect(await drainRetention()).toBe(1501);
|
||||
expect(yielded).toBe(true);
|
||||
expect((api.handle.prepare('SELECT id FROM ec_host_operations').all() as { id: string }[]).map(row => row.id).sort()).toEqual(retained.sort());
|
||||
expect(await drainRetention()).toBe(0);
|
||||
});
|
||||
|
||||
it('strips existing log bodies in batches without deleting recent or protected history', async () => {
|
||||
const api = await setup();
|
||||
const { drainRetention, setRetentionControl } = await import('../../src/lib/server/retention.js');
|
||||
const ids = Array.from({ length: 53 }, () => api.add('logs.read', { age: 0 }));
|
||||
setRetentionControl({ category: 'observation', id: ids[0], protected: true });
|
||||
api.handle.prepare("UPDATE ec_host_operations SET result=? WHERE kind='logs.read'")
|
||||
.run(JSON.stringify({ lines: ['legacy log contents'], size: 20, truncated: false }));
|
||||
expect(await drainRetention()).toBe(0);
|
||||
for (const id of ids) expect(api.getHostOperation(id)?.result).toEqual({ retained: false, lineCount: 1, size: 20, truncated: false });
|
||||
expect(api.handle.prepare("SELECT value FROM settings WHERE key='log_history_metadata_v1'").get()).toEqual({ value: '1' });
|
||||
expect(api.handle.pragma('foreign_key_check')).toEqual([]);
|
||||
});
|
||||
|
||||
it('removes aged successful reads, manifests, and read-only RCON while retaining failures, actions, and recent evidence', async () => {
|
||||
const api = await setup();
|
||||
const removed = ['host.inspect', 'instance.inspect', 'files.read', 'files.stat', 'files.list', 'files.manifest', 'logs.read']
|
||||
|
||||
Reference in New Issue
Block a user