Moves BackupCommand and config/backup.php from the pre-audit WIP that got stashed on 2026-10-21 to master, and registers the command in the Laravel scheduler so it runs at 03:30 Asia/Bahrain nightly. The command handles sqlite (VACUUM INTO after a WAL checkpoint) and mysql (mysqldump | gzip, verified with gzip -t) backends; verifies every snapshot by re-opening it with PDO + PRAGMA integrity_check + a sanity SELECT; ships an off-server copy via Storage::disk() when BACKUP_DISK is set; and prunes artifacts older than BACKUP_RETAIN_DAYS while always keeping at least BACKUP_KEEP_MINIMUM. Scheduler entry mirrors the nas-auto-sync shape — withoutOverlapping + runInBackground so a slow upload doesn't block the next tick. .env knobs: BACKUP_PATH (default: data/backups) BACKUP_RETAIN_DAYS (default: 14) BACKUP_KEEP_MINIMUM (default: 3) BACKUP_DISK (unset — warns on every run until configured) BACKUP_MEDIA_DEST (unset — required when running with --media) BACKUP_MEDIA_DELETE (default: false) Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
79 lines
2.5 KiB
PHP
Executable File
79 lines
2.5 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Console;
|
|
|
|
use Illuminate\Console\Scheduling\Schedule;
|
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
|
|
|
class Kernel extends ConsoleKernel
|
|
{
|
|
/**
|
|
* Define the application's command schedule.
|
|
*/
|
|
protected function schedule(Schedule $schedule): void
|
|
{
|
|
$interval = $this->getCleanupInterval();
|
|
$schedule->command('cleanup:orphaned-videos --force')
|
|
->cron("*/{$interval} * * * *")
|
|
->withoutOverlapping()
|
|
->runInBackground();
|
|
|
|
// Evict NAS stream-cache files older than 24 hours
|
|
$schedule->call(function () {
|
|
$nas = app(\App\Services\NasSyncService::class);
|
|
if ($nas->isEnabled()) {
|
|
$nas->clearNasCache(24);
|
|
}
|
|
})->daily()->name('nas-cache-evict');
|
|
|
|
// Clean up stale temp files in public/tmp older than 1 hour
|
|
$schedule->call(function () {
|
|
$tmpDir = storage_path('app/public/tmp');
|
|
if (! is_dir($tmpDir)) return;
|
|
$cutoff = time() - 3600;
|
|
foreach (glob("{$tmpDir}/*") as $file) {
|
|
if (is_file($file) && filemtime($file) < $cutoff) @unlink($file);
|
|
}
|
|
})->hourly()->name('tmp-cleanup');
|
|
|
|
// Auto-sync local files to NAS when NAS comes back online.
|
|
// Runs every 10 minutes; exits immediately when NAS is unreachable.
|
|
$schedule->command('nas:auto-sync')
|
|
->everyTenMinutes()
|
|
->withoutOverlapping()
|
|
->runInBackground();
|
|
|
|
// Weekly activity digest — every Monday at 9:00 AM (Bahrain time)
|
|
$schedule->command('digest:weekly')
|
|
->weeklyOn(1, '09:00')
|
|
->withoutOverlapping()
|
|
->runInBackground();
|
|
|
|
// Nightly database backup at 03:30 Asia/Bahrain. Writes to
|
|
// data/backups/db-YYYYMMDD-HHMMSS.sqlite, verifies the snapshot,
|
|
// and (when BACKUP_DISK is set) ships a copy off-server.
|
|
$schedule->command('takeone:backup')
|
|
->dailyAt('03:30')
|
|
->withoutOverlapping()
|
|
->runInBackground();
|
|
}
|
|
|
|
/**
|
|
* Register the commands for the application.
|
|
*/
|
|
protected function commands(): void
|
|
{
|
|
$this->load(__DIR__.'/Commands');
|
|
|
|
require base_path('routes/console.php');
|
|
}
|
|
|
|
/**
|
|
* Get the interval in minutes for cleanup (from .env)
|
|
*/
|
|
protected function getCleanupInterval(): int
|
|
{
|
|
return (int) env('CLEANUP_INTERVAL_MINUTES', 30);
|
|
}
|
|
}
|