option('type'); $force = $this->option('force'); if (! in_array($type, ['daily', 'hourly'])) { $this->error("Invalid type '{$type}'. Must be 'daily' or 'hourly'."); return Command::FAILURE; } if ($type === 'daily') { return $this->backfillDaily($force); } else { return $this->backfillHourly($force); } } /** * Backfill daily stats */ protected function backfillDaily(bool $force): int { $days = (int) $this->option('days'); $this->info("Backfilling daily user activity stats for the last {$days} days..."); $progressBar = $this->output->createProgressBar($days); $statsCollected = 0; $statsSkipped = 0; for ($i = $days - 1; $i >= 0; $i--) { $date = Carbon::now()->subDays($i)->format('Y-m-d'); // Check if stats already exist for this date if (! $force && UserActivityStat::where('stat_date', $date)->exists()) { $statsSkipped++; $progressBar->advance(); continue; } UserActivityStat::collectDailyStats($date); $statsCollected++; $progressBar->advance(); } $progressBar->finish(); $this->newLine(2); $this->info('Daily backfill complete!'); $this->info("Stats collected: {$statsCollected}"); if ($statsSkipped > 0) { $this->info("Stats skipped (already existed): {$statsSkipped}"); } return Command::SUCCESS; } /** * Backfill hourly stats */ protected function backfillHourly(bool $force): int { $hours = (int) $this->option('hours'); $this->info("Backfilling hourly user activity stats for the last {$hours} hours..."); $progressBar = $this->output->createProgressBar($hours); $statsCollected = 0; $statsSkipped = 0; for ($i = $hours - 1; $i >= 0; $i--) { $hour = Carbon::now()->subHours($i)->startOfHour()->format('Y-m-d H:00:00'); // Check if stats already exist for this hour if (! $force && DB::table('user_activity_stats_hourly')->where('stat_hour', $hour)->exists()) { $statsSkipped++; $progressBar->advance(); continue; } UserActivityStat::collectHourlyStats($hour); $statsCollected++; $progressBar->advance(); } $progressBar->finish(); $this->newLine(2); $this->info('Hourly backfill complete!'); $this->info("Stats collected: {$statsCollected}"); if ($statsSkipped > 0) { $this->info("Stats skipped (already existed): {$statsSkipped}"); } return Command::SUCCESS; } }