Add separate cron runner that doesn't use proc_open (#1405)

* Add alternative to using the artisan schedule runner

* StyleCI fixes

* Add additional cron time periods

* Style fixes

* Typo

* Update the web cron to use the new system

* Write out JSON for which tasks were run

* Rename cron.php to just cron
This commit is contained in:
Nabeel S 2022-02-11 16:24:06 -05:00 committed by GitHub
parent 607ea6f5e5
commit 78fd8367a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 337 additions and 35 deletions

View File

@ -22,7 +22,11 @@ class ProcessQueue extends Command
'--stop-when-empty' => null,
]);
Log::info(Artisan::output());
$jobOutput = trim(Artisan::output());
if (!empty($jobOutput)) {
Log::info($jobOutput);
}
///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));

90
app/Console/Cron.php Normal file
View File

@ -0,0 +1,90 @@
<?php
/**
* This runs any of the cron tasks that are set to run according to the Laravel schedule
*/
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Contracts\Command;
use Illuminate\Console\Scheduling\Schedule;
class Cron
{
/** @var Schedule */
private $scheduler;
/**
* @var string[] The cron tasks which get called/run
*/
private $cronTasks = [
JobQueue::class,
FiveMinute::class,
FifteenMinute::class,
ThirtyMinute::class,
Hourly::class,
Nightly::class,
Weekly::class,
Monthly::class,
];
/**
* @var array Stores the instantiated cron tasks
*/
private $cronRunners = [];
/**
* @param Schedule $scheduler
*/
public function __construct(Schedule $scheduler)
{
$this->scheduler = $scheduler;
foreach ($this->cronTasks as $task) {
/** @var Command $cronTask */
$cronTask = app($task);
$signature = $cronTask->getSignature();
if (empty($signature)) {
continue;
}
$this->cronRunners[$signature] = $cronTask;
}
}
/**
* Try to figure out which commands are supposed to run right now
*
* @return array string of tasks that were run
*/
public function run(): array
{
$events = $this->scheduler->dueEvents(app());
if (empty($events)) {
return [];
}
$run = [];
/** @var \Illuminate\Console\Scheduling\Event $event */
foreach ($events as $event) {
foreach ($this->cronRunners as $signature => $task) {
if (!str_contains($event->command, $signature)) {
continue;
}
$task->callEvent();
$run[] = $signature;
}
}
return $run;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFifteenMinute;
/**
* The actual cron tasks are in app/Cron
*/
class FifteenMinute extends CronCommand
{
protected $signature = 'cron:fifteen';
protected $description = 'Run the 15 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFifteenMinute());
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFiveMinute;
/**
* This just calls the CronNightly event, so all of the
* listeners, etc can just be called to run those tasks
*
* The actual cron tasks are in app/Cron
*/
class FiveMinute extends CronCommand
{
protected $signature = 'cron:five';
protected $description = 'Run the 5 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFiveMinute());
}
}

View File

@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronHourly;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class Hourly extends Command
class Hourly extends CronCommand
{
protected $signature = 'cron:hourly';
protected $description = 'Run the hourly cron tasks';
@ -17,7 +17,11 @@ class Hourly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronHourly());
}
}

View File

@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use Illuminate\Support\Facades\Artisan;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class JobQueue extends Command
class JobQueue extends CronCommand
{
protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks';
@ -17,9 +17,16 @@ class JobQueue extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
Artisan::call('queue:cron');
$this->callEvent();
$this->info(Artisan::output());
$queueOutput = trim(Artisan::output());
if (!empty($queueOutput)) {
$this->info($queueOutput);
}
}
public function callEvent()
{
Artisan::call('queue:cron');
}
}

View File

@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronMonthly;
/**
@ -11,7 +11,7 @@ use App\Events\CronMonthly;
*
* The actual cron tasks are in app/Cron
*/
class Monthly extends Command
class Monthly extends CronCommand
{
protected $signature = 'cron:monthly';
protected $description = 'Run the monthly cron tasks';
@ -19,7 +19,11 @@ class Monthly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronMonthly());
}
}

View File

@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronNightly;
/**
@ -11,7 +11,7 @@ use App\Events\CronNightly;
*
* The actual cron tasks are in app/Cron
*/
class Nightly extends Command
class Nightly extends CronCommand
{
protected $signature = 'cron:nightly';
protected $description = 'Run the nightly cron tasks';
@ -19,7 +19,11 @@ class Nightly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronNightly());
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronThirtyMinute;
/**
* The actual cron tasks are in app/Cron
*/
class ThirtyMinute extends CronCommand
{
protected $signature = 'cron:thirty';
protected $description = 'Run the 30 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronThirtyMinute());
}
}

View File

