|
3 | 3 | namespace App\Console\Commands; |
4 | 4 |
|
5 | 5 | use App\Jobs\UpdateUserInterestsJob; |
6 | | -use App\Models\Profile; |
| 6 | +use App\Models\User; |
| 7 | +use App\Services\FrontendService; |
7 | 8 | use Illuminate\Console\Command; |
| 9 | +use Illuminate\Support\Facades\Cache; |
8 | 10 |
|
9 | 11 | class UpdateFeedInterestsCommand extends Command |
10 | 12 | { |
11 | 13 | protected $signature = 'feed:update-interests |
12 | 14 | {--profile= : Specific profile ID to update} |
13 | | - {--active-days=7 : Only update profiles active in last N days}'; |
| 15 | + {--active-days=7 : Only update profiles active in last N days} |
| 16 | + {--cache-ttl=48 : Hours to cache completed updates (default 48)} |
| 17 | + {--force : Force update even if recently processed}'; |
14 | 18 |
|
15 | 19 | protected $description = 'Update user interests for personalized feed recommendations'; |
16 | 20 |
|
17 | 21 | public function handle(): int |
18 | 22 | { |
| 23 | + $force = $this->option('force'); |
| 24 | + $cacheTtl = (int) $this->option('cache-ttl') ?: 48; |
| 25 | + |
| 26 | + $config = FrontendService::getCache(); |
| 27 | + $enabled = data_get($config, 'fyf', false); |
| 28 | + |
| 29 | + if (! $enabled) { |
| 30 | + return 0; |
| 31 | + } |
| 32 | + |
19 | 33 | if ($profileId = $this->option('profile')) { |
20 | | - $this->info("Updating interests for profile {$profileId}..."); |
21 | | - UpdateUserInterestsJob::dispatch((int) $profileId); |
| 34 | + return $this->updateSingleProfile((int) $profileId, $force, $cacheTtl); |
| 35 | + } |
| 36 | + |
| 37 | + return $this->updateBulkProfiles($force, $cacheTtl); |
| 38 | + } |
| 39 | + |
| 40 | + protected function updateSingleProfile(int $profileId, bool $force, int $cacheTtl): int |
| 41 | + { |
| 42 | + $cacheKey = "user_interests_updated:{$profileId}"; |
| 43 | + |
| 44 | + if (! $force && Cache::has($cacheKey)) { |
| 45 | + $this->warn("Profile {$profileId} was recently updated. Use --force to override."); |
22 | 46 |
|
23 | 47 | return 0; |
24 | 48 | } |
25 | 49 |
|
| 50 | + $this->info("Updating interests for profile {$profileId}..."); |
| 51 | + UpdateUserInterestsJob::dispatch($profileId); |
| 52 | + Cache::put($cacheKey, now()->timestamp, now()->addHours($cacheTtl)); |
| 53 | + |
| 54 | + return 0; |
| 55 | + } |
| 56 | + |
| 57 | + protected function updateBulkProfiles(bool $force, int $cacheTtl): int |
| 58 | + { |
26 | 59 | $activeDays = (int) $this->option('active-days') ?: 7; |
27 | 60 |
|
28 | | - $profiles = Profile::whereHas('user', function ($query) use ($activeDays) { |
29 | | - $query->where('last_active_at', '>=', now()->subDays($activeDays)); |
30 | | - })->pluck('id'); |
| 61 | + $profiles = User::where('status', 1) |
| 62 | + ->where('last_active_at', '>=', now()->subDays($activeDays)) |
| 63 | + ->pluck('profile_id'); |
| 64 | + |
| 65 | + if ($profiles->isEmpty()) { |
| 66 | + $this->info('No active profiles found.'); |
| 67 | + |
| 68 | + return 0; |
| 69 | + } |
| 70 | + |
| 71 | + $this->info("Found {$profiles->count()} active profiles (last {$activeDays} days)..."); |
31 | 72 |
|
32 | | - $this->info("Queuing interest updates for {$profiles->count()} active profiles..."); |
| 73 | + $queued = 0; |
| 74 | + $skipped = 0; |
33 | 75 |
|
34 | 76 | $bar = $this->output->createProgressBar($profiles->count()); |
35 | 77 | $bar->start(); |
36 | 78 |
|
37 | 79 | foreach ($profiles as $profileId) { |
38 | | - UpdateUserInterestsJob::dispatch((int) $profileId); |
| 80 | + $cacheKey = "user_interests_updated:{$profileId}"; |
| 81 | + |
| 82 | + if (! $force && Cache::has($cacheKey)) { |
| 83 | + $skipped++; |
| 84 | + } else { |
| 85 | + UpdateUserInterestsJob::dispatch((int) $profileId); |
| 86 | + Cache::put($cacheKey, now()->timestamp, now()->addHours($cacheTtl)); |
| 87 | + $queued++; |
| 88 | + } |
| 89 | + |
39 | 90 | $bar->advance(); |
40 | 91 | } |
41 | 92 |
|
42 | 93 | $bar->finish(); |
43 | | - $this->newLine(); |
44 | | - $this->info('Done! Jobs queued for processing.'); |
| 94 | + $this->newLine(2); |
| 95 | + |
| 96 | + $this->info("✓ Queued: {$queued} profiles"); |
| 97 | + if ($skipped > 0) { |
| 98 | + $this->info("⊘ Skipped: {$skipped} profiles (recently updated)"); |
| 99 | + $this->comment(' Use --force to process all profiles regardless of cache'); |
| 100 | + } |
| 101 | + $this->info(" Cache TTL: {$cacheTtl} hours"); |
45 | 102 |
|
46 | 103 | return 0; |
47 | 104 | } |
|
0 commit comments