Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Services/Schedules/ProcessScheduleService.php
10284 views
1
<?php
2
3
namespace Pterodactyl\Services\Schedules;
4
5
use Exception;
6
use Pterodactyl\Models\Schedule;
7
use Illuminate\Contracts\Bus\Dispatcher;
8
use Pterodactyl\Jobs\Schedule\RunTaskJob;
9
use Illuminate\Database\ConnectionInterface;
10
use Pterodactyl\Exceptions\DisplayException;
11
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
12
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
13
14
class ProcessScheduleService
15
{
16
/**
17
* ProcessScheduleService constructor.
18
*/
19
public function __construct(private ConnectionInterface $connection, private Dispatcher $dispatcher, private DaemonServerRepository $serverRepository)
20
{
21
}
22
23
/**
24
* Process a schedule and push the first task onto the queue worker.
25
*
26
* @throws \Throwable
27
*/
28
public function handle(Schedule $schedule, bool $now = false): void
29
{
30
$task = $schedule->tasks()->orderBy('sequence_id')->first();
31
if (is_null($task)) {
32
throw new DisplayException('Cannot process schedule for task execution: no tasks are registered.');
33
}
34
35
$this->connection->transaction(function () use ($schedule, $task) {
36
$schedule->forceFill([
37
'is_processing' => true,
38
'next_run_at' => $schedule->getNextRunDate(),
39
])->saveOrFail();
40
41
$task->update(['is_queued' => true]);
42
});
43
44
$job = new RunTaskJob($task, $now);
45
if ($schedule->only_when_online) {
46
// Check that the server is currently in a starting or running state before executing
47
// this schedule if this option has been set.
48
try {
49
$details = $this->serverRepository->setServer($schedule->server)->getDetails();
50
$state = $details['state'] ?? 'offline';
51
// If the server is stopping or offline just do nothing with this task.
52
if (in_array($state, ['offline', 'stopping'])) {
53
$job->failed();
54
55
return;
56
}
57
} catch (\Exception $exception) {
58
if (!$exception instanceof DaemonConnectionException) {
59
// If we encountered some exception during this process that wasn't just an
60
// issue connecting to Wings run the failed sequence for a job. Otherwise we
61
// can just quietly mark the task as completed without actually running anything.
62
$job->failed($exception);
63
}
64
$job->failed();
65
66
return;
67
}
68
}
69
70
if (!$now) {
71
$this->dispatcher->dispatch($job->delay($task->time_offset));
72
} else {
73
// When using dispatchNow the RunTaskJob::failed() function is not called automatically
74
// so we need to manually trigger it and then continue with the exception throw.
75
//
76
// @see https://github.com/pterodactyl/panel/issues/2550
77
try {
78
$this->dispatcher->dispatchNow($job);
79
} catch (\Exception $exception) {
80
$job->failed($exception);
81
82
throw $exception;
83
}
84
}
85
}
86
}
87
88