diff --git a/src/Illuminate/Cache/CacheManager.php b/src/Illuminate/Cache/CacheManager.php index 2df3fa42ff6f..c34a92c5c853 100755 --- a/src/Illuminate/Cache/CacheManager.php +++ b/src/Illuminate/Cache/CacheManager.php @@ -369,7 +369,7 @@ protected function getSession() */ public function repository(Store $store, array $config = []) { - return tap(new Repository($store, Arr::only($config, ['store'])), function ($repository) use ($config) { + return tap(new Repository($store, Arr::only($config, ['store', 'flexible_cluster_mode'])), function ($repository) use ($config) { if ($config['events'] ?? true) { $this->setEventDispatcher($repository); } diff --git a/src/Illuminate/Cache/Repository.php b/src/Illuminate/Cache/Repository.php index 880ed23f776c..1bb9cde0972d 100755 --- a/src/Illuminate/Cache/Repository.php +++ b/src/Illuminate/Cache/Repository.php @@ -488,36 +488,65 @@ public function rememberForever($key, Closure $callback) */ public function flexible($key, $ttl, $callback, $lock = null, $alwaysDefer = false) { - [ - $key => $value, - "illuminate:cache:flexible:created:{$key}" => $created, - ] = $this->many([$key, "illuminate:cache:flexible:created:{$key}"]); + $createdKey = "illuminate:cache:flexible:created:{$key}"; + $lockKey = "illuminate:cache:flexible:lock:{$key}"; - if (in_array(null, [$value, $created], true)) { - return tap(value($callback), fn ($value) => $this->putMany([ + // Check if sequential mode is enabled (for Redis Cluster compatibility) + $useSequential = $this->config['flexible_cluster_mode'] ?? false; + + if ($useSequential) { + // Sequential operations for Redis Cluster compatibility + $value = $this->get($key); + $created = $this->get($createdKey); + } else { + // Bulk operations (default behavior) + [ $key => $value, - "illuminate:cache:flexible:created:{$key}" => Carbon::now()->getTimestamp(), - ], $ttl[1])); + $createdKey => $created, + ] = $this->many([$key, $createdKey]); + } + + if (in_array(null, [$value, $created], true)) { + $newValue = value($callback); + + if ($useSequential) { + $this->put($key, $newValue, $ttl[1]); + $this->put($createdKey, Carbon::now()->getTimestamp(), $ttl[1]); + } else { + $this->putMany([ + $key => $newValue, + $createdKey => Carbon::now()->getTimestamp(), + ], $ttl[1]); + } + + return $newValue; } if (($created + $this->getSeconds($ttl[0])) > Carbon::now()->getTimestamp()) { return $value; } - $refresh = function () use ($key, $ttl, $callback, $lock, $created) { + $refresh = function () use ($key, $createdKey, $lockKey, $ttl, $callback, $lock, $created, $useSequential) { $this->store->lock( - "illuminate:cache:flexible:lock:{$key}", + $lockKey, $lock['seconds'] ?? 0, $lock['owner'] ?? null, - )->get(function () use ($key, $callback, $created, $ttl) { - if ($created !== $this->get("illuminate:cache:flexible:created:{$key}")) { + )->get(function () use ($key, $createdKey, $callback, $created, $ttl, $useSequential) { + if ($created !== $this->get($createdKey)) { return; } - $this->putMany([ - $key => value($callback), - "illuminate:cache:flexible:created:{$key}" => Carbon::now()->getTimestamp(), - ], $ttl[1]); + $newValue = value($callback); + + if ($useSequential) { + $this->put($key, $newValue, $ttl[1]); + $this->put($createdKey, Carbon::now()->getTimestamp(), $ttl[1]); + } else { + $this->putMany([ + $key => $newValue, + $createdKey => Carbon::now()->getTimestamp(), + ], $ttl[1]); + } }); };