diff --git a/app/Jobs/Schedule/RunTaskJob.php b/app/Jobs/Schedule/RunTaskJob.php index 69a0d171f..ddedb0260 100644 --- a/app/Jobs/Schedule/RunTaskJob.php +++ b/app/Jobs/Schedule/RunTaskJob.php @@ -7,8 +7,6 @@ use Pterodactyl\Jobs\Job; use Carbon\CarbonImmutable; use Pterodactyl\Models\Task; use InvalidArgumentException; -use Illuminate\Http\Response; -use Pterodactyl\Models\Schedule; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; @@ -79,17 +77,11 @@ class RunTaskJob extends Job implements ShouldQueue throw new InvalidArgumentException('Cannot run a task that points to a non-existent action.'); } } catch (Exception $exception) { - if ($exception instanceof DaemonConnectionException) { - // If the task "failed" because the server is offline and it was sending a command or - // executing a power action (which shouldn't happen?) then just stop trying to process - // the schedule, but don't actually log the failure. - if ($this->task->action === Task::ACTION_POWER || $this->task->action === Task::ACTION_COMMAND) { - // Do the thing - if ($exception->getStatusCode() === Response::HTTP_CONFLICT) { - } - } + // If this isn't a DaemonConnectionException on a task that allows for failures + // throw the exception back up the chain so that the task is stopped. + if (!($this->task->continue_on_failure && $exception instanceof DaemonConnectionException)) { + throw $exception; } - throw $exception; } $this->markTaskNotQueued(); diff --git a/app/Services/Schedules/ProcessScheduleService.php b/app/Services/Schedules/ProcessScheduleService.php index 9e62d45cb..a131ad573 100644 --- a/app/Services/Schedules/ProcessScheduleService.php +++ b/app/Services/Schedules/ProcessScheduleService.php @@ -8,6 +8,8 @@ use Illuminate\Contracts\Bus\Dispatcher; use Pterodactyl\Jobs\Schedule\RunTaskJob; use Illuminate\Database\ConnectionInterface; use Pterodactyl\Exceptions\DisplayException; +use Pterodactyl\Repositories\Wings\DaemonServerRepository; +use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; class ProcessScheduleService { @@ -21,13 +23,19 @@ class ProcessScheduleService */ private $connection; + /** + * @var \Pterodactyl\Repositories\Wings\DaemonServerRepository + */ + private $serverRepository; + /** * ProcessScheduleService constructor. */ - public function __construct(ConnectionInterface $connection, Dispatcher $dispatcher) + public function __construct(ConnectionInterface $connection, DaemonServerRepository $serverRepository, Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; $this->connection = $connection; + $this->serverRepository = $serverRepository; } /** @@ -38,7 +46,7 @@ class ProcessScheduleService public function handle(Schedule $schedule, bool $now = false) { /** @var \Pterodactyl\Models\Task $task */ - $task = $schedule->tasks()->orderBy('sequence_id', 'asc')->first(); + $task = $schedule->tasks()->orderBy('sequence_id')->first(); if (is_null($task)) { throw new DisplayException('Cannot process schedule for task execution: no tasks are registered.'); @@ -54,6 +62,30 @@ class ProcessScheduleService }); $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 Wings 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));