Home > PHP Framework > Laravel > How Laravel prevents your scheduled tasks from being executed repeatedly

How Laravel prevents your scheduled tasks from being executed repeatedly

步履不停
Release: 2019-07-03 17:56:57
Original
3393 people have browsed it

How Laravel prevents your scheduled tasks from being executed repeatedly

Basic introduction

Sometimes the execution of a scheduled task may take longer than we imagine, which will cause a problem——Currently Before the task is completed, another identical task will be executed, resulting in task duplication. For example, imagine that we execute a task that generates a report every minute. After a period of time, the amount of data becomes large and the execution time exceeds 1 minute. This will cause another task to be generated before the previous task is completed. The same task starts executing.

Solution

In most cases there is no problem, but sometimes we need to avoid this situation to ensure correct data. In Laravel we can handle it through the withoutOverlapping method:

$schedule->command('mail:send')->withoutOverlapping();
Copy after login

Laravel will check the Console\Scheduling\Event::withoutOverlapping attribute, if the value is true then A mutex will be created for this task, and the task will only be executed if the mutex can be created.

What is a mutex lock?

This is the funniest explanation I've found online:

When we're in a meeting and having a heated discussion, I pull out a Screaming Chicken from my desk. Only the person holding the Screaming Chicken can speak, if you are not holding the Screaming Chicken you cannot speak. You can only ask the meeting host for instructions, and you can only speak when you get the Screaming Chicken, otherwise you can only wait. When you finish speaking, return the Screaming Chicken to the meeting host, who will give the Screaming Chicken to the next person to speak. This will ensure that people are not talking over each other but also that they will have their own time to speak.

Replace the screaming chicken with a mutex lock and the person with a thread. You basically have the basic concept of a mutex.

-- https://stackoverflow.com/questions/34524/...

Principle Analysis

Laravel performs tasks for the first time A mutex lock will be created, and then every time a task is executed, it will be checked to see if the mutex lock exists. The task will only be executed when the mutex lock does not exist. Here is the withoutOverlapping method:

public function withoutOverlapping()
{
    $this->withoutOverlapping = true;

    return $this->then(function () {
        $this->mutex->forget($this);
    })->skip(function () {
        return $this->mutex->exists($this);
    });
}
Copy after login

Laravel creates a filter callback method to tell the schedule manager to ignore tasks for which the mutex still exists, and also creates a method to clean up after completing the task instance. Mutex callback. At the same time, before executing the task, Lravel will perform the following series of checks in the Console\Scheduling\Event::run() method:

if ($this->withoutOverlapping && ! $this->mutex->create($this)) {
    return;
}
Copy after login

Then the properties of the mutex are Where did it come from?

When Console\Scheduling\Schedule is instantiated, Laravel will check whether Console\Scheduling\Mutex is bound to the container, and if so, it will be instantiated Change it, otherwise it will use Console\Scheduling\CacheMutex

$this->mutex = $container->bound(Mutex::class)
                        ? $container->make(Mutex::class)
                        : $container->make(CacheMutex::class);
Copy after login

Now when the task manager registers the event, it will pass the mutex instance together:

$this->events[] = new Event($this->mutex, $command);
Copy after login

Laravel uses a cache-implemented mutex by default, but you can implement and replace it yourself.

Cache version of mutex

The CacheMutex class has only 3 simple methods, which uses the name of the event mutex as the cache key:

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());
}
Copy after login

Just As we have seen before, the manager registers a post-execution callback to ensure that the mutex is removed when the task is completed, which may already be guaranteed for a command in the system. However, for a callback method task, the script may end when the callback is executed. Therefore, in order to avoid this situation, the following code is added to the Console\Scheduling\CallbackEvent::run() method to ensure interaction. The repulsion lock can be removed normally when the task is closed unexpectedly:

register_shutdown_function(function () {
    $this->removeMutex();
});
Copy after login

For more Laravel related technical articles, please visit the Laravel Tutorial column to learn!

The above is the detailed content of How Laravel prevents your scheduled tasks from being executed repeatedly. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template