-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Lock] Add namespace support to Redis & Memcache lock stores #60227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 7.4
Are you sure you want to change the base?
Changes from 1 commit
e674445
08fa69b
c186d5e
788c1c1
b4e39e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,19 +32,32 @@ class RedisStore implements SharedLockStoreInterface | |
use ExpiringStoreTrait; | ||
|
||
private const NO_SCRIPT_ERROR_MESSAGE_PREFIX = 'NOSCRIPT'; | ||
/** | ||
* @internal | ||
*/ | ||
WaylandAce marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private const NS_SEPARATOR = ':'; | ||
|
||
private bool $supportTime; | ||
|
||
private string $namespace = ''; | ||
|
||
/** | ||
* @param float $initialTtl The expiration delay of locks in seconds | ||
* @param array $options See below | ||
* | ||
* Options: | ||
* namespace: Prefix used for keys | ||
*/ | ||
public function __construct( | ||
private \Redis|Relay|RelayCluster|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, | ||
private float $initialTtl = 300.0, | ||
private array $options = [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why use an array of options rather than give the namespace directly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to use namespace parameter directly, but I tried to keep style similar to other stores (DoctrineDbalStore, MongoDbStore, PdoStore, PostgreSqlStore) |
||
) { | ||
if ($initialTtl <= 0) { | ||
throw new InvalidTtlException(\sprintf('"%s()" expects a strictly positive TTL. Got %d.', __METHOD__, $initialTtl)); | ||
} | ||
|
||
$this->namespace = isset($this->options['namespace']) ? $this->options['namespace'] . static::NS_SEPARATOR : ''; | ||
} | ||
|
||
public function save(Key $key): void | ||
|
@@ -85,7 +98,7 @@ public function save(Key $key): void | |
'; | ||
|
||
$key->reduceLifetime($this->initialTtl); | ||
if (!$this->evaluate($script, (string) $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($this->initialTtl * 1000)])) { | ||
if (!$this->evaluate($script, $this->namespace . $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($this->initialTtl * 1000)])) { | ||
throw new LockConflictedException(); | ||
} | ||
|
||
|
@@ -125,7 +138,7 @@ public function saveRead(Key $key): void | |
'; | ||
|
||
$key->reduceLifetime($this->initialTtl); | ||
if (!$this->evaluate($script, (string) $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($this->initialTtl * 1000)])) { | ||
if (!$this->evaluate($script, $this->namespace . $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($this->initialTtl * 1000)])) { | ||
throw new LockConflictedException(); | ||
} | ||
|
||
|
@@ -165,7 +178,7 @@ public function putOffExpiration(Key $key, float $ttl): void | |
'; | ||
|
||
$key->reduceLifetime($ttl); | ||
if (!$this->evaluate($script, (string) $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($ttl * 1000)])) { | ||
if (!$this->evaluate($script, $this->namespace . $key, [microtime(true), $this->getUniqueToken($key), (int) ceil($ttl * 1000)])) { | ||
throw new LockConflictedException(); | ||
} | ||
|
||
|
@@ -199,7 +212,7 @@ public function delete(Key $key): void | |
return true | ||
'; | ||
|
||
$this->evaluate($script, (string) $key, [$this->getUniqueToken($key)]); | ||
$this->evaluate($script, $this->namespace . $key, [$this->getUniqueToken($key)]); | ||
} | ||
|
||
public function exists(Key $key): bool | ||
|
@@ -225,7 +238,7 @@ public function exists(Key $key): bool | |
return false | ||
'; | ||
|
||
return (bool) $this->evaluate($script, (string) $key, [microtime(true), $this->getUniqueToken($key)]); | ||
return (bool) $this->evaluate($script, $this->namespace . $key, [microtime(true), $this->getUniqueToken($key)]); | ||
} | ||
|
||
private function evaluate(string $script, string $resource, array $args): mixed | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,9 +69,21 @@ public static function createStore(#[\SensitiveParameter] object|string $connect | |
throw new InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".'); | ||
} | ||
$storeClass = str_starts_with($connection, 'memcached:') ? MemcachedStore::class : RedisStore::class; | ||
|
||
$matches = []; | ||
$namespace = ''; | ||
if (preg_match('/^(.*[\?&])namespace=([^&#]*)&?(([^#]*).*)$/', $connection, $matches)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can't we use parse_url instead of this logic? also, don't we need something similar on MemcachedStore? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's general to both stores (StoreFactory class). |
||
$prefix = $matches[1]; | ||
$namespace = $matches[2]; | ||
if (empty($matches[4])) { | ||
$prefix = substr($prefix, 0, -1); | ||
} | ||
$connection = $prefix.$matches[3]; | ||
} | ||
|
||
$connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); | ||
|
||
return new $storeClass($connection); | ||
return new $storeClass($connection, ['namespace' => $namespace]); | ||
|
||
case str_starts_with($connection, 'mongodb'): | ||
return new MongoDbStore($connection); | ||
|
Uh oh!
There was an error while loading. Please reload this page.