#php #laravel
Вопрос:
Я работал над проектом, в котором необходим планировщик, и нашел решение, вызывая команду каждую минуту. Я зарегистрировал класс в $commands
переменной в Kernel
, и как только я попытался обслужить приложение, оно просто не работает и не отправляет никакого ответа.
SchedulerDaemon:
<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
use IlluminateSupportFacadesArtisan;
use CarbonCarbon;
use AppActivityLog;
use AppBooking;
use AppNews;
use DB;
use Exception;
use Log;
use Mail;
class SchedulerDaemon extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'schedule:cron {--queue}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Run the scheduler without cron (For use with Heroku etc)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle() {
$this->info('Waiting '. $this->nextMinute(). ' for next run of scheduler');
sleep($this->nextMinute());
$this->runScheduler();
}
/**
* Main recurring loop function.
* Runs the scheduler every minute.
* If the --queue flag is provided it will run the scheduler as a queue job.
* Prevents overruns of cron jobs but does mean you need to have capacity to run the scheduler
* in your queue within 60 seconds.
*
*/
protected function runScheduler() {
// $fn = $this->option('queue') ? 'queue' : 'call';
$this->info('Running scheduler');
// Artisan::$fn('schedule:run');
$this->updateBookings();
$this->info('completed, sleeping..');
sleep($this->nextMinute());
$this->runScheduler();
}
/**
* Works out seconds until the next minute starts;
*
* @return int
*/
protected function nextMinute() {
$current = Carbon::now();
return 60 -$current->second;
}
private function updateBookings() {
if (Carbon::now()->timezone('Asia/Manila')->format('h:i') == '07:00' || Carbon::now()->timezone('Asia/Manila')->format('h:i') == '10:00')
$stoppedAt = null;
try {
$bookings = Booking::where('pickup_date', '=', Carbon::now()->timezone('Asia/Manila')->format('Y-m-d'))
->where('status', '=', '2')
->get();
Log::info($bookings);
foreach ($bookings as $b) {
DB::beginTransaction();
Mail::send(
'templates.emails.pickup',
['booking' => $b, 'status' => 'pickup'],
function ($m) use ($b) {
$m->from('no-reply@kane.com');
$m->to($b->user->email, $b->user->getName())
->subject('Pick up Status');
}
);
$b->status = 3;
$b->save();
$stoppedAt = $b->user;
DB::commit();
}
ActivityLog::log('Updating all bookings with pick up date set for today.', 0);
ActivityLog::log('Sending emails to all clients with pick up date set for today.', 0);
} catch (Exception $e) {
ActivityLog::log('Daily booking update and mailing task failed (stopped at '.$stoppedAt->email.'): '.$e->getMessage(), 0);
Log::error($e);
DB::rollback();
}
}
}
}
Ядро
<?php
namespace AppConsole;
use IlluminateSupportFacadesHttp;
use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;
use CarbonCarbon;
use AppActivityLog;
use AppBooking;
use AppNews;
use DB;
use Exception;
use Log;
use Mail;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
// CommandsSchedulerDaemon::class
];
/**
* Define the application's command schedule.
*
* @param IlluminateConsoleSchedulingSchedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule) {
// UPDATE BOOKINGS FOR THAT DAY
// $schedule->call(function() {
// $stoppedAt = null;
// try {
// $bookings = Booking::where('pickup_date', '=', Carbon::now()->timezone('Asia/Manila')->format('Y-m-d'))
// ->where('status', '=', '2')
// ->get();
// // Log::info($bookings);
// foreach ($bookings as $b) {
// DB::beginTransaction();
// Mail::send(
// 'templates.emails.pickup',
// ['booking' => $b, 'status' => 'pickup'],
// function ($m) use ($b) {
// $m->from('no-reply@kane.com');
// $m->to($b->user->email, $b->user->getName())
// ->subject('Pick up Status');
// }
// );
// $b->status = 3;
// $b->save();
// $stoppedAt = $b->user;
// DB::commit();
// }
// ActivityLog::log('Updating all bookings with pick up date set for today.', 0);
// ActivityLog::log('Sending emails to all clients with pick up date set for today.', 0);
// } catch (Exception $e) {
// ActivityLog::log('Daily booking update and mailing task failed (stopped at '.$stoppedAt->email.'): '.$e->getMessage(), 0);
// Log::error($e);
// DB::rollback();
// }
// })
// // ->everyFiveMinutes()
// ->timezone('Asia/Manila')
// ->twiceDaily(7, 10)
// ->name('daily-pickup-mailer')
// ->withoutOverlapping();
// $schedule->call(function() {
// try {
// DB::beginTransaction();
// $queryString = http_build_query([
// 'access_key' => env('MEDIASTACK_ACCESS_KEY'),
// 'countries' => 'ph',
// 'date' => Carbon::yesterday()->format('Y-m-d').','.Carbon::now()->format('Y-m-d'),
// 'limit' => 1
// ]);
// $ch = curl_init(sprintf('%s?%s', 'https://api.mediastack.com/v1/news', $queryString));
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// $json = curl_exec($ch);
// curl_close($ch);
// $response = json_decode($json, true);
// DB::commit();
// } catch (Exception $e) {
// ActivityLog::log('Failed to fetch new news for today.');
// DB::rollback();
// }
// })
// ->timezone('Asia/Manila')
// ->daily()
// ->name('daily-news-fetcher')
// ->withoutOverlapping();
}
}
Как только я прокомментировал SchedulerDaemon в ядре, ремесленник работает нормально, как будто ничего не произошло.
Ответ №1:
Вы должны изменить свой класс ядра.
<?php
namespace AppConsole;
use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;
use AppConsoleCommandsSchedulerDaemon;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
SchedulerDaemon::class
];
/**
* Define the application's command schedule.
*
* @param IlluminateConsoleSchedulingSchedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('schedule:cron')->everyMinute();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}