mirror of
				https://github.com/pelican-dev/panel.git
				synced 2025-10-31 21:16:51 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			86 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace App\Services\Schedules;
 | |
| 
 | |
| use Exception;
 | |
| use App\Models\Schedule;
 | |
| use Illuminate\Contracts\Bus\Dispatcher;
 | |
| use App\Jobs\Schedule\RunTaskJob;
 | |
| use Illuminate\Database\ConnectionInterface;
 | |
| use App\Exceptions\DisplayException;
 | |
| use App\Repositories\Daemon\DaemonServerRepository;
 | |
| use App\Exceptions\Http\Connection\DaemonConnectionException;
 | |
| 
 | |
| class ProcessScheduleService
 | |
| {
 | |
|     /**
 | |
|      * ProcessScheduleService constructor.
 | |
|      */
 | |
|     public function __construct(private ConnectionInterface $connection, private Dispatcher $dispatcher, private DaemonServerRepository $serverRepository)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Process a schedule and push the first task onto the queue worker.
 | |
|      *
 | |
|      * @throws \Throwable
 | |
|      */
 | |
|     public function handle(Schedule $schedule, bool $now = false): void
 | |
|     {
 | |
|         $task = $schedule->tasks()->orderBy('sequence_id')->first();
 | |
| 
 | |
|         if (!$task) {
 | |
|             throw new DisplayException('Cannot process schedule for task execution: no tasks are registered.');
 | |
|         }
 | |
| 
 | |
|         $this->connection->transaction(function () use ($schedule, $task) {
 | |
|             $schedule->forceFill([
 | |
|                 'is_processing' => true,
 | |
|                 'next_run_at' => $schedule->getNextRunDate(),
 | |
|             ])->saveOrFail();
 | |
| 
 | |
|             $task->update(['is_queued' => true]);
 | |
|         });
 | |
| 
 | |
|         $job = new RunTaskJob($task, $now);
 | |
|         if ($schedule->only_when_online) {
 | |
|             // Check that the server is currently in a starting or running state before executing
 | |
|             // this schedule if this option has been set.
 | |
|             try {
 | |
|                 $details = $this->serverRepository->setServer($schedule->server)->getDetails();
 | |
|                 $state = $details['state'] ?? 'offline';
 | |
|                 // If the server is stopping or offline just do nothing with this task.
 | |
|                 if (in_array($state, ['offline', 'stopping'])) {
 | |
|                     $job->failed();
 | |
| 
 | |
|                     return;
 | |
|                 }
 | |
|             } catch (\Exception $exception) {
 | |
|                 if (!$exception instanceof DaemonConnectionException) {
 | |
|                     // If we encountered some exception during this process that wasn't just an
 | |
|                     // issue connecting to daemon run the failed sequence for a job. Otherwise we
 | |
|                     // can just quietly mark the task as completed without actually running anything.
 | |
|                     $job->failed($exception);
 | |
|                 }
 | |
|                 $job->failed();
 | |
| 
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!$now) {
 | |
|             $this->dispatcher->dispatch($job->delay($task->time_offset));
 | |
|         } else {
 | |
|             // When using dispatchNow the RunTaskJob::failed() function is not called automatically
 | |
|             // so we need to manually trigger it and then continue with the exception throw.
 | |
|             try {
 | |
|                 $this->dispatcher->dispatchNow($job);
 | |
|             } catch (\Exception $exception) {
 | |
|                 $job->failed($exception);
 | |
| 
 | |
|                 throw $exception;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | 
