backend/src/utils/glacierPoller.ts

75 lines
2.4 KiB
TypeScript
Raw Normal View History

import * as fs from 'node:fs'
import { db } from '@/utils/database'
import redis from '@/utils/redis'
import { uploadVideo } from '@/utils/upload'
import { checkRestoreStatus, downloadRestoredObjectToFile } from '@/utils/glacier'
import { sendRestoreCompleteEmail } from '@/utils/mail'
const POLL_INTERVAL_MS = 10 * 60000
async function processRestoringRow(row: { uuid: string, videoId: string, requester_email: string }) {
const { ongoing, expiry } = await checkRestoreStatus(row.videoId)
if (ongoing) return
await db.updateTable('restore_requests')
.set({ status: 'reuploading', aws_restore_expiry: expiry, updated_at: new Date() })
.where('uuid', '=', row.uuid)
.execute()
const filePath = `./videos/${row.videoId}.mp4`
try {
await downloadRestoredObjectToFile(row.videoId, filePath)
const videoUrl = await uploadVideo(filePath)
await db.updateTable('videos')
.set({ deletion_stage: null, source: videoUrl })
.where('id', '=', row.videoId)
.execute()
await redis.del(`watch:${row.videoId}:html`)
await redis.del('deletion:html')
await db.updateTable('restore_requests')
.set({ status: 'reuploaded', updated_at: new Date() })
.where('uuid', '=', row.uuid)
.execute()
const video = await db.selectFrom('videos')
.select(['title'])
.where('id', '=', row.videoId)
.executeTakeFirst()
await sendRestoreCompleteEmail(row.requester_email, row.videoId, video?.title)
} finally {
if (fs.existsSync(filePath)) fs.unlinkSync(filePath)
}
}
async function pollRestores() {
const restoringRows = await db.selectFrom('restore_requests')
.select(['uuid', 'videoId', 'requester_email'])
.where('status', '=', 'restoring')
.execute()
for (const row of restoringRows) {
try {
await processRestoringRow(row)
} catch (error: unknown) {
const err = error as Error
console.log(`[glacier-poller] failed to process restore ${row.uuid} (${row.videoId}): ${err.message}`)
await db.updateTable('restore_requests')
.set({ status: 'failed', error_message: err.message, updated_at: new Date() })
.where('uuid', '=', row.uuid)
.execute()
}
}
}
function startRestorePoller() {
pollRestores()
setInterval(pollRestores, POLL_INTERVAL_MS).unref()
console.log('glacier restore poller started (this server is primary)')
}
export { startRestorePoller, pollRestores }