| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <?php
- namespace App\Console;
- use Illuminate\Console\Scheduling\Schedule;
- use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
- use Illuminate\Support\Facades\Log;
- class Kernel extends ConsoleKernel
- {
- /**
- * The Artisan commands provided by your application.
- *
- * @var array
- */
- protected $commands = [
- //
- ];
- /**
- * Define the application's command schedule.
- *
- * @param \Illuminate\Console\Scheduling\Schedule $schedule
- * @return void
- */
- protected function schedule(Schedule $schedule)
- {
- // 获取环境模式,默认为 'test'
- $appMode = env('MY_APP_MODE', 'test');
- if ($appMode === 'production') {
- $this->production($schedule);
- }else{
- $this->test($schedule);
- }
- }
- public function production($schedule)
- {
- // 1. Windows 特有任务块
- if (str_contains(PHP_OS, 'WIN')) {
- // Redis 重启:最容易报错(10054),必须独立捕获
- // try {
- // $this->redisTask($schedule);
- // } catch (\Throwable $e) {
- // Log::channel('u8_daily')->error("【系统中断】redisTask 注册异常: " . $e->getMessage());
- // }
- // 队列守卫:非常重要,独立捕获防止受 Redis 影响
- try {
- $this->queueTask($schedule);
- } catch (\Throwable $e) {
- Log::channel('u8_daily')->error("【系统中断】queueTask 注册异常: " . $e->getMessage());
- }
- }
- // 2. 核心业务同步块
- try {
- $this->businessSettle($schedule);
- } catch (\Throwable $e) {
- Log::channel('u8_daily')->error("【系统中断】businessSettle 注册异常: " . $e->getMessage());
- }
- }
- public function redisTask($schedule){
- $schedule->call(function () {
- // 找到你小皮面板里 redis-cli.exe 的绝对路径
- $redisCli = 'D:\phpstudy_pro\Extensions\redis3.0.504\redis-cli.exe';
- Log::channel('u8_daily')->info("【定时维护】正在通过 SHUTDOWN 命令重启 Redis...");
- // 执行关闭并保存数据
- // 如果你设置了密码,需要加上 -a your_password
- exec("\"$redisCli\" SHUTDOWN SAVE", $output, $returnVar);
- if ($returnVar === 0) {
- Log::channel('u8_daily')->info("【调试】Redis 重启成功");
- } else {
- Log::channel('u8_daily')->error("【调试】失败", ['out' => $output]);
- }
- })
- ->name('redis-restart-task')
- ->between('6:00', '6:10')
- ->everyMinute()
- ->withoutOverlapping(20);
- }
- public function queueTask($schedule){
- $schedule->call(function () {
- $queueName = "sync_wms_order";
- $phpPath = "D:/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe";
- $artisan = base_path('artisan');
- // 修改点:增加一个 AND 过滤,排除掉包含 "schedule:run" 的进程
- // 并且确保匹配的是 "queue:work"
- $checkCmd = 'wmic process where "name=\'php.exe\' and commandline like \'%queue:work%--queue=' . $queueName . '%\' and not commandline like \'%schedule:run%\'" get processid /format:list';
- $output = shell_exec($checkCmd);
- if (empty(trim($output)) || str_contains($output, 'No Instance')) {
- // 使用绝对路径启动
- $runCmd = "start /B \"\" \"$phpPath\" \"$artisan\" queue:work redis --queue=$queueName --memory=512";
- pclose(popen($runCmd, "r"));
- Log::channel('queue_daily')->info("单进程守卫:未检测到队列[$queueName],已尝试拉起。");
- } else {
- Log::channel('queue_daily')->info('单进程守卫:队列正在运行中,无需拉起。', ['pid' => trim($output)]);
- }
- })
- ->name('queue-task')
- ->everyMinute()
- ->between('7:00', '23:59');
- }
- public function businessSettle($schedule){
- //先同步物料 再同步单据
- $schedule->command('command:u8_settle_inventory')
- ->between('7:00', '23:59') // 关键点:限制执行时间段 只在这段时间内运行
- ->everyMinute()
- ->withoutOverlapping(10) // 锁长时间一点,给第一次同步留足时间
- ->onSuccess(function () {
- // 2. 只有当 U8SettleInventory 的 handle() 返回 0 时,才执行单据同步
- \Illuminate\Support\Facades\Artisan::call('command:u8_settle');
- })
- ->onFailure(function(){
- Log::channel('u8_daily')->warning('物料同步失败,单据同步已挂起。');
- });
- }
- public function test($schedule){
- //开启队列
- if (str_contains(PHP_OS, 'WIN')) {
- $schedule->call(function () {
- $queueName = "sync_wms_order";
- $phpPath = "D:/phpstudy_pro/Extensions/php/php7.4.3nts/php.exe";
- $artisan = base_path('artisan');
- // 修改点:增加一个 AND 过滤,排除掉包含 "schedule:run" 的进程
- // 并且确保匹配的是 "queue:work"
- $checkCmd = 'wmic process where "name=\'php.exe\' and commandline like \'%queue:work%--queue=' . $queueName . '%\' and not commandline like \'%schedule:run%\'" get processid /format:list';
- $output = shell_exec($checkCmd);
- if (empty(trim($output)) || str_contains($output, 'No Instance')) {
- // 使用绝对路径启动
- $runCmd = "start /B \"\" \"$phpPath\" \"$artisan\" queue:work redis --queue=$queueName --memory=512";
- pclose(popen($runCmd, "r"));
- Log::channel('queue_daily')->info("单进程守卫:未检测到队列[$queueName],已尝试拉起。");
- } else {
- Log::channel('queue_daily')->info('单进程守卫:队列正在运行中,无需拉起。', ['pid' => trim($output)]);
- }
- })->everyMinute();
- }
- $schedule->call(function () {
- Log::channel('u8_daily')->info('测试环境:正在跳过物料同步,直接执行单据同步...');
- // 直接调用单据同步命令
- \Illuminate\Support\Facades\Artisan::call('command:u8_settle');
- })->everyMinute();
- }
- /**
- * Register the commands for the application.
- *
- * @return void
- */
- protected function commands()
- {
- $this->load(__DIR__.'/Commands');
- require base_path('routes/console.php');
- }
- }
|