This commit adds conditional support for simdjson based JSON
deserialization.
To enable compile with `--enable-redis-simdjson` and PhpRedis will
attempt to find and link with the `simdjson` shared library. The feature
likely requires simdjson >= `4.0.0` and was tested with `4.3.1`.
Enabling is just like other serializers:
```php
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_SIMDJSON);
$redis->set('foo', ['bar' => 'baz']);
print_r($redis->get('foo'));
```
Initial tests do show aa huge performance improvement in deserializing
json payloads (2-3.5x depending on the payloads themselves).
Add support for Redis' `DELEX` and Valkey's `DELIFEQ` when deleting the
session lock key. Local testing shows about a 10-15% improvement over
the current `EVAL[SHA]` strategy.
This commit adds a new INI settingg:
```ini
redis.session.lock_release_cmd = delex|delifeq|eval
```
By default we continue to use the `EVAL` logic and if a user specifies
another mechanism but the command doesn't exist, we warn the user and
fall back to EVAL.
This commit also refactors a few functions to avoid UB and simplify key
construction.
The stub declares $seeds as ?array but the C code used format
specifier 'a' (non-nullable) instead of 'a!' in
zend_parse_method_parameters. This caused new RedisCluster(null, null)
to throw TypeError instead of RedisClusterException, contradicting
the declared type signature.
Also treat z_seeds == NULL the same as ZEND_NUM_ARGS() < 2 so that
explicitly passing null falls through to INI-based seed loading,
matching the behaviour when the argument is omitted entirely.
Fixes GH-2810.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of currying around a `php_stream_context` object, just retain
the context array provided by the user itself like we do with other
connection information like host and port. This lets users reconnect in
a loop without leaking memory.
```php
$redis = new \Redis;
while (true) {
// Previously each reconnect call would leak the
// `php_stream_context` structure.
$redis->connect('tls://127.0.0.1', 9999, 1, null, 0, 0, [
'stream' => ['verify_peer' => false, 'verify_peer_name' => false],
]);
$redis->ping();
$redis->close();
}
```
We had a `delExType` enum which was later made redundant by
`redisEqType` as they have the same semantics.
This commit just removes `delExType` and uses the new enum.
In `array_zip_values_and_scores` we were blindly calling `Z_STR_P` on
the `zval` assuming it must be a string.
This isn't the case however if the user did something like this:
```php
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$redis->zAdd('zs', 3.14, ['pi', 'is', 'cool']);
// segfault when we try to get `Z_STR_P` from `['pi', 'is', 'cool']`
$redis->zRange('zs', 0, -1, true);
```
Potential fix for #2791
Technically `INFO` can return false in the event of a protocol error or
similar. If that happens the tests are unlikely to be useful but we
should at least account for it to avoid an immediate fatal error when
calling helpers like `detectKeyDB` and `detectValkey`.
See #2783
* Implement the new `MSETEX` Redis command.
* Refactor parsing of extended `SET` arguments into unified helper
functions, deduplicating logic.
* Add new `SET` arguments `IFNE`, `IFDEQ`, and `IFDNE`. We already
support Valkey's existing `IFEQ` argument, which Redis has added.
Fixes#2742
When a persistent ID is not provided, we were generating a "unique" one
by constructing a string with the current seconds and microseconds.
If two connections are createed in rapid succession, they can both
generate the same `persistent_id` and therefore both use the same
underlying `php_stream`.
```php
$r1 = new Redis;
$r2 = new Redis;
// If the two of these execute on the same second and usec, they will both use
// the same persistent_id and therefore the same underlying socket.
$r1->pconnect('localhost', 6379);
$r2->pconnect('localhost', 6379);
// Close and free the first connection
$r1->close();
// Segfault. Closing an already closed stream
$r2->close();
```
This commit simply adds a function scoped static monotonically
incremented counter which is used to make the persistent id's truly unique.
Fixes#2762
It turns out `doctum` will only hyperlink to the Redis methods when the
method casing is identical. For that reason, just match the casing in
`redis_cluster.stub.php` to how it's cased in `redis.stub.php`.
We aren't changing any of the non-commented stub text, just the casing of the
`@see` annotations.
WIP: More
.