queue = config('pterodactyl.queues.standard'); $this->task = $task; $this->manualRun = $manualRun; } /** * Run the job and send actions to the daemon running the server. * * @throws \Throwable */ public function handle( DaemonCommandRepository $commandRepository, InitiateBackupService $backupService, DaemonPowerRepository $powerRepository ) { // Do not process a task that is not set to active, unless it's been manually triggered. if (!$this->task->schedule->is_active && !$this->manualRun) { $this->markTaskNotQueued(); $this->markScheduleComplete(); return; } $server = $this->task->server; // Perform the provided task against the daemon. try { switch ($this->task->action) { case Task::ACTION_POWER: $powerRepository->setServer($server)->send($this->task->payload); break; case Task::ACTION_COMMAND: $commandRepository->setServer($server)->send($this->task->payload); break; case Task::ACTION_BACKUP: $backupService->setIgnoredFiles(explode(PHP_EOL, $this->task->payload))->handle($server, null, true); break; default: 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) { } } } throw $exception; } $this->markTaskNotQueued(); $this->queueNextTask(); } /** * Handle a failure while sending the action to the daemon or otherwise processing the job. */ public function failed(Exception $exception = null) { $this->markTaskNotQueued(); $this->markScheduleComplete(); } /** * Get the next task in the schedule and queue it for running after the defined period of wait time. */ private function queueNextTask() { /** @var \Pterodactyl\Models\Task|null $nextTask */ $nextTask = Task::query()->where('schedule_id', $this->task->schedule_id) ->where('sequence_id', $this->task->sequence_id + 1) ->first(); if (is_null($nextTask)) { $this->markScheduleComplete(); return; } $nextTask->update(['is_queued' => true]); $this->dispatch((new self($nextTask, $this->manualRun))->delay($nextTask->time_offset)); } /** * Marks the parent schedule as being complete. */ private function markScheduleComplete() { $this->task->schedule()->update([ 'is_processing' => false, 'last_run_at' => CarbonImmutable::now()->toDateTimeString(), ]); } /** * Mark a specific task as no longer being queued. */ private function markTaskNotQueued() { $this->task->update(['is_queued' => false]); } }