[13.x] Laravel Framework: Implement CanFlushLocks on NullStore and MemoizedStore
@sumaiazaman merged PR #59850 into laravel/framework for the 13.x branch, implementing the CanFlushLocks interface on NullStore and MemoizedStore.
The Gap
After #59738 added CanFlushLocks to FailoverStore, every major cache lock provider implemented both LockProvider and CanFlushLocks except two. NullStore and MemoizedStore both implemented LockProvider but were missing CanFlushLocks, which meant Cache::supportsFlushingLocks() returned false for those stores even though the other five (Redis, File, Array, Database, Failover) all returned true.
| Store | Before | After |
|---|---|---|
NullStore |
LockProvider only |
LockProvider, CanFlushLocks |
MemoizedStore |
LockProvider only |
LockProvider, CanFlushLocks |
NullStore: A Stateless No-Op
NullStore uses NoLock internally, which never persists anything. There is nothing to flush, so flushLocks() simply returns true and hasSeparateLockStore() returns false.
// NullStore now satisfies CanFlushLocks
$store = Cache::store('null');
$store->flushLocks(); // returns true, no-op
$store->hasSeparateLockStore(); // returns false
MemoizedStore: Delegates to the Underlying Store
MemoizedStore wraps another store, so its CanFlushLocks implementation passes the call through. If the underlying store implements CanFlushLocks, flushLocks() delegates to it. If it does not, a BadMethodCallException is thrown, consistent with how lock() and restoreLock() already handle unsupported underlying stores.
// Underlying store supports flushing locks
$store = Cache::store('memoized'); // backed by Redis, Array, etc.
$store->flushLocks(); // delegates to the underlying store
$store->hasSeparateLockStore(); // delegates to the underlying store
// Underlying store does not support CanFlushLocks
$store->flushLocks(); // throws BadMethodCallException
Test Coverage
@sumaiazaman added five new tests covering both stores:
CacheNullStoreTest::testLocksCanBeFlushedCacheNullStoreTest::testHasSeparateLockStoreCacheMemoizedStoreTest::testLocksCanBeFlushedWhenUnderlyingStoreSupportsItCacheMemoizedStoreTest::testFlushLocksThrowsWhenUnderlyingStoreDoesNotSupportItCacheMemoizedStoreTest::testHasSeparateLockStoreDelegatestoUnderlyingStore
Anyone writing code that calls Cache::supportsFlushingLocks() and branching on the result can now rely on consistent behavior across all built-in cache stores, including null and memoized configurations.