Files
LWLT-AIBOT/control-plane/src/retention.ts

56 lines
1.8 KiB
TypeScript

import { loadConfig } from './config.js';
import { closePool, withTransaction } from './db.js';
import { writeEmergencyDiagnostic } from './diagnostics.js';
export async function runRetention(): Promise<{
archivedTasks: number;
deletedTasks: number;
deletedAuditEvents: number;
deletedSessions: number;
}> {
const config = loadConfig();
if (!config.DATA_RETENTION_ENABLED) {
return { archivedTasks: 0, deletedTasks: 0, deletedAuditEvents: 0, deletedSessions: 0 };
}
return withTransaction(config, async (client) => {
const archivedTasks = await client.query(
`UPDATE tasks
SET archived_at = now(), archived_by = NULL,
archive_reason = 'retention_policy', updated_at = now()
WHERE created_at < now() - ($1 * interval '1 day')
AND status IN ('completed', 'cancelled', 'parse_failed')
AND archived_at IS NULL`,
[config.DATA_RETENTION_DAYS]
);
const deletedSessions = await client.query(
`DELETE FROM sessions
WHERE (revoked_at IS NOT NULL AND revoked_at < now() - interval '30 days')
OR (expires_at IS NOT NULL AND expires_at < now() - interval '30 days')`,
[]
);
return {
archivedTasks: archivedTasks.rowCount || 0,
deletedTasks: 0,
deletedAuditEvents: 0,
deletedSessions: deletedSessions.rowCount || 0
};
});
}
if (process.argv[1]?.endsWith('/retention.ts') || process.argv[1]?.endsWith('/retention.js')) {
runRetention()
.then((result) => console.log(JSON.stringify({
ok: true,
diagnostic_event: 'retention.completed',
diagnostic_stage: 'data_retention',
...result
})))
.catch((error) => {
writeEmergencyDiagnostic('retention.failed', error, {
diagnostic_stage: 'data_retention'
});
process.exitCode = 1;
})
.finally(() => closePool());
}