public function withoutOverlapping()
{
$this->withoutOverlapping = true;
return $this->then(function () {
$this->mutex->forget($this);
})->skip(function () {
return $this->mutex->exists($this);
});
}
Laravel创建了一个过滤回调方法来告诉计划管理器忽略互斥锁仍然存在的任务,同时也创建了一个在完成任务实例后清除互斥锁的回调。同时,在执行任务之前,Lravel会在Console\Scheduling\Event::run()
方法中依次执行下面一系列的检查:
if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; }
那么互斥锁的属性是从哪里来的呢?
当Console\Scheduling\Schedule
被实例化的时候,Laravel会检查Console\Scheduling\Mutex
是否绑定到了容器,如果是那么就会实例化它,否则会使用Console\Scheduling\CacheMutex
$this->mutex = $container->bound(Mutex::class) ? $container->make(Mutex::class) : $container->make(CacheMutex::class);
现在当任务管理器在注册事件的时候会将互斥锁的实例一并传进去:
$this->events[] = new Event($this->mutex, $command);
Laravel默认使用了缓存实现的互斥锁,但是你可以自己实现并替换它。
CacheMutex类只有3个简单的方法,它使用了事件互斥锁的名字作为缓存的键值:
public function create(Event $event) { return $this->cache->add($event->mutexName(), true, 1440); } public function exists(Event $event) { return $this->cache->has($event->mutexName()); } public function forget(Event $event) { $this->cache->forget($event->mutexName()); }
就像我们之前看过的,管理器注册了一个执行后回调来保证任务执行完毕的时候移除互斥锁,对于一个系统里的命令来说也许已经可以确保移除了。但是对于一个回调方法的任务来说脚本可能在执行回调的时候结束,因此为了避免这种情况在Console\Scheduling\CallbackEvent::run()
方法中加入了下面的代码确保互斥锁在任务意外关闭的时候能够正常移除:
register_shutdown_function(function () { $this->removeMutex(); });
更多Laravel相关技术文章,请访问Laravel教程栏目进行学习!