Laravel非重叠计划作业未执行

Laravel非重叠计划作业未执行,laravel,laravel-5,Laravel,Laravel 5,我有一个Laravel计划的作业,它是在Kernel.php中定义的 $schedule->call('\App\Http\Controllers\ScheduleController@processQueuedMessages') ->everyFiveMinutes() ->name('process_queued_messages') ->withoutOverlapping(); 在开发过程中,由于语法错误,我的作业引发了一个异常。我更正

我有一个Laravel计划的作业,它是在
Kernel.php
中定义的

$schedule->call('\App\Http\Controllers\ScheduleController@processQueuedMessages')
    ->everyFiveMinutes()
    ->name('process_queued_messages')
    ->withoutOverlapping();
在开发过程中,由于语法错误,我的作业引发了一个异常。我更正了错误并再次尝试执行它;但由于某种原因,它不会

我尝试了
artisan向下
,然后
artisan向上
。我还尝试重新启动服务器实例。但没有任何帮助。作业没有执行(也没有例外)


我意识到问题是由于
->没有重叠()。不知何故,Laravel scheduler认为作业已在运行,因此不再执行它。

我通过查看供应商代码找到了解决方案

Illuminate\Console\Scheduling\CallbackEvent.php
它在本地存储器中创建一个名为
schedule-*
的文件

public function withoutOverlapping()
{
    if ( ! isset($this->description))
    {
        throw new LogicException(
            "A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'."
        );
    }

    return $this->skip(function()
        {
            return file_exists($this->mutexPath());
        });
}

protected function mutexPath()
{
    return storage_path().'/framework/schedule-'.md5($this->description);
}

存储/framework
中删除文件
计划-*
解决了问题。

即使我遇到了这个问题,也没有一个合适的解决方案,但是一个变通方法可以解决这个问题

转到项目的存储/框架文件夹,删除所有
计划-*********
文件

然后再次尝试运行cron。即使使用
而不使用overlapping()函数
,它也会出现错误


希望这对你有用。问我们这周是否有任何疑问,我们认为我们找到了原因。我们的cron运行在生产服务器的一个站点文件夹中。我们的部署过程包括在第二个文件夹中进行部署/构建,然后在最后进行热文件夹交换。由于withoutOverlapping()可能必须在进程完成时更新schedule-*文件中的一行,因此文件夹可能会在作业中被交换,并且cron无法成功地将作业标记为已在正确的schedule-*文件中完成,因此它认为它仍在运行/卡住


这是一种罕见的情况,但我们将在部署后添加一个命令来清除这些文件,这样就不会再发生这种情况了。

对于阅读本文的任何人来说,自己删除计划文件不是正确的方法。您需要指定-锁定时间-基于此,如果没有重叠,将阻止进一步的任务运行

引用于

如果需要,您可以指定在“无重叠”锁定过期之前必须经过多少分钟。默认情况下,锁将在24小时后过期:

您的问题源于withoutOverlapping在24小时内应用默认锁这一事实。因此,在接受类似任务之前,您必须等待24小时。只需根据您的需要通过以下操作调整锁定时间:

$schedule->command('emails:send')->不重叠(10);//其中10表示分钟


这对我来说是个好办法:

php artisan cache:clear

我已经用完全相同的答案回答了我自己的问题。谢谢你,哦,sry。。事实上,我很高兴能与大家分享我的解决方案,我甚至没有读到另一个答案。请注意,锁存储在您选择的缓存中。在我的例子中,我们使用的是redis。我必须在redis中找到/删除密钥。来源:我认为到期时间现在是秒,而不是分钟:如果它确实在框架的另一层中发生了更改,那么它似乎不是秒,这意味着他们还必须更改此函数中的expiresAt默认值,仍然是1440(1440分钟=24小时)。哦,你说得对。谢谢你的调查。看起来他们在幕后将其从分钟转换为秒: