It seems like Redis changed what it will do when you send a negative
number of events. Previously this would just return an error but it
seems to return `1` now.
For this reason just remove that assertion so we don't have to use
different logic depending on the version of the server.
Unfortunately `VEMB` has a unique `RESP2` reply as far as I can tell,
where it sends the embedding mode (int8, bin, fp32) as a simple string.
This would cause any of PhpRedis' generic reply handlers to turn that
into `true` which isn't useful. For that reason we need a custom reply
handler.
Additionally slightly rework `VINFO` to short circuit and return failure
if we read anything other than a bulk string or an integer reply type.
Otherwise we may get out of sync on the socket.
See #2543
Valkey 9.0.0 implemented a new variant of `GEOSEARCH` where you supply
the verticies to an arbitrary polygon.
Since we can't modify the `geosearch` prototype using it is a little
wonky (you need to just pass empty strings for position and unit).
```php
$redis->geosearch('ca:cities', '', [
-121.90, 39.65, -121.77, 39.65, -121.77, 39.80, -121.90, 39.80
], '');
$redis->geosearchstore('ca:cities', 'dst', '', [
-121.90, 39.65, -121.77, 39.65, -121.77, 39.80, -121.90, 39.80
], '');
```
* Rework `HEXPIRE` test inclusion + bump Valkey
* Add a little `haveCommand` helper which uses `COMMAND INFO` to check
if a given server has a specific command. This way when we bump valkey
to an official release that supports the commands we will start
testing.
* Bump Valkey from 7.2.5 to 8.1.3 which is much newer.
* Rework `haveCommand` to explicitly check for the command name
COMMAND INFO will return the command name as one of the first bits of
data so we can check for it that way.
* Fix incorrect logic
* We can make the code simpler by using `zend_empty_array` when no args
are passed as well as the new argument parsing macros and newer internal
redis command appending functions that take zend strings.
* Add a regression test for when we execute `EVAL[SHA]` with arguments
but do not send any keys. This was causing UB in RedisCluster (#2681).
This command is similar to `VADD` in that it's pretty simple but allows
for a great many options.
In it's most basic form:
```php
// To get similarity of a different element
$redis->vsim('myvec', 'some-element');
// To get similarity for a vector of scores
```
As seen above the method attempts to infer element or vector from the
argument passed to $member`. However, since we do serialize the member
when doing `ELE` mode, the user can also specify `ELE` explicitly in the
options array to force an `ELE` search sending serialized values.
```php
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$redis->vsim('myvec', [3.14, 2.71], ['ELE']);
```
See #2543
This is for Redis 8.0's vector sets.
The command itself can be quite complex with all of the various options but
pretty simple using all defaults.
```php
$redis->vadd('myvec', [3.14, 2.17], 'myelement');
```
The implementation takes a default argument `$options` which can be an array in
order to specify the myriad of other knobs users can send. We just do a bit of
validation on inputs (e.g. certain numeric options must be positive) and make
sure the command is constructed in a valid way (e.g. REDUCE <dim> must come
before the floating point values).
By default we deliver `FP32` blobs but allow the user to send `VALUES` in the
options array which will cause PhpRedis to send N individual values. Sending
values is slower but might be nice for debugging (e.g. watching monitor)
See #2543
The current echo liveness check was doing one big complex conditional
trying to incorporate both sentinel's expected ERR no such command
response and non-sentinel's actual bulk reply to ECHO.
This commit refactors the logic to check the echo response into a little
helper with different logic depending on whether or not we're connected
to a sentinel.
Additionally, we add a test to verify that we are in fact reusing
persistent connections when the user requests a persistent connection
with `RedisSentinel`.
Fixes#2148
* Rework HMGET and implement HGETEX
Instead of using a bespoke NULL terminated `zval**` array for the
context array we can use a `HashTable`. This might be a tiny bit more
expensive but Zend hashtables are quite efficient and this should also
be less error prone.
* Rework our `HashTable` context array to store keys
Instead of sending an array of values we can instead add the fields as
keys to our context array. That way when we combine the keys with the
Redis provided values we can do it in-place and then just give the
HashTable to the user to then do with what they want.
* Implement HGETDEL command.
* Fix edge cases to abide by legacy behavior.
Previously we coerced integer strings into integer keys when zipping
`HMGET` responses. This commit adds logic so we continue to do this and
do not change semantics.
* Implement `HGETDEL` and `HGETEX` for `RedisCluster`.
This commit implements the new commands and reworks the `HMGET` reply
handler to use the new context `HashTable`.
* Fix an edge case where we get zero multiblk elements
* Tests for `HGETEX` and `HGETDEL`
* Minor logic improvement
We don't need to check if `c->reply_len > 0` in the last else block
since we have already determined it must be.
* Implement `HSETEX` for `Redis` and `RedisCluster`
* Use `zval_get_tmp_string` ro populating non-long keys
We often have to rerun the test suite on GitHub actions because of a
hard to reproduce "Read error on connection" exception when getting a
new `RedisCluster` instance.
No one has ever reported this failure outside of GitHub CI and it's not
clear exactly what might be going on.
This commit does two main things:
1. Allows for one failure to construct a new `RedisCluster` instance but
only if we detect we're running in GitHub CI.
2. Adds much more diagnostic information if we still have a fatal error
(e.g. we can't connect in two tries, or some other fatal error
happens). The new info includes the whole callstack before aborting
as well as an attempt to manually ping the seeds with `redis-cli`.
DragonflyDB will report to be Redis but also include `dragonfly_version`
in the hello response, which we can use to identify the fork.
Also fix parsing of the `HELLO` response for `serverName()` and
`serverVersion()`. Starting in Redis 8.0 there seem to always be modules
running, which the previous function was not expecting or parsing.
* New option 'database' for Redis class constructor
Selecting database is very common action after connecting to Redis. This simplifies lazy connecting to Redis, when requested database will be selected after first command.
* More specific exception message when invalid auth or database number is provided
Before it was just 'Redis server went away'
* Rename reselect_db method to redis_select_db and slightly optimise it
Adds an option that instructs PhpRedis to not serialize or compress
numeric values. Specifically where `Z_TYPE_P(z) == IS_LONG` or
`Z_TYPE_P(z) == IS_DOUBLE`.
This flag lets the user enable serialization and/or compression while
still using the various increment/decrement command (`INCR`, `INCRBY`,
`DECR`, `DECRBY`, `INCRBYFLOAT`, `HINCRBY`, and `HINCRBYFLOAT`).
Because PhpRedis can't be certain that this option was enabled when
writing keys, there is a small runtime cost on the read-side that tests
whether or not the value its reading is a pure integer or floating point
value.
See #23
Redis requires the user to send a count if `WITHVALUES` is specified,
otherwise it sees the `WITHVALUES` argument as the count and will error
out that it's not a number.
We can also return false if the key doesn't exist.
* Remove/update mentions of removed methods
These methods were deprecated in a previous release
* Correct documentation for zInter/zinterstore
* Correct documentation for zUnion/zunionstore
* Add documentation for zDiff/zdiffstore
* Add documentation for zMscore
* Adds `GETEX` to the README.md documentation.
* Allow the user to send `PERSIST` either as an array key or just in the
array, to conform with similar methods.
* Implement getEx for `RedisCluster`
Fixes#2512
* More unit test utility functions/usage.
* Add `assertKeyEquals` and `assertKeyEqualsWeak` as we test key values
hundreds of places in `RedisTest.php`
* We are almost always using `$this->redis` when we want to run an
assertion that needs access to the client, so make this argument
optional and default to `$this->redis`.
* Update a few more assertions to use our new methods.
* Various minor fixes/tweaks.
* Update RedisTest.php
typo
This probably isn't a very common scenerio since we've never had someone
ask it in a decade, but it was very simple to get them working.
Primarily we just needed to test for `STDTOUT`/`STDERR` and use
`__DIR__` instead of `$_SERVER['PHP_SELF']`.
Fixes#2507