Skip to content

Commit 2685295

Browse files
authored
Merge branch 'develop' into xtermstuff
2 parents 8f2e90d + 14099c1 commit 2685295

File tree

26 files changed

+585
-288
lines changed

26 files changed

+585
-288
lines changed

app/Contracts/Repository/ScheduleRepositoryInterface.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@ interface ScheduleRepositoryInterface extends RepositoryInterface
1515
*/
1616
public function findServerSchedules(int $server): Collection;
1717

18-
/**
19-
* Load the tasks relationship onto the Schedule module if they are not
20-
* already present.
21-
*
22-
* @param \Pterodactyl\Models\Schedule $schedule
23-
* @param bool $refresh
24-
* @return \Pterodactyl\Models\Schedule
25-
*/
26-
public function loadTasks(Schedule $schedule, bool $refresh = false): Schedule;
27-
2818
/**
2919
* Return a schedule model with all of the associated tasks as a relationship.
3020
*

app/Http/Controllers/Api/Client/Servers/ScheduleController.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@
1010
use Pterodactyl\Models\Schedule;
1111
use Illuminate\Http\JsonResponse;
1212
use Pterodactyl\Helpers\Utilities;
13+
use Pterodactyl\Jobs\Schedule\RunTaskJob;
1314
use Pterodactyl\Exceptions\DisplayException;
1415
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
16+
use Pterodactyl\Services\Schedules\ProcessScheduleService;
1517
use Pterodactyl\Transformers\Api\Client\ScheduleTransformer;
1618
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
1719
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
20+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1821
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\ViewScheduleRequest;
1922
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\StoreScheduleRequest;
2023
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\DeleteScheduleRequest;
2124
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\UpdateScheduleRequest;
25+
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest;
2226

2327
class ScheduleController extends ClientApiController
2428
{
@@ -27,16 +31,23 @@ class ScheduleController extends ClientApiController
2731
*/
2832
private $repository;
2933

34+
/**
35+
* @var \Pterodactyl\Services\Schedules\ProcessScheduleService
36+
*/
37+
private $service;
38+
3039
/**
3140
* ScheduleController constructor.
3241
*
3342
* @param \Pterodactyl\Repositories\Eloquent\ScheduleRepository $repository
43+
* @param \Pterodactyl\Services\Schedules\ProcessScheduleService $service
3444
*/
35-
public function __construct(ScheduleRepository $repository)
45+
public function __construct(ScheduleRepository $repository, ProcessScheduleService $service)
3646
{
3747
parent::__construct();
3848

3949
$this->repository = $repository;
50+
$this->service = $service;
4051
}
4152

4253
/**
@@ -147,6 +158,30 @@ public function update(UpdateScheduleRequest $request, Server $server, Schedule
147158
->toArray();
148159
}
149160

161+
/**
162+
* Executes a given schedule immediately rather than waiting on it's normally scheduled time
163+
* to pass. This does not care about the schedule state.
164+
*
165+
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest $request
166+
* @param \Pterodactyl\Models\Server $server
167+
* @param \Pterodactyl\Models\Schedule $schedule
168+
* @return \Illuminate\Http\JsonResponse
169+
*
170+
* @throws \Throwable
171+
*/
172+
public function execute(TriggerScheduleRequest $request, Server $server, Schedule $schedule)
173+
{
174+
if (!$schedule->is_active) {
175+
throw new BadRequestHttpException(
176+
'Cannot trigger schedule exection for a schedule that is not currently active.'
177+
);
178+
}
179+
180+
$this->service->handle($schedule, true);
181+
182+
return new JsonResponse([], JsonResponse::HTTP_ACCEPTED);
183+
}
184+
150185
/**
151186
* Deletes a schedule and it's associated tasks.
152187
*
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Schedules;
4+
5+
use Pterodactyl\Models\Permission;
6+
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
7+
8+
class TriggerScheduleRequest extends ClientApiRequest
9+
{
10+
/**
11+
* @return string
12+
*/
13+
public function permission(): string
14+
{
15+
return Permission::ACTION_SCHEDULE_UPDATE;
16+
}
17+
18+
/**
19+
* @return array
20+
*/
21+
public function rules(): array
22+
{
23+
return [];
24+
}
25+
}

