51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { and, eq, lt } from 'drizzle-orm';
|
|
|
|
import { db } from '../db/client';
|
|
import { recordings } from '../db/schema';
|
|
import { hasRequiredTables } from '../utils/db-schema';
|
|
|
|
const STALE_RECORDING_SECONDS = Number(process.env.RECORDING_STALE_SECONDS ?? 60 * 30);
|
|
|
|
export const startRecordingsWorker = (): void => {
|
|
const intervalMs = Number(process.env.RECORDING_WORKER_INTERVAL_MS ?? 30_000);
|
|
const requiredTables = ['recordings'];
|
|
|
|
void (async () => {
|
|
const ready = await hasRequiredTables(requiredTables);
|
|
if (!ready) {
|
|
console.warn(
|
|
`[recordings worker] skipped startup because required tables are missing (${requiredTables.join(', ')}). Run migrations and restart.`,
|
|
);
|
|
return;
|
|
}
|
|
|
|
setInterval(() => {
|
|
reconcileStaleRecordings().catch((error) => {
|
|
console.error('recordings worker failed', error);
|
|
});
|
|
}, intervalMs);
|
|
})().catch((error) => {
|
|
console.error('recordings worker failed to initialize', error);
|
|
});
|
|
};
|
|
|
|
const reconcileStaleRecordings = async (): Promise<void> => {
|
|
const staleBefore = new Date(Date.now() - STALE_RECORDING_SECONDS * 1000);
|
|
|
|
const stale = await db.query.recordings.findMany({
|
|
where: and(eq(recordings.status, 'awaiting_upload'), lt(recordings.createdAt, staleBefore)),
|
|
limit: 100,
|
|
});
|
|
|
|
for (const recording of stale) {
|
|
await db
|
|
.update(recordings)
|
|
.set({
|
|
status: 'failed',
|
|
error: 'recording upload timeout',
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(eq(recordings.id, recording.id));
|
|
}
|
|
};
|