Laravel Atomic Locks

Atomic locks allow for the manipulation of distributed locks without worrying about race conditions. For example, Laravel Forge uses atomic locks to ensure that only one remote task is being executed on a server at a time. You may create and manage locks using the Cache::lock method:

if (Cache::lock('foo', 10)->get()) {
    // Lock acquired for 10 seconds...

    Cache::lock('foo')->release();
}

Cache::lock('foo')->get(function () {
    // Lock acquired indefinitely and automatically released...
});

ふー、一日間開けるとあかんわ。
If the lock is not available at the moment you request it, you may instruct Laravel to wait for a specified number of seconds. If the lock can not be acquired within the specified time limit, an Illuminate\Contracts\Cache\LockTimeoutException will be thrown:

The Cache Helper
In addition to using the Cache facade or cache contract, you may also use the global cache function to retrieve and store data via the cache. When the cache function is called with a single, string argument, it will return the value of the given key:

$value = cache('key');
cache(['key' => 'value'], $minutes);

cache(['key' => 'value'], now()->addSeconds(10));

Storing Tagged Cache Items
Cache tags allow you to tag related items in the cache and then flush all cached values that have been assigned a given tag. You may access a tagged cache by passing in an ordered array of tag names. For example, let’s access a tagged cache and put value in the cache:

Cache::tags(['people', 'artists'])->put('John', $john, $minutes);
Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);

Removing Tagged Cache Items
You may flush all items that are assigned a tag or list of tags. For example, this statement would remove all caches tagged with either people, authors, or both. So, both Anne and John would be removed from the cache:

Cache::tags([‘people’, ‘authors’])->flush();
In contrast, this statement would remove only caches tagged with authors, so Anne would be removed, but not John:

Cache::tags(‘authors’)->flush();
Adding Custom Cache Drivers
Writing The Driver
To create our custom cache driver, we first need to implement the Illuminate\Contracts\Cache\Store contract. So, a MongoDB cache implementation would look something like this:

namespace App\Extensions;

use Illuminate\Contracts\Cache\Store;

class MongoStore implements Store
{
public function get($key) {}
public function many(array $keys);
public function put($key, $value, $minutes) {}
public function putMany(array $values, $minutes);
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function forget($key) {}
public function flush() {}
public function getPrefix() {}
}
We just need to implement each of these methods using a MongoDB connection. For an example of how to implement each of these methods, take a look at the Illuminate\Cache\MemcachedStore in the framework source code. Once our implementation is complete, we can finish our custom driver registration.

Cache::extend(‘mongo’, function ($app) {
return Cache::repository(new MongoStore);
});

protected $listen = [
    'Illuminate\Cache\Events\CacheHit' => [
        'App\Listeners\LogCacheHit',
    ],

    'Illuminate\Cache\Events\CacheMissed' => [
        'App\Listeners\LogCacheMissed',
    ],

    'Illuminate\Cache\Events\KeyForgotten' => [
        'App\Listeners\LogKeyForgotten',
    ],

    'Illuminate\Cache\Events\KeyWritten' => [
        'App\Listeners\LogKeyWritten',
    ],
];