app/Jobs/Schedule/RunTaskJob.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,13 @@ public function __construct(Task $task)
4242
* @param \Pterodactyl\Repositories\Wings\DaemonCommandRepository $commandRepository
4343
* @param \Pterodactyl\Services\Backups\InitiateBackupService $backupService
4444
* @param \Pterodactyl\Repositories\Wings\DaemonPowerRepository $powerRepository
45-
* @param \Pterodactyl\Repositories\Eloquent\TaskRepository $taskRepository
4645
*
4746
* @throws \Throwable
4847
*/
4948
public function handle(
5049
DaemonCommandRepository $commandRepository,
5150
InitiateBackupService $backupService,
52-
DaemonPowerRepository $powerRepository,
53-
TaskRepository $taskRepository
51+
DaemonPowerRepository $powerRepository
5452
) {
5553
// Do not process a task that is not set to active.
5654
if (! $this->task->schedule->is_active) {

app/Models/Schedule.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Pterodactyl\Models;
44

5+
use Cron\CronExpression;
6+
use Carbon\CarbonImmutable;
57
use Illuminate\Container\Container;
68
use Pterodactyl\Contracts\Extensions\HashidsInterface;
79

@@ -114,6 +116,20 @@ class Schedule extends Model
114116
'next_run_at' => 'nullable|date',
115117
];
116118

119+
/**
120+
* Returns the schedule's execution crontab entry as a string.
121+
*
122+
* @return \Carbon\CarbonImmutable
123+
*/
124+
public function getNextRunDate()
125+
{
126+
$formatted = sprintf('%s %s %s * %s', $this->cron_minute, $this->cron_hour, $this->cron_day_of_month, $this->cron_day_of_week);
127+
128+
return CarbonImmutable::createFromTimestamp(
129+
CronExpression::factory($formatted)->getNextRunDate()->getTimestamp()
130+
);
131+
}
132+
117133
/**
118134
* Return a hashid encoded string to represent the ID of the schedule.
119135
*

app/Repositories/Eloquent/ScheduleRepository.php

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,6 @@ public function findServerSchedules(int $server): Collection
3131
return $this->getBuilder()->withCount('tasks')->where('server_id', '=', $server)->get($this->getColumns());
3232
}
3333

34-
/**
35-
* Load the tasks relationship onto the Schedule module if they are not
36-
* already present.
37-
*
38-
* @param \Pterodactyl\Models\Schedule $schedule
39-
* @param bool $refresh
40-
* @return \Pterodactyl\Models\Schedule
41-
*/
42-
public function loadTasks(Schedule $schedule, bool $refresh = false): Schedule
43-
{
44-
if (! $schedule->relationLoaded('tasks') || $refresh) {
45-
$schedule->load('tasks');
46-
}
47-
48-
return $schedule;
49-
}
50-
5134
/**
5235
* Return a schedule model with all of the associated tasks as a relationship.
5336
*

app/Services/Schedules/ProcessScheduleService.php

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
namespace Pterodactyl\Services\Schedules;
44

5-
use Cron\CronExpression;
65
use Pterodactyl\Models\Schedule;
76
use Illuminate\Contracts\Bus\Dispatcher;
87
use Pterodactyl\Jobs\Schedule\RunTaskJob;
9-
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
10-
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
8+
use Illuminate\Database\ConnectionInterface;
9+
use Pterodactyl\Exceptions\DisplayException;
1110

1211
class ProcessScheduleService
1312
{
@@ -17,62 +16,51 @@ class ProcessScheduleService
1716
private $dispatcher;
1817

1918
/**
20-
* @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface
19+
* @var \Illuminate\Database\ConnectionInterface
2120
*/
22-
private $scheduleRepository;
23-
24-
/**
25-
* @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface
26-
*/
27-
private $taskRepository;
21+
private $connection;
2822

2923
/**
3024
* ProcessScheduleService constructor.
3125
*
26+
* @param \Illuminate\Database\ConnectionInterface $connection
3227
* @param \Illuminate\Contracts\Bus\Dispatcher $dispatcher
33-
* @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $scheduleRepository
34-
* @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $taskRepository
3528
*/
36-
public function __construct(
37-
Dispatcher $dispatcher,
38-
ScheduleRepositoryInterface $scheduleRepository,
39-
TaskRepositoryInterface $taskRepository
40-
) {
29+
public function __construct(ConnectionInterface $connection, Dispatcher $dispatcher)
30+
{
4131
$this->dispatcher = $dispatcher;
42-
$this->scheduleRepository = $scheduleRepository;
43-
$this->taskRepository = $taskRepository;
32+
$this->connection = $connection;
4433
}
4534

4635
/**
4736
* Process a schedule and push the first task onto the queue worker.
4837
*
4938
* @param \Pterodactyl\Models\Schedule $schedule
39+
* @param bool $now
5040
*
51-
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
52-
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
41+
* @throws \Throwable
5342
*/
54-
public function handle(Schedule $schedule)
43+
public function handle(Schedule $schedule, bool $now = false)
5544
{
56-
$this->scheduleRepository->loadTasks($schedule);
57-
5845
/** @var \Pterodactyl\Models\Task $task */
59-
$task = $schedule->getRelation('tasks')->where('sequence_id', 1)->first();
46+
$task = $schedule->tasks()->where('sequence_id', 1)->first();
6047

61-
$formattedCron = sprintf('%s %s %s * %s',
62-
$schedule->cron_minute,
63-
$schedule->cron_hour,
64-
$schedule->cron_day_of_month,
65-
$schedule->cron_day_of_week
66-
);
48+
if (is_null($task)) {
49+
throw new DisplayException(
50+
'Cannot process schedule for task execution: no tasks are registered.'
51+
);
52+
}
6753

68-
$this->scheduleRepository->update($schedule->id, [
69-
'is_processing' => true,
70-
'next_run_at' => CronExpression::factory($formattedCron)->getNextRunDate(),
71-
]);
54+
$this->connection->transaction(function () use ($schedule, $task) {
55+
$schedule->forceFill([
56+
'is_processing' => true,
57+
'next_run_at' => $schedule->getNextRunDate(),
58+
])->saveOrFail();
7259

73-
$this->taskRepository->update($task->id, ['is_queued' => true]);
60+
$task->update(['is_queued' => true]);
61+
});
7462

75-
$this->dispatcher->dispatch(
63+
$this->dispatcher->{$now ? 'dispatchNow' : 'dispatch'}(
7664
(new RunTaskJob($task))->delay($task->time_offset)
7765
);
7866
}

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"name": "pterodactyl-panel",
33
"dependencies": {
4-
"@fortawesome/fontawesome-svg-core": "1.2.19",
5-
"@fortawesome/free-solid-svg-icons": "^5.9.0",
6-
"@fortawesome/react-fontawesome": "0.1.4",
4+
"@fortawesome/fontawesome-svg-core": "^1.2.32",
5+
"@fortawesome/free-solid-svg-icons": "^5.15.1",
6+
"@fortawesome/react-fontawesome": "^0.1.11",
77
"axios": "^0.19.2",
88
"chart.js": "^2.8.0",
99
"codemirror": "^5.57.0",
@@ -23,9 +23,9 @@
2323
"react": "^16.13.1",
2424
"react-dom": "npm:@hot-loader/react-dom",
2525
"react-fast-compare": "^3.2.0",
26+
"react-ga": "^3.1.2",
2627
"react-google-recaptcha": "^2.0.1",
2728
"react-helmet": "^6.1.0",
28-
"react-ga": "^3.1.2",
2929
"react-hot-loader": "^4.12.21",
3030
"react-i18next": "^11.2.1",
3131
"react-redux": "^7.1.0",

resources/scripts/api/server/schedules/getServerSchedules.tsx renamed to resources/scripts/api/server/schedules/getServerSchedules.ts

File renamed without changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import http from '@/api/http';
2+
3+
export default async (server: string, schedule: number): Promise<void> =>
4+
await http.post(`/api/client/servers/${server}/schedules/${schedule}/execute`);

0 commit comments

Comments
 (0)