56 lines
1.8 KiB
TypeScript
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());
|
|
}
|