44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import { dirname, join, resolve } from 'node:path'
|
|
import type { FastifyInstance } from 'fastify'
|
|
import { backupDatabase, resolveDatabasePath, type Sqlite } from '@authportal/db'
|
|
import type { AppConfig } from '../config.js'
|
|
|
|
export function backupDirFor(config: AppConfig, databaseUrl = config.databaseUrl) {
|
|
if (config.backupDir) return resolve(config.backupDir)
|
|
const path = resolveDatabasePath(databaseUrl)
|
|
return join(dirname(resolve(path)), 'backups')
|
|
}
|
|
|
|
export async function runBackup(
|
|
sqlite: Sqlite,
|
|
config: AppConfig,
|
|
databaseUrl = config.databaseUrl,
|
|
) {
|
|
return backupDatabase(sqlite, {
|
|
dir: backupDirFor(config, databaseUrl),
|
|
keep: config.backupKeep,
|
|
})
|
|
}
|
|
|
|
/** Периодический бэкап; выключен при BACKUP_INTERVAL_HOURS=0. */
|
|
export function startBackupJob(app: FastifyInstance): () => void {
|
|
const hours = app.config.backupIntervalHours
|
|
if (hours <= 0 || app.sqlite.memory) return () => {}
|
|
let running = false
|
|
const run = async () => {
|
|
if (running) return
|
|
running = true
|
|
try {
|
|
const res = await runBackup(app.sqlite, app.config)
|
|
app.log.info({ file: res.file, removed: res.removed.length }, 'db backup')
|
|
} catch (err) {
|
|
app.log.error({ err }, 'db backup failed')
|
|
} finally {
|
|
running = false
|
|
}
|
|
}
|
|
const interval = setInterval(() => void run(), hours * 60 * 60 * 1000)
|
|
interval.unref()
|
|
return () => clearInterval(interval)
|
|
}
|