diff --git a/src/Store.php b/src/Store.php index 6099c55..f7f2cb1 100644 --- a/src/Store.php +++ b/src/Store.php @@ -2,14 +2,16 @@ namespace ElcoBvg\Opcache; +use Illuminate\Cache\FileLock; use Illuminate\Support\Str; use Illuminate\Cache\TagSet; use Illuminate\Cache\TaggableStore; use Illuminate\Support\Facades\Log; use Illuminate\Contracts\Cache\Store as StoreContract; use Illuminate\Cache\RetrievesMultipleKeys; +use Illuminate\Contracts\Cache\LockProvider; -class Store extends TaggableStore implements StoreContract +class Store extends TaggableStore implements StoreContract, LockProvider { use RetrievesMultipleKeys; @@ -41,6 +43,13 @@ class Store extends TaggableStore implements StoreContract */ protected $enabled = false; + /** + * The file cache lock directory. + * + * @var string|null + */ + protected $lockDirectory; + /** * Create a new OPcache store. * @@ -63,7 +72,7 @@ public function __construct(string $prefix = '', string $directory = '') */ $this->directory = $directory ?: config('cache.stores.opcache.path', config('cache.stores.file.path')); } - + /** * Begin executing a new tags operation. * @@ -401,4 +410,50 @@ public function extendExpiration(string $key, int $seconds = 1) } return false; } + + /** + * Get a lock instance. + * + * @param string $name + * @param int $seconds + * @param string|null $owner + * @return \Illuminate\Contracts\Cache\Lock + */ + public function lock($name, $seconds = 0, $owner = null) + { + $directory = $this->lockDirectory ?? $this->directory; + $this->checkDirectory($directory); + + return new FileLock( + new static($this->prefix, $directory), + $name, + $seconds, + $owner + ); + } + + /** + * Restore a lock instance using the owner identifier. + * + * @param string $name + * @param string $owner + * @return \Illuminate\Contracts\Cache\Lock + */ + public function restoreLock($name, $owner) + { + return $this->lock($name, 0, $owner); + } + + /** + * Set the cache directory where locks should be stored. + * + * @param string|null $lockDirectory + * @return $this + */ + public function setLockDirectory($lockDirectory) + { + $this->lockDirectory = $lockDirectory; + + return $this; + } } diff --git a/tests/OpcacheDriverTest.php b/tests/OpcacheDriverTest.php index b479dc0..394ff43 100644 --- a/tests/OpcacheDriverTest.php +++ b/tests/OpcacheDriverTest.php @@ -195,6 +195,42 @@ public function testStoreRememberFromCache() $this->testStoreRemember(); } + public function testStoreLock() + { + $store = $this->getStore(); + $lock = $store->lock('test-lock', 10); + + $this->assertInstanceOf(\Illuminate\Cache\FileLock::class, $lock); + $this->assertTrue($lock->acquire()); + $this->assertTrue($lock->release()); + } + + public function testStoreRestoreLock() + { + $store = $this->getStore(); + $lock = $store->lock('test-lock', 10); + + $owner = $lock->owner(); + $this->assertTrue($lock->acquire()); + + $restoredLock = $store->restoreLock('test-lock', $owner); + $this->assertInstanceOf(\Illuminate\Cache\FileLock::class, $restoredLock); + $this->assertTrue($restoredLock->release()); + } + + public function testStoreLockDirectory() + { + $store = $this->getStore(); + $customLockPath = sys_get_temp_dir() . '/opcache-locks'; + + $store->setLockDirectory($customLockPath); + $lock = $store->lock('test-lock', 10); + + $this->assertTrue($lock->acquire()); + $this->assertTrue(file_exists($customLockPath)); + $this->assertTrue($lock->release()); + } + protected function getStore() { return new Store('opcache', sys_get_temp_dir());