@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronWeekly;
/**
@ -11,7 +11,7 @@ use App\Events\CronWeekly;
*
* The actual cron tasks are in app/Cron
*/
class Weekly extends Command
class Weekly extends CronCommand
{
protected $signature = 'cron:weekly';
protected $description = 'Run the weekly cron tasks';
@ -19,7 +19,11 @@ class Weekly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronWeekly());
}
}

View File

@ -2,10 +2,13 @@
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Services\CronService;
use Illuminate\Console\Scheduling\Schedule;
@ -33,10 +36,16 @@ class Kernel extends ConsoleKernel
->withoutOverlapping();
}
/*
* NOTE: IF MORE TASKS ARE ADDED, THEY ALSO MUST BE ADDED TO THE CRON.PHP
*/
$schedule->command(FiveMinute::class)->everyFiveMinutes();
$schedule->command(FifteenMinute::class)->everyFifteenMinutes();
$schedule->command(ThirtyMinute::class)->everyThirtyMinutes();
$schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Hourly::class)->hourly();
$schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1);
$schedule->command(Hourly::class)->hourly();
// When spatie-backups runs
/*if (config('backup.backup.enabled', false) === true) {

View File

@ -29,6 +29,16 @@ abstract class Command extends \Illuminate\Console\Command
}*/
}
/**
* Return the signature of the command
*
* @return string
*/
public function getSignature(): string
{
return $this->signature;
}
/**
* Splice the logger and replace the active handlers with the handlers from the
* a stack in config/logging.php

View File

@ -0,0 +1,20 @@
<?php
namespace App\Contracts;
abstract class CronCommand extends Command
{
/**
* @return mixed
*/
abstract public function callEvent();
/**
* Adjust the logging depending on where we're running from
*/
public function __construct()
{
parent::__construct();
$this->redirectLoggingToFile('cron');
}
}

View File

@ -20,7 +20,7 @@ class ClearExpiredSimbrief extends Listener
}
/**
* @param \App\Events\CronNightly $event
* @param CronHourly $event
*/
public function handle(CronHourly $event): void
{

View File

@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFifteenMinute extends Event
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFiveMinute extends Event
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronThirtyMinute extends Event
{
}

View File

@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api;
use App\Console\Cron;
use App\Contracts\Controller;
use App\Exceptions\CronInvalid;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
class MaintenanceController extends Controller
{
@ -24,12 +24,12 @@ class MaintenanceController extends Controller
throw new CronInvalid();
}
$output = '';
Artisan::call('schedule:run');
$output .= trim(Artisan::output());
$cron = app(Cron::class);
$run = $cron->run();
return response([
'content' => $output,
return response()->json([
'count' => count($run),
'tasks' => $run,
]);
}
}

View File

@ -12,9 +12,12 @@ use App\Cron\Nightly\PilotLeave;
use App\Cron\Nightly\RecalculateBalances;
use App\Cron\Nightly\RecalculateStats;
use App\Cron\Nightly\SetActiveFlights;
use App\Events\CronFifteenMinute;
use App\Events\CronFiveMinute;
use App\Events\CronHourly;
use App\Events\CronMonthly;
use App\Events\CronNightly;
use App\Events\CronThirtyMinute;
use App\Events\CronWeekly;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@ -24,6 +27,15 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
class CronServiceProvider extends ServiceProvider
{
protected $listen = [
CronFiveMinute::class => [],
CronFifteenMinute::class => [],
CronThirtyMinute::class => [],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
CronNightly::class => [
ApplyExpenses::class,
RecalculateBalances::class,
@ -32,19 +44,10 @@ class CronServiceProvider extends ServiceProvider
RecalculateStats::class,
NewVersionCheck::class,
],
CronWeekly::class => [
],
CronMonthly::class => [
\App\Cron\Monthly\ApplyExpenses::class,
],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
];
}

35
bin/cron Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env php
<?php
/**
* THIS CRON FILE IS A BACKUP METHOD IF YOUR SERVER DOES NOT HAVE PROC_OPEN ENABLED
* YOU SHOULD TRY USING THE DEFAULT INSTRUCTIONS OF USING ARTISAN SCHEDULE:RUN
*/
define('LARAVEL_START', microtime(true));
use App\Console\Cron;
use App\Console\Kernel;
require __DIR__.'/../vendor/autoload.php';
/** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php';
/** @var Kernel $kernel */
$kernel = $app->make(Kernel::class);
// Run a null artisan thing just so Laravel internals can be setup properly
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'version',
]),
new Symfony\Component\Console\Output\NullOutput()
);
/** @var Cron $cron */
$cron = app(Cron::class);
$run = $cron->run();
echo json_encode([
'count' => count($run),
'tasks' => $run,
]);