*/ protected $commands = [ ImportLegacyUsers::class, \App\Console\Commands\EnforceUsernamePolicy::class, ImportCategories::class, MigrateFeaturedWorks::class, \App\Console\Commands\AvatarsMigrate::class, \App\Console\Commands\ResetAllUserPasswords::class, CleanupUploadsCommand::class, BackfillArtworkEmbeddingsCommand::class, AggregateSimilarArtworkAnalyticsCommand::class, AggregateFeedAnalyticsCommand::class, EvaluateFeedWeightsCommand::class, CompareFeedAbCommand::class, AiTagArtworksCommand::class, \App\Console\Commands\MigrateFollows::class, RecalculateTrendingCommand::class, RecalculateRankingsCommand::class, ]; /** * Define the application's command schedule. */ protected function schedule(\Illuminate\Console\Scheduling\Schedule $schedule): void { $schedule->command('uploads:cleanup')->dailyAt('03:00'); $schedule->command('analytics:aggregate-similar-artworks')->dailyAt('03:10'); $schedule->command('analytics:aggregate-feed')->dailyAt('03:20'); // Recalculate trending scores every 30 minutes (staggered to reduce peak load) $schedule->command('skinbase:recalculate-trending --period=24h')->everyThirtyMinutes(); $schedule->command('skinbase:recalculate-trending --period=7d --skip-index')->everyThirtyMinutes()->runInBackground(); // ── Ranking system (rank_v1) ──────────────────────────────────────── // Step 1: compute per-artwork scores every hour at :05 $schedule->job(new RankComputeArtworkScoresJob)->hourlyAt(5)->runInBackground(); // Step 2: build ranked lists every hour at :15 (after scores are ready) $schedule->job(new RankBuildListsJob)->hourlyAt(15)->runInBackground(); // ── Ranking Engine V2 — runs every 30 min ────────────────────────── $schedule->command('nova:recalculate-rankings --sync-rank-scores') ->everyThirtyMinutes() ->name('ranking-v2') ->withoutOverlapping() ->runInBackground(); } /** * Register the commands for the application. */ protected function commands(): void { $this->load(__DIR__ . '/Commands'); require base_path('routes/console.php'); } }