feat(scheduling): add frequency filter option for manual execution of scheduled jobs

This commit is contained in:
Andras Bacsai 2025-07-11 15:10:43 +02:00
parent 25023ab813
commit 2214099c90

View file

@ -13,6 +13,7 @@ class RunScheduledJobsManually extends Command
{ {
protected $signature = 'schedule:run-manual protected $signature = 'schedule:run-manual
{--type=all : Type of jobs to run (all, backups, tasks)} {--type=all : Type of jobs to run (all, backups, tasks)}
{--frequency= : Filter by frequency (daily, hourly, weekly, monthly, yearly, or cron expression)}
{--chunk=5 : Number of jobs to process in each batch} {--chunk=5 : Number of jobs to process in each batch}
{--delay=30 : Delay in seconds between batches} {--delay=30 : Delay in seconds between batches}
{--max= : Maximum number of jobs to process (useful for testing)} {--max= : Maximum number of jobs to process (useful for testing)}
@ -23,37 +24,52 @@ class RunScheduledJobsManually extends Command
public function handle() public function handle()
{ {
$type = $this->option('type'); $type = $this->option('type');
$frequency = $this->option('frequency');
$chunkSize = (int) $this->option('chunk'); $chunkSize = (int) $this->option('chunk');
$delay = (int) $this->option('delay'); $delay = (int) $this->option('delay');
$maxJobs = $this->option('max') ? (int) $this->option('max') : null; $maxJobs = $this->option('max') ? (int) $this->option('max') : null;
$dryRun = $this->option('dry-run'); $dryRun = $this->option('dry-run');
$this->info('Starting manual execution of scheduled jobs...'.($dryRun ? ' (DRY RUN)' : '')); $this->info('Starting manual execution of scheduled jobs...'.($dryRun ? ' (DRY RUN)' : ''));
$this->info("Type: {$type}, Chunk size: {$chunkSize}, Delay: {$delay}s".($maxJobs ? ", Max jobs: {$maxJobs}" : '').($dryRun ? ', Dry run: enabled' : '')); $this->info("Type: {$type}".($frequency ? ", Frequency: {$frequency}" : '').", Chunk size: {$chunkSize}, Delay: {$delay}s".($maxJobs ? ", Max jobs: {$maxJobs}" : '').($dryRun ? ', Dry run: enabled' : ''));
if ($dryRun) { if ($dryRun) {
$this->warn('DRY RUN MODE: No jobs will actually be dispatched'); $this->warn('DRY RUN MODE: No jobs will actually be dispatched');
} }
if ($type === 'all' || $type === 'backups') { if ($type === 'all' || $type === 'backups') {
$this->runScheduledBackups($chunkSize, $delay, $maxJobs, $dryRun); $this->runScheduledBackups($chunkSize, $delay, $maxJobs, $dryRun, $frequency);
} }
if ($type === 'all' || $type === 'tasks') { if ($type === 'all' || $type === 'tasks') {
$this->runScheduledTasks($chunkSize, $delay, $maxJobs, $dryRun); $this->runScheduledTasks($chunkSize, $delay, $maxJobs, $dryRun, $frequency);
} }
$this->info('Completed manual execution of scheduled jobs.'.($dryRun ? ' (DRY RUN)' : '')); $this->info('Completed manual execution of scheduled jobs.'.($dryRun ? ' (DRY RUN)' : ''));
} }
private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false): void private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false, ?string $frequency = null): void
{ {
$this->info('Processing scheduled database backups...'); $this->info('Processing scheduled database backups...');
$scheduled_backups = ScheduledDatabaseBackup::where('enabled', true)->get(); $query = ScheduledDatabaseBackup::where('enabled', true);
if ($frequency) {
$query->where(function ($q) use ($frequency) {
// Handle human-readable frequency strings
if (in_array($frequency, ['daily', 'hourly', 'weekly', 'monthly', 'yearly', 'every_minute'])) {
$q->where('frequency', $frequency);
} else {
// Handle cron expressions
$q->where('frequency', $frequency);
}
});
}
$scheduled_backups = $query->get();
if ($scheduled_backups->isEmpty()) { if ($scheduled_backups->isEmpty()) {
$this->info('No enabled scheduled backups found.'); $this->info('No enabled scheduled backups found'.($frequency ? " with frequency '{$frequency}'" : '').'.');
return; return;
} }
@ -96,7 +112,7 @@ private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs =
$this->info("Limited to {$maxJobs} scheduled backups for testing"); $this->info("Limited to {$maxJobs} scheduled backups for testing");
} }
$this->info("Found {$finalScheduledBackups->count()} valid scheduled backups to process"); $this->info("Found {$finalScheduledBackups->count()} valid scheduled backups to process".($frequency ? " with frequency '{$frequency}'" : ''));
$chunks = $finalScheduledBackups->chunk($chunkSize); $chunks = $finalScheduledBackups->chunk($chunkSize);
foreach ($chunks as $index => $chunk) { foreach ($chunks as $index => $chunk) {
@ -105,10 +121,10 @@ private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs =
foreach ($chunk as $scheduled_backup) { foreach ($chunk as $scheduled_backup) {
try { try {
if ($dryRun) { if ($dryRun) {
$this->info("🔍 Would dispatch backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id})"); $this->info("🔍 Would dispatch backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id}, Frequency: {$scheduled_backup->frequency})");
} else { } else {
DatabaseBackupJob::dispatch($scheduled_backup); DatabaseBackupJob::dispatch($scheduled_backup);
$this->info("✓ Dispatched backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id})"); $this->info("✓ Dispatched backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id}, Frequency: {$scheduled_backup->frequency})");
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error("✗ Failed to dispatch backup job for {$scheduled_backup->id}: ".$e->getMessage()); $this->error("✗ Failed to dispatch backup job for {$scheduled_backup->id}: ".$e->getMessage());
@ -123,14 +139,28 @@ private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs =
} }
} }
private function runScheduledTasks(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false): void private function runScheduledTasks(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false, ?string $frequency = null): void
{ {
$this->info('Processing scheduled tasks...'); $this->info('Processing scheduled tasks...');
$scheduled_tasks = ScheduledTask::where('enabled', true)->get(); $query = ScheduledTask::where('enabled', true);
if ($frequency) {
$query->where(function ($q) use ($frequency) {
// Handle human-readable frequency strings
if (in_array($frequency, ['daily', 'hourly', 'weekly', 'monthly', 'yearly', 'every_minute'])) {
$q->where('frequency', $frequency);
} else {
// Handle cron expressions
$q->where('frequency', $frequency);
}
});
}
$scheduled_tasks = $query->get();
if ($scheduled_tasks->isEmpty()) { if ($scheduled_tasks->isEmpty()) {
$this->info('No enabled scheduled tasks found.'); $this->info('No enabled scheduled tasks found'.($frequency ? " with frequency '{$frequency}'" : '').'.');
return; return;
} }
@ -188,7 +218,7 @@ private function runScheduledTasks(int $chunkSize, int $delay, ?int $maxJobs = n
$this->info("Limited to {$maxJobs} scheduled tasks for testing"); $this->info("Limited to {$maxJobs} scheduled tasks for testing");
} }
$this->info("Found {$finalScheduledTasks->count()} valid scheduled tasks to process"); $this->info("Found {$finalScheduledTasks->count()} valid scheduled tasks to process".($frequency ? " with frequency '{$frequency}'" : ''));
$chunks = $finalScheduledTasks->chunk($chunkSize); $chunks = $finalScheduledTasks->chunk($chunkSize);
foreach ($chunks as $index => $chunk) { foreach ($chunks as $index => $chunk) {
@ -197,10 +227,10 @@ private function runScheduledTasks(int $chunkSize, int $delay, ?int $maxJobs = n
foreach ($chunk as $scheduled_task) { foreach ($chunk as $scheduled_task) {
try { try {
if ($dryRun) { if ($dryRun) {
$this->info("🔍 Would dispatch task job for: {$scheduled_task->name} (ID: {$scheduled_task->id})"); $this->info("🔍 Would dispatch task job for: {$scheduled_task->name} (ID: {$scheduled_task->id}, Frequency: {$scheduled_task->frequency})");
} else { } else {
ScheduledTaskJob::dispatch($scheduled_task); ScheduledTaskJob::dispatch($scheduled_task);
$this->info("✓ Dispatched task job for: {$scheduled_task->name} (ID: {$scheduled_task->id})"); $this->info("✓ Dispatched task job for: {$scheduled_task->name} (ID: {$scheduled_task->id}, Frequency: {$scheduled_task->frequency})");
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error("✗ Failed to dispatch task job for {$scheduled_task->id}: ".$e->getMessage()); $this->error("✗ Failed to dispatch task job for {$scheduled_task->id}: ".$e->getMessage());