Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Jobs/Schedule/RunTaskJob.php
10279 views
1
<?php
2
3
namespace Pterodactyl\Jobs\Schedule;
4
5
use Exception;
6
use Pterodactyl\Jobs\Job;
7
use Carbon\CarbonImmutable;
8
use Pterodactyl\Models\Task;
9
use Illuminate\Queue\SerializesModels;
10
use Illuminate\Queue\InteractsWithQueue;
11
use Illuminate\Contracts\Queue\ShouldQueue;
12
use Illuminate\Foundation\Bus\DispatchesJobs;
13
use Pterodactyl\Services\Backups\InitiateBackupService;
14
use Pterodactyl\Repositories\Wings\DaemonPowerRepository;
15
use Pterodactyl\Repositories\Wings\DaemonCommandRepository;
16
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
17
18
class RunTaskJob extends Job implements ShouldQueue
19
{
20
use DispatchesJobs;
21
use InteractsWithQueue;
22
use SerializesModels;
23
24
/**
25
* RunTaskJob constructor.
26
*/
27
public function __construct(public Task $task, public bool $manualRun = false)
28
{
29
$this->queue = 'standard';
30
}
31
32
/**
33
* Run the job and send actions to the daemon running the server.
34
*
35
* @throws \Throwable
36
*/
37
public function handle(
38
DaemonCommandRepository $commandRepository,
39
InitiateBackupService $backupService,
40
DaemonPowerRepository $powerRepository,
41
) {
42
// Do not process a task that is not set to active, unless it's been manually triggered.
43
if (!$this->task->schedule->is_active && !$this->manualRun) {
44
$this->markTaskNotQueued();
45
$this->markScheduleComplete();
46
47
return;
48
}
49
50
$server = $this->task->server;
51
// If we made it to this point and the server status is not null it means the
52
// server was likely suspended or marked as reinstalling after the schedule
53
// was queued up. Just end the task right now — this should be a very rare
54
// condition.
55
if (!is_null($server->status)) {
56
$this->failed();
57
58
return;
59
}
60
61
// Perform the provided task against the daemon.
62
try {
63
switch ($this->task->action) {
64
case Task::ACTION_POWER:
65
$powerRepository->setServer($server)->send($this->task->payload);
66
break;
67
case Task::ACTION_COMMAND:
68
$commandRepository->setServer($server)->send($this->task->payload);
69
break;
70
case Task::ACTION_BACKUP:
71
$backupService->setIgnoredFiles(explode(PHP_EOL, $this->task->payload))->handle($server, null, true);
72
break;
73
default:
74
throw new \InvalidArgumentException('Invalid task action provided: ' . $this->task->action);
75
}
76
} catch (\Exception $exception) {
77
// If this isn't a DaemonConnectionException on a task that allows for failures
78
// throw the exception back up the chain so that the task is stopped.
79
if (!($this->task->continue_on_failure && $exception instanceof DaemonConnectionException)) {
80
throw $exception;
81
}
82
}
83
84
$this->markTaskNotQueued();
85
$this->queueNextTask();
86
}
87
88
/**
89
* Handle a failure while sending the action to the daemon or otherwise processing the job.
90
*/
91
public function failed(?\Exception $exception = null)
92
{
93
$this->markTaskNotQueued();
94
$this->markScheduleComplete();
95
}
96
97
/**
98
* Get the next task in the schedule and queue it for running after the defined period of wait time.
99
*/
100
private function queueNextTask()
101
{
102
/** @var Task|null $nextTask */
103
$nextTask = Task::query()->where('schedule_id', $this->task->schedule_id)
104
->orderBy('sequence_id', 'asc')
105
->where('sequence_id', '>', $this->task->sequence_id)
106
->first();
107
108
if (is_null($nextTask)) {
109
$this->markScheduleComplete();
110
111
return;
112
}
113
114
$nextTask->update(['is_queued' => true]);
115
116
$this->dispatch((new self($nextTask, $this->manualRun))->delay($nextTask->time_offset));
117
}
118
119
/**
120
* Marks the parent schedule as being complete.
121
*/
122
private function markScheduleComplete()
123
{
124
$this->task->schedule()->update([
125
'is_processing' => false,
126
'last_run_at' => CarbonImmutable::now()->toDateTimeString(),
127
]);
128
}
129
130
/**
131
* Mark a specific task as no longer being queued.
132
*/
133
private function markTaskNotQueued()
134
{
135
$this->task->update(['is_queued' => false]);
136
}
137
}
138
139