From 8c6327fd3253e009f86313695a57469728fd7807 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 25 Oct 2020 15:06:54 -0700 Subject: [PATCH] Let MySQL do the time logic when looking for tasks --- .../Schedule/ProcessRunnableCommand.php | 60 ++++------- .../ScheduleRepositoryInterface.php | 8 -- app/Helpers/Utilities.php | 7 +- .../Eloquent/ScheduleRepository.php | 15 --- .../Schedule/ProcessRunnableCommandTest.php | 102 ------------------ 5 files changed, 24 insertions(+), 168 deletions(-) delete mode 100644 tests/Unit/Commands/Schedule/ProcessRunnableCommandTest.php diff --git a/app/Console/Commands/Schedule/ProcessRunnableCommand.php b/app/Console/Commands/Schedule/ProcessRunnableCommand.php index 67654708c..4d5981fd3 100644 --- a/app/Console/Commands/Schedule/ProcessRunnableCommand.php +++ b/app/Console/Commands/Schedule/ProcessRunnableCommand.php @@ -1,62 +1,38 @@ . - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ namespace Pterodactyl\Console\Commands\Schedule; -use Cake\Chronos\Chronos; use Illuminate\Console\Command; -use Illuminate\Support\Collection; +use Pterodactyl\Models\Schedule; use Pterodactyl\Services\Schedules\ProcessScheduleService; -use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; class ProcessRunnableCommand extends Command { /** * @var string */ - protected $description = 'Process schedules in the database and determine which are ready to run.'; - - /** - * @var \Pterodactyl\Services\Schedules\ProcessScheduleService - */ - protected $processScheduleService; - - /** - * @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface - */ - protected $repository; + protected $signature = 'p:schedule:process'; /** * @var string */ - protected $signature = 'p:schedule:process'; - - /** - * ProcessRunnableCommand constructor. - * - * @param \Pterodactyl\Services\Schedules\ProcessScheduleService $processScheduleService - * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository - */ - public function __construct(ProcessScheduleService $processScheduleService, ScheduleRepositoryInterface $repository) - { - parent::__construct(); - - $this->processScheduleService = $processScheduleService; - $this->repository = $repository; - } + protected $description = 'Process schedules in the database and determine which are ready to run.'; /** * Handle command execution. + * + * @param \Pterodactyl\Services\Schedules\ProcessScheduleService $service + * + * @throws \Throwable */ - public function handle() + public function handle(ProcessScheduleService $service) { - $schedules = $this->repository->getSchedulesToProcess(Chronos::now()->toAtomString()); + $schedules = Schedule::query()->with('tasks') + ->where('is_active', true) + ->where('is_processing', false) + ->whereRaw('next_run_at <= NOW()') + ->get(); + if ($schedules->count() < 1) { $this->line('There are no scheduled tasks for servers that need to be run.'); @@ -64,9 +40,9 @@ class ProcessRunnableCommand extends Command } $bar = $this->output->createProgressBar(count($schedules)); - $schedules->each(function ($schedule) use ($bar) { - if ($schedule->tasks instanceof Collection && count($schedule->tasks) > 0) { - $this->processScheduleService->handle($schedule); + foreach ($schedules as $schedule) { + if ($schedule->tasks->isNotEmpty()) { + $service->handle($schedule); if ($this->input->isInteractive()) { $bar->clear(); @@ -79,7 +55,7 @@ class ProcessRunnableCommand extends Command $bar->advance(); $bar->display(); - }); + } $this->line(''); } diff --git a/app/Contracts/Repository/ScheduleRepositoryInterface.php b/app/Contracts/Repository/ScheduleRepositoryInterface.php index 32650bdcf..b6e73a2de 100644 --- a/app/Contracts/Repository/ScheduleRepositoryInterface.php +++ b/app/Contracts/Repository/ScheduleRepositoryInterface.php @@ -24,12 +24,4 @@ interface ScheduleRepositoryInterface extends RepositoryInterface * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ public function getScheduleWithTasks(int $schedule): Schedule; - - /** - * Return all of the schedules that should be processed. - * - * @param string $timestamp - * @return \Illuminate\Support\Collection - */ - public function getSchedulesToProcess(string $timestamp): Collection; } diff --git a/app/Helpers/Utilities.php b/app/Helpers/Utilities.php index d900425d9..d6b4e752f 100644 --- a/app/Helpers/Utilities.php +++ b/app/Helpers/Utilities.php @@ -52,7 +52,12 @@ class Utilities )->getNextRunDate()); } - public static function checked($name, $default) + /** + * @param string $name + * @param mixed $default + * @return string + */ + public static function checked(string $name, $default) { $errors = session('errors'); diff --git a/app/Repositories/Eloquent/ScheduleRepository.php b/app/Repositories/Eloquent/ScheduleRepository.php index 030939da7..cb1b2cbf0 100644 --- a/app/Repositories/Eloquent/ScheduleRepository.php +++ b/app/Repositories/Eloquent/ScheduleRepository.php @@ -47,19 +47,4 @@ class ScheduleRepository extends EloquentRepository implements ScheduleRepositor throw new RecordNotFoundException; } } - - /** - * Return all of the schedules that should be processed. - * - * @param string $timestamp - * @return \Illuminate\Support\Collection - */ - public function getSchedulesToProcess(string $timestamp): Collection - { - return $this->getBuilder()->with('tasks') - ->where('is_active', true) - ->where('is_processing', false) - ->where('next_run_at', '<=', $timestamp) - ->get($this->getColumns()); - } } diff --git a/tests/Unit/Commands/Schedule/ProcessRunnableCommandTest.php b/tests/Unit/Commands/Schedule/ProcessRunnableCommandTest.php deleted file mode 100644 index 5efbef6c4..000000000 --- a/tests/Unit/Commands/Schedule/ProcessRunnableCommandTest.php +++ /dev/null @@ -1,102 +0,0 @@ -processScheduleService = m::mock(ProcessScheduleService::class); - $this->repository = m::mock(ScheduleRepositoryInterface::class); - - $this->command = new ProcessRunnableCommand($this->processScheduleService, $this->repository); - } - - /** - * Test that a schedule can be queued up correctly. - */ - public function testScheduleIsQueued() - { - $schedule = factory(Schedule::class)->make(); - $schedule->tasks = collect([factory(Task::class)->make()]); - - $this->repository->shouldReceive('getSchedulesToProcess')->with(Chronos::now()->toAtomString())->once()->andReturn(collect([$schedule])); - $this->processScheduleService->shouldReceive('handle')->with($schedule)->once()->andReturnNull(); - - $display = $this->runCommand($this->command); - - $this->assertNotEmpty($display); - $this->assertStringContainsString(trans('command/messages.schedule.output_line', [ - 'schedule' => $schedule->name, - 'hash' => $schedule->hashid, - ]), $display); - } - - /** - * If tasks is an empty collection, don't process it. - */ - public function testScheduleWithNoTasksIsNotProcessed() - { - $schedule = factory(Schedule::class)->make(); - $schedule->tasks = collect([]); - - $this->repository->shouldReceive('getSchedulesToProcess')->with(Chronos::now()->toAtomString())->once()->andReturn(collect([$schedule])); - - $display = $this->runCommand($this->command); - - $this->assertNotEmpty($display); - $this->assertStringNotContainsString(trans('command/messages.schedule.output_line', [ - 'schedule' => $schedule->name, - 'hash' => $schedule->hashid, - ]), $display); - } - - /** - * If tasks isn't an instance of a collection, don't process it. - */ - public function testScheduleWithTasksObjectThatIsNotInstanceOfCollectionIsNotProcessed() - { - $schedule = factory(Schedule::class)->make(['tasks' => null]); - - $this->repository->shouldReceive('getSchedulesToProcess')->with(Chronos::now()->toAtomString())->once()->andReturn(collect([$schedule])); - - $display = $this->runCommand($this->command); - - $this->assertNotEmpty($display); - $this->assertStringNotContainsString(trans('command/messages.schedule.output_line', [ - 'schedule' => $schedule->name, - 'hash' => $schedule->hashid, - ]), $display); - } -}