Compare commits

..

107 Commits

Author SHA1 Message Date
vladvildanov a5bb1b362e Updated CHANGELOG.md 2026-06-05 14:23:58 +03:00
vladvildanov 79ec4e3a6d Merge branch 'main' of github.com:predis/predis into vv-update-runners 2026-06-05 14:19:12 +03:00
vladvildanov e9b598c540 Update GH runners based on NodeJS <= 20 2026-06-05 14:15:12 +03:00
Till Krüss 8cc4319c06 Prepare 3.5.0 (#1682) 2026-06-02 12:25:56 -07:00
dependabot[bot] 84c77ea460 Bump the github-actions group with 5 updates (#1683) 2026-06-02 10:32:02 -07:00
Till Krüss 3da5d996bd move file 2026-06-02 10:20:38 -07:00
Till Krüss 5d1d9fdf11 Add dependabot configuration for GitHub Actions and Composer 2026-06-02 10:18:37 -07:00
Vladyslav Vildanov 135b405eae Added support for UNLINK command (#1680) 2026-06-02 09:28:57 -07:00
Vladyslav Vildanov 1611b33e4a Updated 8.8 GA test image (#1679) 2026-06-02 09:28:39 -07:00
Vladyslav Vildanov 37ed2dcd77 Updated INCREX arguments (#1677)
* Updated INCREX command arguments

* Updated test image

* Updated CHANGELOG.md

* Updated test image
2026-05-22 12:17:15 +03:00
Vladyslav Vildanov d6f91964e0 Added support for new array commands (#1672)
* Added support for new array commands

* Updated test image, fixed tests

* Updated CHANGELOG.md

* Removed ARLASTITEMS from ClusterStrategy testing

* Fixed broken tests

* Fixed broken test

* Updated 8.8-RC1 image

* Fixed Vector Set tests
2026-05-19 12:19:46 +03:00
Vladyslav Vildanov afc8035491 Revert GCRA command support (#1673)
* Revert GCRA command support

* Updated test image

* Fixed flacky test
2026-05-19 11:36:42 +03:00
Vladyslav Vildanov b2d1397fc6 Fixed SENTINEL SLAVES RESP3 incompatible response (#1676)
* Fixed SENTINEL SLAVES RESP3 incompatible response

* Updated CHANGELOG.md

* Revert relay-incompatible annotations
2026-05-14 09:56:32 +03:00
Vladyslav Vildanov f12e6694b5 Added support for INCREX command (#1674)
* Added support for INCREX command

* Fixed RESP2 and RESP3 incompatibility

* Removed non-printable characters

* Codestyle fixes
2026-05-13 11:11:07 +03:00
Vladyslav Vildanov 268449ae69 Added testing for subkey notification channels (#1671)
* Added testing for subkey notification channels

* Updated CHANGELOG.md

* Codestyle fixes

* Added test cleanup

* Added relay-incompatible label
2026-04-29 22:29:28 +03:00
Vladyslav Vildanov 52286f8164 Added support for multiple aggregators for TS range commands (#1670)
* Added support for multiple aggregators for TS range commands

* Updated CHANGELOG.md
2026-04-23 10:26:00 +03:00
Vladyslav Vildanov 6c3909e675 Added new COUNT aggregator for Sorted Set commands (#1668)
* Added test coverage with new COUNT aggregator

* Updated CHANGELOG.md

* Changed version constraint

* Fixed broken test

* Marked as relay-resp3
2026-04-22 10:47:00 +03:00
Vladyslav Vildanov 622f4df2b6 Added XNACK support (#1666)
* Renamed GCRA parameters to match latest API

* Added support for XNACK command

* Updated test image

* Updated test image

* Updated version requirements

* Fixed broken test

* Updated CHANGELOG.md

* Updated CHANGELOG.md
2026-04-22 10:30:57 +03:00
Vladyslav Vildanov ae4a706b01 Fixed Sentinel retry to narrow retryable exceptions to CommunicationException (#1665)
* Fixed Sentinel retry to narrow retryable exceptions to CommunicationException

* Update CHANGELOG.md
2026-04-20 10:10:15 +03:00
Vladyslav Vildanov 54bb300931 Updated arguments name for GCRA command (#1667)
* Renamed GCRA parameters to match latest API

* Updated test image

* Updated version requirements

* Fixed broken test

* Updated CHANGELOG.md
2026-04-20 10:09:34 +03:00
Vladyslav Vildanov 5024c7a662 Fixed ZRANGE to include 6.2 arguments (#1662)
* Fixed ZRANGE to include 6.2 arguments

* Removed duplicated arguments entry
2026-04-06 10:59:15 +03:00
Vladyslav Vildanov 3fc01fed58 Added FPHA argument for JSON.SET command (#1661) 2026-04-03 18:50:19 +09:00
messikiller 4c56d5d290 Fix SlotMap::offsetUnset() corrupting mappings when unsetting a slot in a gap (#1660) 2026-03-25 18:36:01 +09:00
Vladyslav Vildanov 7a4fa99d13 Added support for GCRA command (#1657)
* Added support for GCRA command

* Codestyle fixes

* Updated test image
2026-03-24 13:50:23 +02:00
Kevin Rojas bb37322a24 Handle -READONLY as a redirection signal for Redis Cluster (AWS ElastiCache support) (#1656)
* feature: Added support for READONLY responses from AWS Elastic Cache

* chore: improve -READONLY handler comment and add changelog entry (#1656)

* tests: add unit test demonstrating ServerException behavior with READONLY error
2026-03-23 09:00:26 +02:00
Copilot 1c4219cf88 Include command name in unsupported container command error messages (#1654)
Co-authored-by: tillkruss <665029+tillkruss@users.noreply.github.com>
2026-03-18 10:09:30 +09:00
Till Krüss 383623eb05 bump dev version 2026-03-09 13:34:39 -07:00
Till Krüss 2033429520 tag v3.4.2 2026-03-09 13:33:04 -07:00
Till Krüss 87390e7381 Use static closures (#1652) 2026-03-09 13:30:46 -07:00
Till Krüss f57dfcbeea Format changelog entry [skip ci] 2026-03-09 13:04:50 -07:00
Vasil Chomakov 7388d91153 Add upstream_driver option for CLIENT SETINFO upstream reporting (#1645)
* Add driver_info option for CLIENT SETINFO upstream reporting

* Use null default for upstreamDriver and ternary operator

* Remove redundant null initialization

* fix: remove trailing newline from VERSION file

* fix: update copyright year to 2026 in DriverInfo files

* refactor: rename driver_info to upstream_driver

* fix: code style issues

* docs: update CHANGELOG to reflect upstream_driver rename
2026-03-05 17:05:02 +02:00
Wolfgang Kerschbaumer d0f6671a60 Fix sentinel discovery methods not catching StreamInitException (#1650)
* Fix sentinel discovery methods not catching StreamInitException

The getMaster(), getSlaves(), and updateSentinels() methods only catch
ConnectionException when connecting to Sentinel nodes. StreamInitException
(thrown by stream_socket_client() failures) extends PredisException directly,
not ConnectionException, so it propagates uncaught — preventing fallback to
the next Sentinel node.

This causes complete application failure when any single Sentinel is
unreachable, even if other Sentinels are healthy.

Add StreamInitException to the catch clause using a union type in all three
methods. This is more precise than catching PredisException, which would
also swallow ServerException (e.g. "ERR No such master with that name")
and mask configuration errors.

See also #1577 which applied a similar fix to retryCommandOnFailure().

* Fix coding standards and add changelog entry

- Remove spaces around | in union catch (php-cs-fixer)
- Add CHANGELOG.md entry for #1650

* Codestlye fixes

---------

Co-authored-by: Wolfgang Kerschbaumer <wolfgang.kerschbaumer@bergfex.at>
Co-authored-by: vladvildanov <vladyslav.vildanov@redis.com>
2026-03-05 17:01:40 +02:00
Vladyslav Vildanov 274cb866bd Fixed Sentinel getParameters() executed on string configuration (#1649) 2026-02-26 11:01:54 -08:00
Till Krüss 0850f2f36e Prepare v3.4.1 release (#1647) 2026-02-23 11:51:21 -08:00
Till Krüss 581c5659bd update year in headers 2026-02-23 11:48:06 -08:00
predakanga 4a5be21d62 Make LMPOP and BLMPOP commands prefixable (#1646)
* Make LMPOP and BLMPOP commands prefixable

* Update CHANGELOG
2026-02-23 10:31:19 +02:00
Thomas Stägemann 7fd23dbcb9 Removed static from callables because it's deprecated since PHP 8.2 (#1642) 2026-02-20 11:05:12 +02:00
Amir Hossein Shokri dd0713b515 Fix typo (#1640) 2026-02-17 09:12:43 -08:00
Vladyslav Vildanov 4b527ba961 Make HTTL and HPTTL commands Prefixable (#1639) 2026-02-17 09:12:12 -08:00
Vladyslav Vildanov 6c9de258be Fixed getParameter() call on array + added integration testing with Sentinel (#1636)
* Fixed getParameter() call on array + added integration testing with Sentinel

* Added sentinel.conf

* Updated CHANGELOG.md

* Added handling of ParametersInterface
2026-02-13 11:30:43 +02:00
Till Krüss 1183f5732e fix changelog date 2026-02-11 09:30:28 -08:00
Till Krüss 83dbdbeb43 prepare v3.4.0 2026-02-11 09:28:17 -08:00
Denis 5d85628a11 Add normalizeVariadic to RPUSHX and LPUSHX commands (#1633)
* Add normalizeVariadic to RPUSHX and LPUSHX commands

RPUSHX and LPUSHX commands were missing the setArguments method
with normalizeVariadic call, unlike their RPUSH and LPUSH counterparts.
This caused errors when passing values as a single array argument
(e.g. $client->rpushx('key', ['val1', 'val2'])).

Fixes #1504

* Update CHANGELOG.md with RPUSHX/LPUSHX variadic fix (#1633)

* Fix variadic arguments normalization for [L|R]PUSHX

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2026-02-11 19:07:39 +02:00
Vladyslav Vildanov 8b9f882a43 Added testing with Redis 8.6 GA (#1634) 2026-02-11 09:00:42 -08:00
Vladyslav Vildanov e851ed6ceb Added support for idempotent stream API (#1632)
* Added augment commands support

* Added support for Redis 8.6

* Codestyle changes and test fixes

* Fixed hybdrid tests

* Updated CHANGELOG.md and composer.json

* Fixed XINFO tests

* Added support for idempontent stream API

* Update CHANGELOG.md

* Updated expected exported files

* Removed agentic files

* Removed .augment entry
2026-02-09 10:25:51 +02:00
Vladyslav Vildanov 861bde010a Added support for HOTKEYS container command (#1630)
* Added testing with SSL authentication using CN

* Update CHANGELOG.md

* Codestyle changes

* Fixed broken tests

* Fixed hybdrid tests

* Fixed SSL tests

* Fixed array merging

* Updated README.md

* Updated spelling list

* Added support for HOTKEYS container command

* Added ignoring for PHPUnit package

* Update CHANGELOG.md, codestyle fixes, mark tests as relay-incompatible

* Added RESP3 test, fixed response parsing

* Removed redundant tests

* Added cluster test

* Fix assertion
2026-02-05 10:48:48 +02:00
Vladyslav Vildanov 53504469d7 Added testing with TimeSeries NaN values (#1628)
* Added testing with SSL authentication using CN

* Update CHANGELOG.md

* Codestyle changes

* Fixed broken tests

* Fixed hybdrid tests

* Fixed SSL tests

* Fixed array merging

* Updated README.md

* Updated spelling list

* Added testing with TimeSeries NaN values

* Updated CHANGELOG.md

* Fixed incorrect annotation

* Added support for Redis 8.6

* Codestyle changes and test fixes

* Fixed hybdrid tests

* Updated CHANGELOG.md and composer.json

* Fixed XINFO tests
2026-02-04 11:29:24 +02:00
Vladyslav Vildanov d8a99ef674 Added testing with SSL authentication using CN (#1627)
* Added testing with SSL authentication using CN

* Update CHANGELOG.md

* Codestyle changes

* Fixed broken tests

* Fixed hybdrid tests

* Fixed SSL tests

* Fixed array merging

* Updated README.md

* Updated spelling list

* Added support for Redis 8.6

* Codestyle changes and test fixes

* Fixed hybdrid tests

* Updated CHANGELOG.md and composer.json

* Fixed XINFO tests
2026-02-04 11:18:53 +02:00
Vladyslav Vildanov a24a7be9b4 Added support for Redis 8.6 (#1631)
* Added support for Redis 8.6

* Codestyle changes and test fixes

* Fixed hybdrid tests

* Updated CHANGELOG.md and composer.json

* Fixed XINFO tests
2026-02-04 10:49:05 +02:00
Vladyslav Vildanov 95e802430d Added testing with SSL connection (#1624)
* Added testing with SSL connection

* Update CHANGELOG.md

* Revert changes

* Codestyle fixes

* Add version restriction

* Fixed issue with connecting to SSL port to check redis version

* Mark tests as relay-incompatible

* Codestyle fixes
2026-01-20 17:45:10 +02:00
Vladyslav Vildanov 0703c3cae6 Added support for VRANGE command (#1623)
* Added support for VRANGE command

* Update CHANGELOG.md

* Codestyle fixes

* Codestyle fixes
2026-01-19 10:50:39 +02:00
Vladyslav Vildanov 7c7cf90152 Improve connection handshake by pipelining commands (#1622)
* Improve connection handshake by pipelining commands

* Added exceptions handling for Redis < 6.0

* Updated CHANGELOG.md
2026-01-08 13:56:55 +02:00
Markus Reinhold b211afd755 Make ZRANDMEMBER prefixable (#1621)
* Make ZRANDMEMBER prefixable

* Update CHANGELOG.md

---------

Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-12-23 13:27:27 +02:00
Vladyslav Vildanov 980326d5d8 Added retry support (#1616)
* Initial work on retries

* Added retry class and test coverage

* Added support for standalone and cluster

* Make TimeoutException instance of CommunicationException

* Added pipeline, trasnaction, replication support

* Fixed broken test

* Marked test as relay-incompatible

* Marked test as relay-incompatible

* Fixed analysis errors, added missing tests

* Codestyle fixes

* Fixed test

* Update README.md

* Update README.md

* Update README.md

* Updated README.md

* Refactor retry on read and write

* Added check for timeout value

* Updated README.md

* Fixed README.md

* Codestyle changes

* Added missing coverage

* Added missing test coverage

* Removed comments

* Added retry support for Relay connection (#1620)

* Added integration test case with mocked retry

* Changed client initialisation in tests

* Marked test as relay-incompatible

---------

Co-authored-by: Pavlo Yatsukhnenko <yatsukhnenko@users.noreply.github.com>
2025-12-23 10:40:46 +02:00
Pavlo Yatsukhnenko 0ae180c942 Enable more Relay tests (#1617)
run tests against relay nightly for faster testing
2025-11-27 16:18:22 -08:00
Andrew Ivchenkov 98c853a689 fixed param annotation (#1614) 2025-11-25 09:04:34 -08:00
Till Krüss 153097374b Prepare v3.3.0 release (#1612) 2025-11-24 09:48:50 -08:00
Vladyslav Vildanov 6ef87493ca Added testing with 8.4-GA (#1611) 2025-11-19 08:30:39 -08:00
Vladyslav Vildanov 80430b4cde Added new experimental CAS/CAD functionallity (#1609)
* Added new CAS/CAD functionallity

* Updated CHANGELOG.md

* Codestyle fixes

* Fixed version constraint

* Marked feature as experimental

* Updated version constraints, added missing annotations
2025-11-12 10:14:06 +02:00
Vladyslav Vildanov d0f37f0bac Added temporary XREADGROUP_CLAIM command (#1608)
* Added temporary XREADGROUP_CLAIM command

* Updated CHANGELOG.md

* Added deprecation annotation
2025-11-12 09:14:57 +02:00
Vladyslav Vildanov f11e855047 Added experimental support for FT.HYBRID (#1607)
* Added basic structures and test coverage

* Added most of the test coverage

* Added more test coverage

* Codestyle fixes

* Fixed static analysis

* ANother static analysis fix

* Codestyle fixes

* Fixed version constraints

* Added missing annotations

* Use class context

* Added more test coverage

* Codestyle fixes

* Added experimental mentioning
2025-11-11 15:31:10 +02:00
Vladyslav Vildanov ce853ecec2 Added support for MSET command (#1610)
* Added support for MSET command

* Codestyle fixes
2025-11-11 14:49:07 +02:00
Vladyslav Vildanov f4dcf6ce57 Added testing with 8.4-RC1-pre.2 (#1605)
* Added testing with 8.4-RC1-pre.2

* Updated CHANGELOG.md
2025-11-03 16:49:12 +02:00
Vladyslav Vildanov 72a95b3d75 Added testing with 8.4-RC1-pre image (#1602)
* Added testing with 8.4-RC1-pre image

* Updated CHANGELOG.md
2025-10-27 09:47:24 -07:00
Pavlo Yatsukhnenko 62f4ebcc37 Add AUTH command to Relay connection tests (#1601) 2025-10-20 10:34:31 -07:00
Pavlo Yatsukhnenko f26a13c8f4 Improve Relay compatibility (#1599) 2025-10-20 07:52:40 -07:00
Till Krüss 44e4546ccd add remaining @group relay-fixme 2025-10-17 13:09:13 -07:00
Pavlo Yatsukhnenko da7b1cedb7 Improve Relay compatibility (#1597) 2025-10-17 13:03:29 -07:00
Vladyslav Vildanov fd1a0fc278 Added testing with 8.4-M01 (#1593) 2025-10-17 10:42:36 -07:00
Vladyslav Vildanov 7a15da293b Added prefixable interface for HEXPIRE, HEXPIRETIME (#1592) 2025-10-17 10:27:44 -07:00
Viktor Szépe d9dfefd247 Fix typos (#1579) 2025-10-03 16:22:43 -07:00
Vladyslav Vildanov 8a0c70baa5 Added testing with 8.2.1-pre (#1588) 2025-08-15 09:13:51 -07:00
Vladyslav Vildanov 053cb4b6ac Refactor pipeline data writing depends on connection type (#1586)
* Refactor pipeline data writing depends on connection type

* Updated CHANGELOG.md
2025-08-13 09:59:39 +03:00
Róbert Kelčák 0f4bc7653c Fix stream commands cluster support (#1587)
* Fix stream commands cluster support

* Update CHANGELOG.md
2025-08-12 13:33:48 +03:00
Vladyslav Vildanov 9e9deec4df Tag v3.2.0 (#1585)
* Tag v3.2.0

* Updated 8.2 test image
2025-08-06 09:41:24 +03:00
Vladyslav Vildanov c1845d96cc Added test coverage for updated Vamana (#1584)
* Added test coverage for updated Vamana

* Updated CHANGELOG.md

* Increased timeouts

* Removed assertion cause Relay removes total field

* Added realy-resp3 group

* Revert assertions
2025-08-03 22:20:07 +03:00
Elena Kolevska 8f18de1c12 Updates 8.2 test image to rc2 (#1583) 2025-08-01 12:42:25 -07:00
Hristo Temelski 6d37dc45b0 Added new stream commands, extended existing ones (#1580)
* Added new stream commands, extended existing ones

* updated the changelog

* fixed linter errors

* fixed regressions

* more linter fixes

* XADD fix

* lint fix

* Update CHANGELOG.md

* update interfaces, address PR comments

* fixed linter errors

* fixed xdelex return type

* updated new command signatures

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-07-29 12:59:06 +03:00
Vladyslav Vildanov 1c96f704fc Added missing VSIM argument (#1582)
* Added missing VSIM argument

* Updated CHANGELOG.md
2025-07-28 15:57:35 +03:00
Till Krüss b10cf7c96a back to dev version 2025-07-22 08:38:59 -07:00
Till Krüss 202e0c5322 bump version 2025-07-22 08:37:44 -07:00
Till Krüss 6387da61d4 bump dev version 2025-07-22 08:33:40 -07:00
Till Krüss 97bce0062d cleanup changelog 2025-07-22 08:31:37 -07:00
Till Krüss fe1ea1b8f9 tag v3.0.2 2025-07-22 08:30:03 -07:00
Hristo Temelski 302b63b742 Added test to ensure ftcreate vamana compatibility (#1578)
* Added test to ensure ftcreate vamana compatibility

* updated changelog
2025-07-21 09:48:12 -07:00
ridgey-dev 8e7afbe679 Retry all exceptions from Sentinel replicas (#1577)
* Retry SentinelReplication::retryCommandOnFailure on all classes with Throwable interface

* Retry SentinelReplication::retryCommandOnFailure on all classes with Throwable interface

* Fix coding style
2025-07-18 09:21:40 +03:00
Vladyslav Vildanov c60003a717 Marked missing commands as Prefixable (#1576)
* Marked missing commands as Prefixable

* Codestyle fixes

* Updated CHANGELOG.md
2025-07-09 19:03:22 +03:00
Vladyslav Vildanov 4dcc66f47e Updated Redis 8.2 test image (#1573)
* Updated Redis 8.2 test image

* Updated CHANGELOG.md
2025-07-03 16:53:00 +03:00
Hristo Temelski e0a03c6590 BITOP added operation validation (#1566)
* BITOP added operation validation

* Ensure that the arguments are not an empty list before doing operation check

* Updated changelog, fixed linter errors

* added test for the new bitop operations

* fixed liniting

* update requiresRedisVersion

---------

Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-06-21 11:03:17 +03:00
Vladyslav Vildanov 5e59123f0a Added testing with 8.2 (#1567)
* Added testing with 8.2

* Updated CHANGELOG.md

* Updated conditions for Relay stack tests

* Removed redundat condition

* Removed stack port overriding
2025-06-20 18:39:26 +03:00
alschastny 7509e5f42d XINFO command parse response changes + more tests (#1560)
Co-authored-by: alschastny <>
2025-06-19 10:32:39 +03:00
Till Krüss efc2c3798c Update CODEOWNERS (#1564) 2025-06-17 07:00:17 -07:00
alschastny ec375afa4a fix XREAD parse null response (#1563)
Co-authored-by: aleksanders <alexander.s@seranking.com>
2025-06-17 10:39:31 +03:00
Vladyslav Vildanov 9992595711 Updated Redis 8.0 test image (#1562)
* Updated Redis 8.0 test image

* Updated CHANGELOG.md

* Updated version restriction

* Marked test as relay-incompatible
2025-06-16 09:42:56 -07:00
alschastny 33e1174a4f implement XSETID command (#1559)
* implement XSETID command

* modify CHANGELOG.md

* split test to basic and extended version

---------

Co-authored-by: aleksanders <alexander.s@seranking.com>
2025-06-16 10:11:51 +03:00
alschastny 1e390b1814 implement XPENDING command (#1558)
* implement XPENDING command

* modify CHANGELOG.md

---------

Co-authored-by: aleksanders <alexander.s@seranking.com>
Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-06-13 10:34:52 +03:00
alschastny 0a8fe54b44 implement XCLAIM command (#1557)
* implement XCLAIM command

* modify CHANGELOG.md

* add empty line before return

* test xclaim with all available options

* review refactoring

* remove fast-track check for empty answer

---------

Co-authored-by: aleksanders <alexander.s@seranking.com>
2025-06-13 10:07:44 +03:00
alschastny b5b486a254 add XACK command (#1555)
* add XACK command

* add XACK to ClientContextInterface

* modify CHANGELOG.md

---------

Co-authored-by: aleksanders <alexander.s@seranking.com>
Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-06-11 09:28:13 -07:00
Vladyslav Vildanov 5e18e91ffc fix(commands): Fixed wrong command API call on prefix processing (#1554)
* fix(commands): Fixed wrong command API call on prefix processing

* Updated CHANGELOG.md

* Updated test case
2025-06-11 10:46:25 +03:00
Vladyslav Vildanov c2b95dfd2a Backport #1551 (#1552)
* fix(conn): Removed automatic conn_uid assignment (#1551)

* fix(conn): Removed automatic conn_uid assignment

* Restrict redis version

* Updated CHANGELOG.md

* Added test case

* Update CHANGELOG.md

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>

* Removed duplicated disconnect

* Updated CHANGELOg.md

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-06-05 18:34:21 +03:00
Vladyslav Vildanov 30e48f566e feat(commands): Add support for VectorSet commands (#1550)
* feat(commands): Add support for VectorSet commands

* Codestyle fixes

* Fixed test

* Added logging for test purposes

* Marked tests as relay incompatible

* Missing incompatible tests

* Updated CHANGELOG to reflect experimental nature of feature

* Marked properties as nullable

* Changed static variables to constants

* Codestyle fixe

* Revert changes

* Update CHANGELOG.md

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-06-05 09:28:31 +03:00
Vladyslav Vildanov d7f60099a6 fix(stream): Fixed throwing CommunicationException when stream is EOF (#1548)
* fix(stream): Fixed return type to match function signature

* Updated CHANGELOG.md

* Fix syntax error

* Updated CHANGELOG.md entry
2025-05-30 10:26:17 +03:00
Mustafa AKBEL 6021daf9cd Treat LOADING Errors as Connection Failures to Retry with Next Replica (#1536)
* fix(sentinel-replication): Treat LOADING error responses as ConnectionException to allow retry mechanism to discard the current replica and switch to the next available one.

* fix(sentinel-replication): add changelog entries for LOADING response handling

* Update CHANGELOG.md

* Update CHANGELOG.md

---------

Co-authored-by: Mustafa AKBEL <mustafa.akbel@pusula.net.tr>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-05-28 15:11:13 +03:00
Till Krüss 2372b5c767 Update CHANGELOG.md 2025-05-27 09:55:23 -07:00
Vladyslav Vildanov 87e08a3709 Backport #1546 (#1547)
* Fix return type for ZCOUNT (#1546)

* Fix return type for ZCOUNT

ZCOUNT returns an `int`:

> Integer reply: the number of members in the specified score range.

* Update CHANGELOG.md

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>

* Added changelog entry

---------

Co-authored-by: Tim Düsterhus <timwolla@googlemail.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-05-27 09:54:46 -07:00
Vladyslav Vildanov 421827625e Backport #1503 (#1545)
* Backport #1503

* Update CHANGELOG.md

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-05-27 10:17:35 +03:00
Till Krüss afa8b55aa3 bump dev version 2025-05-16 11:33:03 -07:00
1276 changed files with 24416 additions and 1869 deletions
+2 -14
View File
@@ -1,14 +1,2 @@
# Default
* @tillkruss
# Redis commands
src/Command/Redis/* @predis/team @tillkruss
# Redis Stack
src/Command/Redis/Json/* @predis/team
src/Command/Redis/Search/* @predis/team
src/Command/Redis/TopK/* @predis/team
src/Command/Redis/TDigest/* @predis/team
src/Command/Redis/BloomFilter/* @predis/team
src/Command/Redis/CuckooFilter/* @predis/team
src/Command/Redis/CountMinSketch/* @predis/team
* @predis/maintainers
src/Relay* @tillkruss
+20
View File
@@ -0,0 +1,20 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: /
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "composer"
directory: /
schedule:
interval: "monthly"
groups:
composer-minor:
update-types:
- "minor"
- "patch"
+29 -4
View File
@@ -3,7 +3,7 @@
services:
redis-official:
image: ${REDIS_IMAGE_NAME:-redis:7.4}
image: ${REDIS_IMAGE_NAME:-redis:8.0}
container_name: redis-official
healthcheck:
test: [ "CMD", "redis-cli", "PING" ]
@@ -20,10 +20,11 @@ services:
- standalone
redis-clients:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
container_name: redis-standalone
environment:
- TLS_ENABLED=yes
- TLS_CLIENT_CNS=test_user
- REDIS_CLUSTER=no
- REDIS_PASSWORD=foobar
- PORT=6379
@@ -40,7 +41,7 @@ services:
- standalone
redis-unprotected:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
container_name: redis-unprotected
environment:
- TLS_ENABLED=no
@@ -56,9 +57,10 @@ services:
- all
- clients
- unprotected
- sentinel
redis-cluster:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
container_name: redis-cluster
environment:
- REDIS_CLUSTER=yes
@@ -66,11 +68,13 @@ services:
- NODES=6
- REPLICAS=1
- TLS_ENABLED=yes
- TLS_CLIENT_CNS=test_user
- PORT=6372
- TLS_PORT=27379
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save "" --requirepass "foobar"}
ports:
- "6372-6377:6372-6377"
- "27379-27384:27379-27384"
volumes:
- "./dockers/cluster:/redis/work"
profiles:
@@ -94,3 +98,24 @@ services:
- all
- clients
- stack
sentinel:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
container_name: redis-sentinel
depends_on:
- redis-unprotected
environment:
- REDIS_CLUSTER=no
- NODES=3
- PORT=26379
command: ${REDIS_EXTRA_ARGS:---sentinel}
ports:
- 26379:26379
- 26380:26380
- 26381:26381
volumes:
- "./dockers/sentinel.conf:/redis/config-default/redis.conf"
- "./dockers/sentinel:/redis/work"
profiles:
- sentinel
- all
+8
View File
@@ -0,0 +1,8 @@
sentinel resolve-hostnames yes
sentinel monitor predis-test 127.0.0.1 6380 2
# Be much more tolerant to transient stalls (index builds, GC, I/O)
sentinel down-after-milliseconds predis-test 60000
# Avoid rapid repeated failover attempts
sentinel failover-timeout predis-test 180000
# Keep it conservative: sync one replica at a time
sentinel parallel-syncs predis-test 1
+1 -1
View File
@@ -1,7 +1,7 @@
name-template: 'v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
change-template: '- $TITLE (#$NUMBER)'
filter-by-comitish: true
filter-by-commitish: true
commitish: v3.x
autolabeler:
+5
View File
@@ -1,10 +1,15 @@
ACLs
AUTH
Autoloading
cafile
CAS
CN
Customizable
ElastiCache
FPM
GC
IANA
mTLS
Lua
PSR
Packagist
+8 -8
View File
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Check file permissions
run: test "$(find . -type f -not -path './.git/*' -executable)" = "./bin/create-command-test"
@@ -47,7 +47,7 @@ jobs:
tools: parallel-lint
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Check source code for syntax errors
run: composer exec -- parallel-lint bin/ examples/ src/ tests/
@@ -67,13 +67,13 @@ jobs:
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Validate Composer configuration
run: composer validate --no-interaction --strict
- name: Install dependencies
uses: ramsey/composer-install@v2
uses: ramsey/composer-install@v4
with:
dependency-versions: highest
@@ -101,7 +101,7 @@ jobs:
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Check EditorConfig configuration
run: test -f .editorconfig
@@ -110,7 +110,7 @@ jobs:
uses: greut/eclint-action@v0
- name: Install dependencies
uses: ramsey/composer-install@v2
uses: ramsey/composer-install@v4
with:
dependency-versions: highest
@@ -130,7 +130,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Check exported files
run: |
@@ -159,7 +159,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
steps:
- uses: release-drafter/release-drafter@v5
- uses: release-drafter/release-drafter@v7
with:
config-name: release-drafter-config.yml
env:
+2 -2
View File
@@ -6,9 +6,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Check Spelling
uses: rojopolis/spellcheck-github-actions@0.33.1
uses: rojopolis/spellcheck-github-actions@0.60.0
with:
config_path: .github/spellcheck-settings.yml
task_name: Markdown
+49 -29
View File
@@ -31,6 +31,10 @@ jobs:
- '7.2'
- '7.4'
- '8.0'
- '8.2'
- '8.4'
- '8.6'
- '8.8'
steps:
@@ -38,7 +42,11 @@ jobs:
run: |
# Mapping of original redis versions to client test containers
declare -A redis_clients_version_mapping=(
["8.0"]="8.0.1-pre"
["8.8"]="8.8.0"
["8.6"]="8.6.1"
["8.4"]="8.4.0"
["8.2"]="8.2.2"
["8.0"]="8.0.2"
["7.4"]="7.4.2"
["7.2"]="7.2.7"
)
@@ -70,16 +78,16 @@ jobs:
fi
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Start Redis standalone image
uses: hoverkraft-tech/compose-action@v2.0.1
uses: hoverkraft-tech/compose-action@v3.0.0
with:
compose-file: .github/docker-compose.yml
services: ${{ env.DOCKER_SERVICE }}
- name: Start Redis unprotected image
uses: hoverkraft-tech/compose-action@v2.0.1
uses: hoverkraft-tech/compose-action@v3.0.0
if: ${{ matrix.redis > '4.0' }}
with:
compose-file: .github/docker-compose.yml
@@ -87,7 +95,7 @@ jobs:
- name: Start Redis stack image
id: stack_infra
uses: hoverkraft-tech/compose-action@v2.0.1
uses: hoverkraft-tech/compose-action@v3.0.0
if: ${{ matrix.redis >= '7.2' && matrix.redis < '8.0' }}
with:
compose-file: .github/docker-compose.yml
@@ -95,98 +103,110 @@ jobs:
- name: Start Redis cluster image
id: cluster_infra
uses: hoverkraft-tech/compose-action@v2.0.1
uses: hoverkraft-tech/compose-action@v3.0.0
if: ${{ matrix.redis > '4.0' }}
with:
compose-file: .github/docker-compose.yml
services: redis-cluster
- name: Start Redis sentinels image
id: sentinel_infra
uses: hoverkraft-tech/compose-action@v3.0.0
if: ${{ matrix.redis > '4.0' }}
with:
compose-file: .github/docker-compose.yml
services: sentinel
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: relay
coverage: ${{ (matrix.php == '8.4' && matrix.redis == '7.4') && 'xdebug' || 'none' }}
extensions: relay-nightly
coverage: ${{ (matrix.php == '8.4' && matrix.redis == '8.0') && 'xdebug' || 'none' }}
- name: Install Composer dependencies
uses: ramsey/composer-install@v2
uses: ramsey/composer-install@v4
with:
dependency-versions: highest
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
- name: Run tests
if: ${{ matrix.php != '8.4' || matrix.redis != '7.4' }}
if: ${{ matrix.php != '8.4' || matrix.redis != '8.0' }}
run: vendor/bin/phpunit
- name: Run tests with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit --coverage-php build/cov/coverage-predis.cov --coverage-filter ./src
- name: Run tests using Relay
if: ${{ matrix.php != '8.4' && matrix.redis >= '7.2' }}
if: ${{ matrix.php != '8.4' && matrix.redis >= '8.0' }}
run: vendor/bin/phpunit -c phpunit.relay.xml
- name: Run tests using Relay with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit -c phpunit.relay.xml --coverage-php build/cov/coverage-relay.cov --coverage-filter ./src
- name: Run tests against unprotected Redis
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && matrix.redis > '4.0'}}
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis > '4.0'}}
run: vendor/bin/phpunit --group unprotected
- name: Run tests against unprotected Redis with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit --group unprotected --coverage-php build/cov/coverage-unprotected.cov --coverage-filter ./src
- name: Run sentinel tests
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis > '4.0'}}
run: vendor/bin/phpunit --group sentinel
- name: Run sentinel tests with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit --group sentinel --coverage-php build/cov/coverage-sentinel.cov --coverage-filter ./src
- name: Run stack tests
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && matrix.redis >= '7.2' }}
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis >= '7.2' }}
run: vendor/bin/phpunit --group realm-stack
- name: Run stack tests with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' && steps.stack_infra.conclusion == 'success' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit --group realm-stack --coverage-php build/cov/coverage-stack.cov --coverage-filter ./src
env:
REDIS_STACK_SERVER_PORT: 6479
- name: Run stack tests using Relay
if: ${{ matrix.php != '8.4' && matrix.redis == '7.4' }}
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis >= '7.2' }}
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml
- name: Run stack tests using Relay with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml --coverage-php build/cov/coverage-stack-relay.cov --coverage-filter ./src
env:
REDIS_STACK_SERVER_PORT: 6479
- name: Run tests against cluster
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && steps.cluster_infra.conclusion == 'success' }}
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && steps.cluster_infra.conclusion == 'success' }}
run: |
vendor/bin/phpunit --group cluster
- name: Run tests against cluster with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' && steps.cluster_infra.conclusion == 'success' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' && steps.cluster_infra.conclusion == 'success' }}
run: |
vendor/bin/phpunit --group cluster --coverage-php build/cov/coverage-cluster.cov --coverage-filter ./src
- name: Run tests against cluster using Relay
if: ${{ matrix.php != '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php != '8.4' && matrix.redis == '8.0' }}
run: |
sleep 5
vendor/bin/phpunit -c phpunit.relay.xml --group cluster
- name: Run tests against cluster using Relay with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: |
sleep 5
vendor/bin/phpunit -c phpunit.relay.xml --group cluster --coverage-php build/cov/coverage-cluster-relay.cov --coverage-filter ./src
- name: Merge coverage reports
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
run: php vendor/bin/phpcov merge --clover build/logs/clover.xml build/cov
- name: Send coverage to Coveralls
uses: coverallsapp/github-action@v2
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
+1 -1
View File
@@ -4,7 +4,7 @@ $PREDIS_HEADER = <<<EOS
This file is part of the Predis package.
(c) 2009-2020 Daniele Alessandri
(c) 2021-2025 Till Krüss
(c) 2021-2026 Till Krüss
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
+103 -1
View File
@@ -1,7 +1,109 @@
## Changelog
### Unreleased
### Changed
- Update GH runners based on NodeJS <= 20 (#1684)
## v3.5.0 (2026-06-02)
### Added
- Added support for `XNACK` command (#1666)
- Added support for `INCREX` command (#1674)
- Added support for `UNLINK` command (#1680)
- Added support for `AR*` array commands (#1672)
- Handle Redis Cluster `-READONLY` responses failover events (#1656)
- Added `FPHA` argument for `JSON.SET` command (#1661)
- Added new `COUNT` aggregator for Sorted Set commands (#1668)
- Added support for multiple aggregators for `TS.range` commands (#1670)
### Changed
- Include command name in unsupported container command error messages (#1653)
### Fixed
- Fixed handling of gap slots in `SlotMap::offsetUnset()` (#1660)
- Fixed `ZRANGE` to include 6.2 arguments (#1662)
- Fixed Sentinel retry to narrow retryable exceptions to `CommunicationException` (#1665)
- Fixed `SENTINEL SLAVES` RESP3 incompatible response (#1676)
## v3.4.2 (2026-03-09)
### Changed
- Switch to `static` closures
### Fixed
- Fixed Sentinel `getParameters()` executed on string configuration (#1649)
- Fixed Sentinel discovery methods not catching `StreamInitException` on connection failure (#1650)
## v3.4.1 (2026-02-23)
### Added
- Added `upstream_driver` option for CLIENT SETINFO upstream reporting (#1645)
- Made `H(P)TTL` commands prefixable (#1639)
- Made `(B)LMPOP` commands prefixable (#1643)
### Fixed
- Fixed Sentinel `getParameter()` call on array error (#2423)
- Removed deprecated `static` from callables (#1642)
## v3.4.0 (2026-02-11)
### Added
- Added optional retry support (#1616)
- Added support for `VRANGE` command (#1623)
- Added support for idempotent stream API (#1632)
- Added support for `HOTKEYS` container command (#1630)
### Fixed
- Fixed `[L|R]PUSHX` variadic arguments normalization (#1633)
- Fixed wrong `@param` annotation in `Parameters` (#1614)
- Made `ZRANDMEMBER` prefixable (#1621)
- Improve connection handshake by pipelining commands (#1622)
## v3.3.0 (2025-11-24)
### Added
- Added cluster support for `XADD`, `XDEL` and `XRANGE` (#1587)
- Added prefixable interface for `HEXPIRE` and `HEXPIRETIME` (#1592)
- Added new experimental CAS/CAD functionality (#1609)
- Added temporary `XREADGROUP_CLAIM` command (#1608)
- Added support for `MSET` command (#1610)
- Added experimental support for `FT.HYBRID` (#1607)
### Changed
- Improved compatiblity with Relay (#1597)
- Refactor pipeline data writing depends on connection type (#1586)
## v3.2.0 (2025-08-05)
### Added
- Added support for `XDELEX` and `XACKDEL` (#1580)
- Added missing VSIM argument (#1582)
### Changed
- Extended `XTRIM` and `XADD` commands with new parameters (#1580)
### Maintenance
- Updated Redis 8.2 test image (#1583)
- Added test coverage for updated Vamana (#1584)
## v3.1.0 (2025-07-22)
### Added
- Add experimental support for vector sets commands (#1550)
- Added support for `XACK` command (#1555)
- Added support for `XCLAIM` command (#1557)
- Added support for `XPENDING` command (#1558)
- Added support for `XSETID` command (#1559)
- Added validation and support for the new `BITOP` command operations (#1566)
### Changed
- Handle and retry `LOADING` errors from Sentinel replicas (#1536)
- Retry all exceptions from Sentinel replicas (#1577)
### Fixed
- Fixed PHP 8.4 deprecated call to `stream_context_set_option()` (#1545)
- Fixed return type for `ZCOUNT` to be `int` (#1547)
- Fixed throwing `CommunicationException` when stream is EOF (#1548)
- Removed automatic `conn_uid` parameter assignment (#1552)
- Fixed wrong command API call on prefix processing (#1554)
- Fixed `XREAD` response parsing while read null (#1563)
- Fixed `XINFO` command responses parsing (#1560)
- Marked missing commands as Prefixable (#1576)
## v3.0.1 (2025-05-16)
### Fixed
- Send `default` user if only password is used for authentication (#1535)
+116 -1
View File
@@ -114,6 +114,40 @@ The connection schemes [`redis`](http://www.iana.org/assignments/uri-schemes/pro
also supported, with the difference that URI strings containing these schemes are parsed following
the rules described on their respective IANA provisional registration documents.
Since Redis 8.6, you can authenticate a client using the Subject CN from its TLS client certificate (mTLS).
When this is enabled on the server, the client is authenticated during the TLS handshake, so you dont need
to send an AUTH command.
To use this, configure:
- a CA certificate used to verify the server certificate (cafile),
- a client certificate (local_cert) signed by a CA trusted by the Redis server for client authentication,
- the corresponding private key (local_pk).
Make sure:
- the Redis server certificate is signed by a CA trusted by the client, and
- the client certificate is signed by a CA trusted by the Redis server (mTLS).
```php
// Named array of connection parameters:
$client = new Predis\Client([
'scheme' => 'tls',
'ssl' => [
'cafile' => 'ca.pem', // CA used to verify the server certificate
'local_cert' => 'client.crt', // client certificate (Subject CN maps to ACL user)
'local_pk' => 'client.key', // client private key
'verify_peer' => true,
],
]);
// ACL user must exist and match the certificate Subject CN (example: CN=CN_NAME).
// Enable the user and grant permissions as needed:
$client->acl->setUser('CN_NAME', 'on', '>clientpass', 'allcommands', 'allkeys')
echo $client->acl->whoami() // CN_NAME
```
The actual list of supported connection parameters can vary depending on each connection backend so
it is recommended to refer to their specific documentation or implementation for details.
@@ -138,6 +172,50 @@ it is still desired to have control of when the connection is opened or closed:
achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect
of these methods on aggregate connections may differ depending on each specific implementation.
#### Persistent connections ####
To increase a performance of your application you may set up a client to use persistent TCP connection, this way
client saves a time on socket creation and connection handshake. By default, connection is created on first-command
execution and will be automatically closed by GC before the process is being killed.
However, if your application is backed by PHP-FPM the processes are idle, and you may set up it to be persistent and
reusable across multiple script execution within the same process.
To enable the persistent connection mode you should provide following configuration:
```php
// Standalone
$client = new Predis\Client(['persistent' => true]);
// Cluster
$client = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
```
**Important**
If you operate on multiple clients within the same application, and they communicate with the same resource, by default
they will share the same socket (that's the default behaviour of persistent sockets). So in this case you would need
to additionally provide a `conn_uid` identifier for each client, this way each client will create its own socket so
the connection context won't be shared across clients. This socket behaviour explained
[here](https://www.php.net/manual/en/function.stream-socket-client.php#105393)
```php
// Standalone
$client1 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_1']);
$client2 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_2']);
// Cluster
$client1 = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_1']]
);
$client2 = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_2']]
);
```
### Client configuration ###
@@ -465,6 +543,43 @@ $client = new Predis\Client('tcp://127.0.0.1', [
For a more in-depth insight on how to create new connection backends you can refer to the actual
implementation of the standard connection classes available in the `Predis\Connection` namespace.
### Retry exceptions
You can enable automatic retry that is disabled by default, to be able to reduce the amount of
false-positives in case of network issues. By default, we're retrying on any connection,
timeout or socket initialization exception, but you can update the list of retry
exceptions. For now `EqualBackoff` and `ExponentialBackoff` strategies are available,
but you may provide your custom one. Retry may be configured with any type of communication
(standalone node, cluster, pipeline, transaction, replication). Here's an example of
configuration:
```php
// Standalone client
$client = new Predis\Client([
'retry' => new \Predis\Retry\Retry(
new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000), // Base and cap configuration in microseconds
3 // Number of retries
),
]);
// Cluster configuration
$options = [
'parameters' => [
'retry' => new \Predis\Retry\Retry(new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000), 3),
],
];
$client = new Predis\Client(['tcp://host:port', 'tcp://host:port', 'tcp://host:port'], $options);
$retry = new \Predis\Retry\Retry(
new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000),
3
);
// Update a list of exceptions to catch
$retry->updateCatchableExceptions([Exception::class]);
```
## RESP3 ##
### Connection ###
@@ -549,7 +664,7 @@ $client = new Predis\Client(['read_write_timeout' => 0, 'protocol' => 3]);
// Create push notifications consumer.
// Provides callback where current consumer subscribes to few channels before
// enter the loop.
$push = $client->push(static function (ClientInterface $client) {
$push = $client->push(function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
+1 -1
View File
@@ -1 +1 @@
3.0.1
3.5.0
+1 -1
View File
@@ -15,7 +15,7 @@
// For example, to generate a test case for SET (which is represented by the
// Predis\Command\Redis\StringSet class):
//
// $ ./bin/generate-command-test --class=StringSet
// $ ./bin/create-command-test --class=StringSet
//
// Here is a list of optional arguments:
//
+7 -1
View File
@@ -46,7 +46,13 @@
},
"config": {
"sort-packages": true,
"preferred-install": "dist"
"preferred-install": "dist",
"audit": {
"ignore": [
"GHSA-vvj3-c3rp-c85p",
"PKSA-z3gr-8qht-p93v"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+3 -3
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -40,7 +40,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
public function remove($node)
{
$this->nodes = array_filter($this->nodes, function ($n) use ($node) {
$this->nodes = array_filter($this->nodes, static function ($n) use ($node) {
return $n !== $node;
});
@@ -89,7 +89,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
}
$options = [
'cluster' => function () {
'cluster' => static function () {
$distributor = new NaiveDistributor();
$strategy = new PredisStrategy($distributor);
$cluster = new PredisCluster($strategy);
+3 -3
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -34,11 +34,11 @@ class SimpleDebuggableConnection extends StreamConnection
private function storeDebug(CommandInterface $command, $direction)
{
$firtsArg = $command->getArgument(0);
$firstArg = $command->getArgument(0);
$timestamp = round(microtime(true) - $this->tstart, 4);
$debug = $command->getId();
$debug .= isset($firtsArg) ? " $firtsArg " : ' ';
$debug .= isset($firstArg) ? " $firstArg " : ' ';
$debug .= "$direction $this";
$debug .= " [{$timestamp}s]";
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -62,7 +62,7 @@ class EventsListener implements Countable
$dispatcher->attachCallback('events', $events = new EventsListener());
// Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
$dispatcher->attachCallback('control', static function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -18,7 +18,7 @@ require __DIR__ . '/shared.php';
$client = new Predis\Client($single_server);
$responses = $client->pipeline(function ($pipe) {
$responses = $client->pipeline(static function ($pipe) {
$pipe->flushdb();
$pipe->incrby('counter', 10);
$pipe->incrby('counter', 30);
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -23,7 +23,7 @@ $pubsub = $client->pubSubLoop();
// When using Relay you cannot use foreach-loops to iterate
// over messages instead use a callback function
$poorMansKafka = function ($message, $client) {
$poorMansKafka = static function ($message, $client) {
switch ($message->kind) {
case 'subscribe':
echo "Subscribed to {$message->channel}", PHP_EOL;
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -56,7 +56,7 @@ $options = [
'commands' => [
'hmgetall' => 'HashMultipleGetAll',
],
'replication' => function () {
'replication' => static function () {
$strategy = new ReplicationStrategy();
$strategy->setScriptReadOnly(HashMultipleGetAll::BODY);
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -74,7 +74,7 @@ class EventsListener implements Countable
$dispatcher->attachCallback('{channels}_events', $events = new EventsListener());
// 6. Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
$dispatcher->attachCallback('control', static function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+3 -3
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -22,9 +22,9 @@ function redis_version($info)
return $info['Server']['redis_version'];
} elseif (isset($info['redis_version'])) {
return $info['redis_version'];
} else {
return 'unknown version';
}
return 'unknown version';
}
$single_server = [
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -35,7 +35,7 @@ function zpop($client, $key)
// which the client bails out with an exception.
];
$client->transaction($options, function ($tx) use ($key, &$element) {
$client->transaction($options, static function ($tx) use ($key, &$element) {
@[$element] = $tx->zrange($key, 0, 0);
if (isset($element)) {
-6
View File
@@ -29,9 +29,6 @@ parameters:
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$weight\\.$#"
count: 1
path: src/Connection/Cluster/PredisCluster.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 2
path: src/Connection/Cluster/RedisCluster.php
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$role\\.$#"
count: 1
path: src/Connection/Replication/MasterSlaveReplication.php
@@ -45,6 +42,3 @@ parameters:
- message: "#^Variable \\$response might not be defined\\.$#"
count: 1
path: src/Connection/Replication/MasterSlaveReplication.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 1
path: src/Connection/Replication/SentinelReplication.php
+25
View File
@@ -10,6 +10,9 @@
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true"
>
<php>
<ini name="error_reporting" value="E_ALL &amp; ~E_DEPRECATED"/>
</php>
<testsuites>
<testsuite name="Predis Test Suite">
@@ -30,6 +33,7 @@
<group>gears</group>
<group>gears-cluster</group>
<group>unprotected</group>
<group>sentinel</group>
<!-- <group>connected</group> -->
<!-- <group>disconnected</group> -->
<!-- <group>commands</group> -->
@@ -52,6 +56,27 @@
<env name="USE_RELAY" value="false" />
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
<!-- Sentinel -->
<const name="REDIS_SENTINEL_SERVICE" value="predis-test" />
<const
name="REDIS_SENTINEL_ENDPOINTS"
value="127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381"
/>
<!-- SSL -->
<env name="STANDALONE_CA_CERT_PATH" value=".github/dockers/standalone/tls/ca.crt" />
<env name="STANDALONE_LOCAL_CERT_PATH" value=".github/dockers/standalone/tls/test_user.crt" />
<env name="STANDALONE_LOCAL_PK_PATH" value=".github/dockers/standalone/tls/test_user.key" />
<env name="CN_USER_NAME" value="test_user" />
<env name="REDIS_SSL_PORT" value="6666" />
<env name="CLUSTER_CA_CERT_PATH" value=".github/dockers/cluster/tls/ca.crt" />
<env name="CLUSTER_LOCAL_CERT_PATH" value=".github/dockers/cluster/tls/test_user.crt" />
<env name="CLUSTER_LOCAL_PK_PATH" value=".github/dockers/cluster/tls/test_user.key" />
<const
name="SSL_REDIS_CLUSTER_ENDPOINTS"
value="127.0.0.1:27379?password=foobar,127.0.0.1:27380?password=foobar,127.0.0.1:27381?password=foobar"
/>
<!-- Redis Cluster -->
<!-- Only master nodes endpoints included -->
<const
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+22 -9
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -22,6 +22,7 @@ use Predis\Command\RawCommand;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\AggregateConnectionInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
@@ -41,6 +42,7 @@ use Predis\Response\ServerException;
use Predis\Transaction\MultiExec as MultiExecTransaction;
use ReturnTypeWillChange;
use RuntimeException;
use Throwable;
use Traversable;
/**
@@ -54,7 +56,7 @@ use Traversable;
*/
class Client implements ClientInterface, IteratorAggregate
{
public const VERSION = '3.0.1';
public const VERSION = '3.5.0';
/** @var OptionsInterface */
private $options;
@@ -90,9 +92,8 @@ class Client implements ClientInterface, IteratorAggregate
return new Options($options);
} elseif ($options instanceof OptionsInterface) {
return $options;
} else {
throw new InvalidArgumentException('Invalid type for client options');
}
throw new InvalidArgumentException('Invalid type for client options');
}
/**
@@ -138,11 +139,10 @@ class Client implements ClientInterface, IteratorAggregate
return $initializer($parameters, true);
} elseif ($options->defined('aggregate') && $initializer = $options->aggregate) {
return $initializer($parameters, false);
} else {
throw new InvalidArgumentException(
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
);
}
throw new InvalidArgumentException(
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
);
}
if (is_callable($parameters)) {
@@ -376,12 +376,25 @@ class Client implements ClientInterface, IteratorAggregate
/**
* {@inheritdoc}
* @throws Throwable
*/
public function executeCommand(CommandInterface $command)
{
$response = $this->connection->executeCommand($command);
$parameters = $this->connection->getParameters();
if ($this->connection instanceof AggregateConnectionInterface || $this->connection instanceof RelayConnection) {
$response = $this->connection->executeCommand($command);
} else {
$response = $parameters->retry->callWithRetry(
function () use ($command) {
return $this->connection->executeCommand($command);
},
function () {
$this->connection->disconnect();
}
);
}
if ($response instanceof ResponseInterface) {
if ($response instanceof ErrorResponseInterface) {
$response = $this->onErrorResponse($command, $response);
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+63 -4
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -19,6 +19,7 @@ use Predis\Command\Argument\Search\AlterArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\DropArguments;
use Predis\Command\Argument\Search\ExplainArguments;
use Predis\Command\Argument\Search\HybridSearch\HybridSearchQuery;
use Predis\Command\Argument\Search\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
use Predis\Command\Argument\Search\SearchArguments;
@@ -41,16 +42,21 @@ use Predis\Command\CommandInterface;
use Predis\Command\Container\ACL;
use Predis\Command\Container\CLIENT;
use Predis\Command\Container\FUNCTIONS;
use Predis\Command\Container\HOTKEYS;
use Predis\Command\Container\Json\JSONDEBUG;
use Predis\Command\Container\Search\FTCONFIG;
use Predis\Command\Container\Search\FTCURSOR;
use Predis\Command\Container\XGROUP;
use Predis\Command\Redis\HSETEX;
use Predis\Command\Redis\VADD;
/**
* Interface defining a client-side context such as a pipeline or transaction.
*
* @method $this copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method $this del(array|string $keys)
* @method $this delex(string $key, string $flag, $flagValue)
* @method $this digest(string $key)
* @method $this dump($key)
* @method $this exists($key)
* @method $this expire($key, $seconds, string $expireOption = '')
@@ -71,7 +77,26 @@ use Predis\Command\Container\XGROUP;
* @method $this sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method $this ttl($key)
* @method $this type($key)
* @method $this unlink(string ...$keys)
* @method $this append($key, $value)
* @method $this arcount(string $key)
* @method $this ardel(string $key, int ...$index)
* @method $this ardelrange(string $key, int ...$startEnd)
* @method $this arget(string $key, int $index)
* @method $this argetrange(string $key, int $start, int $end)
* @method $this argrep(string $key, int $start, int $end, array $predicates, ?string $combinator = null, ?int $limit = null, bool $withValues = false, bool $noCase = false)
* @method $this arinfo(string $key, bool $full = false)
* @method $this arinsert(string $key, string ...$value)
* @method $this arlastitems(string $key, int $count, bool $reverse = false)
* @method $this arlen(string $key)
* @method $this armget(string $key, int ...$index)
* @method $this armset(string $key, array $indexValueDictionary)
* @method $this arnext(string $key)
* @method $this arop(string $key, int $start, int $end, string $operation, $matchValue = null)
* @method $this arring(string $key, int $size, string ...$value)
* @method $this arscan(string $key, int $start, int $end, ?int $limit = null)
* @method $this arseek(string $key, int $index)
* @method $this arset(string $key, int $index, string ...$value)
* @method $this bfadd(string $key, $item)
* @method $this bfexists(string $key, $item)
* @method $this bfinfo(string $key, string $modifier = '')
@@ -125,6 +150,7 @@ use Predis\Command\Container\XGROUP;
* @method $this ftdictdump(string $dict)
* @method $this ftdropindex(string $index, ?DropArguments $arguments = null)
* @method $this ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
* @method $this fthybrid(string $index, HybridSearchQuery $query)
* @method $this ftinfo(string $index)
* @method $this ftprofile(string $index, ProfileArguments $arguments)
* @method $this ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
@@ -145,11 +171,13 @@ use Predis\Command\Container\XGROUP;
* @method $this incr($key)
* @method $this incrby($key, $increment)
* @method $this incrbyfloat($key, $increment)
* @method $this increx(string $key, int|float|string $value, ?int $lbound = null, ?int $ubound = null, bool $saturate = false, ?string $expireType = null, $expireValue = null, bool $enx = false)
* @method $this mget(array $keys)
* @method $this mset(array $dictionary)
* @method $this msetex(array $dictionary, ?string $existModifier = null, ?string $expireResolution = null, ?int $expireTTL = null)
* @method $this msetnx(array $dictionary)
* @method $this psetex($key, $milliseconds, $value)
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null, $flagValue = null)
* @method $this setbit($key, $offset, $value)
* @method $this setex($key, $seconds, $value)
* @method $this setnx($key, $value)
@@ -200,7 +228,7 @@ use Predis\Command\Container\XGROUP;
* @method $this jsonobjkeys(string $key, string $path = '$')
* @method $this jsonobjlen(string $key, string $path = '$')
* @method $this jsonresp(string $key, string $path = '$')
* @method $this jsonset(string $key, string $path, string $value, ?string $subcommand = null)
* @method $this jsonset(string $key, string $path, string $value, ?string $subcommand = null, ?string $fpha = null)
* @method $this jsonstrappend(string $key, string $path, string $value)
* @method $this jsonstrlen(string $key, string $path = '$')
* @method $this jsontoggle(string $key, string $path)
@@ -266,7 +294,7 @@ use Predis\Command\Container\XGROUP;
* @method $this topklist(string $key, bool $withCount = false)
* @method $this topkquery(string $key, ...$items)
* @method $this topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method $this tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method $this tsadd(string $key, int $timestamp, string|float $value, ?AddArguments $arguments = null)
* @method $this tsalter(string $key, ?TSAlterArguments $arguments = null)
* @method $this tscreate(string $key, ?TSCreateArguments $arguments = null)
* @method $this tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
@@ -283,6 +311,24 @@ use Predis\Command\Container\XGROUP;
* @method $this tsqueryindex(string ...$filterExpression)
* @method $this tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this xack(string $key, string $group, string ...$id)
* @method $this xackdel(string $key, string $group, string $mode, array $ids)
* @method $this xadd(string $key, array $dictionary, string $id = '*', array $options = null)
* @method $this xautoclaim(string $key, string $group, string $consumer, int $minIdleTime, string $start, ?int $count = null, bool $justId = false)
* @method $this xclaim(string $key, string $group, string $consumer, int $minIdleTime, string|array $ids, ?int $idle = null, ?int $time = null, ?int $retryCount = null, bool $force = false, bool $justId = false, ?string $lastId = null)
* @method $this xcfgset(string $key, ?int $duration = null, ?int $maxsize = null)
* @method $this xdel(string $key, string ...$id)
* @method $this xdelex(string $key, string $mode, array $ids)
* @method $this xlen(string $key)
* @method $this xnack(string $key, string $group, string $mode, array $ids, ?int $retryCount = null, bool $force = false)
* @method $this xpending(string $key, string $group, ?int $minIdleTime = null, ?string $start = null, ?string $end = null, ?int $count = null, ?string $consumer = null)
* @method $this xrevrange(string $key, string $end, string $start, ?int $count = null)
* @method $this xrange(string $key, string $start, string $end, ?int $count = null)
* @method $this xread(int $count = null, int $block = null, array $streams = null, string ...$id)
* @method $this xreadgroup(string $group, string $consumer, ?int $count = null, ?int $blockMs = null, bool $noAck = false, string ...$keyOrId)
* @method $this xreadgroup_claim(string $group, string $consumer, array $keyIdDict, ?int $count = null, ?int $blockMs = null, bool $noAck = false, ?int $claim = null)
* @method $this xsetid(string $key, string $lastId, ?int $entriesAdded = null, ?string $maxDeleteId = null)
* @method $this xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
* @method $this zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
@@ -325,6 +371,18 @@ use Predis\Command\Container\XGROUP;
* @method $this unwatch()
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method $this unsubscribe(string ...$channels)
* @method $this vadd(string $key, string|array $vector, string $elem, int $dim = null, bool $cas = false, string $quant = VADD::QUANT_DEFAULT, ?int $BEF = null, string|array $attributes = null, int $numlinks = null)
* @method $this vcard(string $key)
* @method $this vdim(int $key)
* @method $this vemb(string $key, string $elem, bool $raw = false)
* @method $this vgetattr(string $key, string $elem, bool $asJson = false)
* @method $this vinfo(string $key)
* @method $this vlinks(string $key, string $elem, bool $withScores = false)
* @method $this vrandmember(string $key, int $count = null)
* @method $this vrange(string $key, string $start, string $end, int $count = null)
* @method $this vrem(string $key, string $elem)
* @method $this vsetattr(string $key, string $elem, string|array $attributes)
* @method $this vsim(string $key, string|array $vectorOrElem, bool $isElem = false, bool $withScores = false, int $count = null, float $epsilon = null, int $ef = null, string $filter = null, int $filterEf = null, bool $truth = false, bool $noThread = false)
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
@@ -361,6 +419,7 @@ use Predis\Command\Container\XGROUP;
*
* Container commands
* @property CLIENT $client
* @property HOTKEYS $hotkeys
* @property FUNCTIONS $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+55 -5
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -19,6 +19,7 @@ use Predis\Command\Argument\Search\AlterArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\DropArguments;
use Predis\Command\Argument\Search\ExplainArguments;
use Predis\Command\Argument\Search\HybridSearch\HybridSearchQuery;
use Predis\Command\Argument\Search\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
use Predis\Command\Argument\Search\SearchArguments;
@@ -41,12 +42,15 @@ use Predis\Command\CommandInterface;
use Predis\Command\Container\ACL;
use Predis\Command\Container\CLIENT;
use Predis\Command\Container\FUNCTIONS;
use Predis\Command\Container\HOTKEYS;
use Predis\Command\Container\Json\JSONDEBUG;
use Predis\Command\Container\Search\FTCONFIG;
use Predis\Command\Container\Search\FTCURSOR;
use Predis\Command\Container\XGROUP;
use Predis\Command\Container\XINFO;
use Predis\Command\FactoryInterface;
use Predis\Command\Redis\HSETEX;
use Predis\Command\Redis\VADD;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Response\Status;
@@ -61,6 +65,8 @@ use Predis\Response\Status;
*
* @method int copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method int del(string[]|string $keyOrKeys, string ...$keys = null)
* @method int delex(string $key, string $flag, $flagValue)
* @method string digest(string $key)
* @method string|null dump(string $key)
* @method int exists(string $key)
* @method int expire(string $key, int $seconds, string $expireOption = '')
@@ -81,7 +87,26 @@ use Predis\Response\Status;
* @method array sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int unlink(string ...$keys)
* @method int append(string $key, $value)
* @method int arcount(string $key)
* @method int ardel(string $key, int ...$index)
* @method int ardelrange(string $key, int ...$startEnd)
* @method string|null arget(string $key, int $index)
* @method array argetrange(string $key, int $start, int $end)
* @method array argrep(string $key, int $start, int $end, array $predicates, ?string $combinator = null, ?int $limit = null, bool $withValues = false, bool $noCase = false)
* @method array arinfo(string $key, bool $full = false)
* @method int arinsert(string $key, string ...$value)
* @method array arlastitems(string $key, int $count, bool $reverse = false)
* @method int arlen(string $key)
* @method array armget(string $key, int ...$index)
* @method int armset(string $key, array $indexValueDictionary)
* @method int|null arnext(string $key)
* @method mixed arop(string $key, int $start, int $end, string $operation, $matchValue = null)
* @method int arring(string $key, int $size, string ...$value)
* @method array arscan(string $key, int $start, int $end, ?int $limit = null)
* @method int arseek(string $key, int $index)
* @method int arset(string $key, int $index, string ...$value)
* @method mixed bfadd(string $key, $item)
* @method mixed bfexists(string $key, $item)
* @method array bfinfo(string $key, string $modifier = '')
@@ -135,6 +160,7 @@ use Predis\Response\Status;
* @method array ftdictdump(string $dict)
* @method Status ftdropindex(string $index, ?DropArguments $arguments = null)
* @method string ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
* @method array fthybrid(string $index, HybridSearchQuery $query)
* @method array ftinfo(string $index)
* @method array ftprofile(string $index, ProfileArguments $arguments)
* @method array ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
@@ -155,11 +181,13 @@ use Predis\Response\Status;
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
* @method string incrbyfloat(string $key, int|float $increment)
* @method array increx(string $key, int|float|string $value, ?int $lbound = null, ?int $ubound = null, bool $saturate = false, ?string $expireType = null, $expireValue = null, bool $enx = false)
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed mset(array $dictionary)
* @method array msetex(array $dictionary, ?string $existModifier = null, ?string $expireResolution = null, ?int $expireTTL = null)
* @method int msetnx(array $dictionary)
* @method Status psetex(string $key, $milliseconds, $value)
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null, $flagValue = null)
* @method int setbit(string $key, $offset, $value)
* @method Status setex(string $key, $seconds, $value)
* @method int setnx(string $key, $value)
@@ -210,7 +238,7 @@ use Predis\Response\Status;
* @method array jsonobjkeys(string $key, string $path = '$')
* @method array jsonobjlen(string $key, string $path = '$')
* @method array jsonresp(string $key, string $path = '$')
* @method string jsonset(string $key, string $path, string $value, ?string $subcommand = null)
* @method string jsonset(string $key, string $path, string $value, ?string $subcommand = null, ?string $fpha = null)
* @method array jsonstrappend(string $key, string $path, string $value)
* @method array jsonstrlen(string $key, string $path = '$')
* @method array jsontoggle(string $key, string $path)
@@ -277,7 +305,7 @@ use Predis\Response\Status;
* @method array topklist(string $key, bool $withCount = false)
* @method array topkquery(string $key, ...$items)
* @method Status topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method int tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method int tsadd(string $key, int $timestamp, string|float $value, ?AddArguments $arguments = null)
* @method Status tsalter(string $key, ?TSAlterArguments $arguments = null)
* @method Status tscreate(string $key, ?TSCreateArguments $arguments = null)
* @method Status tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
@@ -294,18 +322,27 @@ use Predis\Response\Status;
* @method array tsqueryindex(string ...$filterExpression)
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method int xack(string $key, string $group, string ...$id)
* @method array xackdel(string $key, string $group, string $mode, array $ids)
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
* @method array xautoclaim(string $key, string $group, string $consumer, int $minIdleTime, string $start, ?int $count = null, bool $justId = false)
* @method array xclaim(string $key, string $group, string $consumer, int $minIdleTime, string|array $ids, ?int $idle = null, ?int $time = null, ?int $retryCount = null, bool $force = false, bool $justId = false, ?string $lastId = null)
* @method Status xcfgset(string $key, ?int $duration = null, ?int $maxsize = null)
* @method int xdel(string $key, string ...$id)
* @method array xdelex(string $key, string $mode, array $ids)
* @method int xlen(string $key)
* @method int xnack(string $key, string $group, string $mode, array $ids, ?int $retryCount = null, bool $force = false)
* @method array xpending(string $key, string $group, ?int $minIdleTime = null, ?string $start = null, ?string $end = null, ?int $count = null, ?string $consumer = null)
* @method array xrevrange(string $key, string $end, string $start, ?int $count = null)
* @method array xrange(string $key, string $start, string $end, ?int $count = null)
* @method array|null xread(int $count = null, int $block = null, array $streams = null, string ...$id)
* @method array xreadgroup(string $group, string $consumer, ?int $count = null, ?int $blockMs = null, bool $noAck = false, string ...$keyOrId)
* @method array xreadgroup_claim(string $group, string $consumer, array $keyIdDict, ?int $count = null, ?int $blockMs = null, bool $noAck = false, ?int $claim = null)
* @method Status xsetid(string $key, string $lastId, ?int $entriesAdded = null, ?string $maxDeleteId = null)
* @method string xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
* @method int zadd(string $key, array $membersAndScoresDictionary)
* @method int zcard(string $key)
* @method string zcount(string $key, int|string $min, int|string $max)
* @method int zcount(string $key, int|string $min, int|string $max)
* @method array zdiff(array $keys, bool $withScores = false)
* @method int zdiffstore(string $destination, array $keys)
* @method string zincrby(string $key, int $increment, string $member)
@@ -346,6 +383,18 @@ use Predis\Response\Status;
* @method mixed multi()
* @method mixed unwatch()
* @method array unsubscribe(string ...$channels)
* @method bool vadd(string $key, string|array $vector, string $elem, int $dim = null, bool $cas = false, string $quant = VADD::QUANT_DEFAULT, int $bef = null, string|array $attributes = null, int $numlinks = null)
* @method int vcard(string $key)
* @method int vdim(string $key)
* @method array vemb(string $key, string $elem, bool $raw = false)
* @method string|array|null vgetattr(string $key, string $elem, bool $asJson = false)
* @method array|null vinfo(string $key)
* @method array|null vlinks(string $key, string $elem, bool $withScores = false)
* @method string|array|null vrandmember(string $key, int $count = null)
* @method array vrange(string $key, string $start, string $end, int $count = null)
* @method bool vrem(string $key, string $elem)
* @method array vsim(string $key, string|array $vectorOrElem, bool $isElem = false, bool $withScores = false, int $count = null, float $epsilon = null, int $ef = null, string $filter = null, int $filterEf = null, bool $truth = false, bool $noThread = false)
* @method bool vsetattr(string $key, string $elem, string|array $attributes)
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method mixed watch(string[]|string $keyOrKeys)
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
@@ -383,6 +432,7 @@ use Predis\Response\Status;
*
* Container commands
* @property CLIENT $client
* @property HOTKEYS $hotkeys
* @property FUNCTIONS $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
+31 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -42,6 +42,7 @@ abstract class ClusterStrategy implements StrategyInterface
/* commands operating on the key space */
'EXISTS' => $getKeyFromAllArguments,
'DEL' => $getKeyFromAllArguments,
'UNLINK' => $getKeyFromAllArguments,
'TYPE' => $getKeyFromFirstArgument,
'EXPIRE' => $getKeyFromFirstArgument,
'EXPIREAT' => $getKeyFromFirstArgument,
@@ -68,6 +69,7 @@ abstract class ClusterStrategy implements StrategyInterface
'INCR' => $getKeyFromFirstArgument,
'INCRBY' => $getKeyFromFirstArgument,
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'INCREX' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => [$this, 'getKeyFromInterleavedArguments'],
@@ -99,6 +101,26 @@ abstract class ClusterStrategy implements StrategyInterface
'LSET' => $getKeyFromFirstArgument,
'LTRIM' => $getKeyFromFirstArgument,
/* commands operating on arrays */
'ARCOUNT' => $getKeyFromFirstArgument,
'ARDEL' => $getKeyFromFirstArgument,
'ARDELRANGE' => $getKeyFromFirstArgument,
'ARGET' => $getKeyFromFirstArgument,
'ARGETRANGE' => $getKeyFromFirstArgument,
'ARGREP' => $getKeyFromFirstArgument,
'ARINFO' => $getKeyFromFirstArgument,
'ARINSERT' => $getKeyFromFirstArgument,
'ARLASTITEMS' => $getKeyFromFirstArgument,
'ARLEN' => $getKeyFromFirstArgument,
'ARMGET' => $getKeyFromFirstArgument,
'ARMSET' => $getKeyFromFirstArgument,
'ARNEXT' => $getKeyFromFirstArgument,
'AROP' => $getKeyFromFirstArgument,
'ARRING' => $getKeyFromFirstArgument,
'ARSCAN' => $getKeyFromFirstArgument,
'ARSEEK' => $getKeyFromFirstArgument,
'ARSET' => $getKeyFromFirstArgument,
/* commands operating on sets */
'SADD' => $getKeyFromFirstArgument,
'SCARD' => $getKeyFromFirstArgument,
@@ -155,6 +177,11 @@ abstract class ClusterStrategy implements StrategyInterface
'HSCAN' => $getKeyFromFirstArgument,
'HSTRLEN' => $getKeyFromFirstArgument,
/* commands operating on streams */
'XADD' => $getKeyFromFirstArgument,
'XDEL' => $getKeyFromFirstArgument,
'XRANGE' => $getKeyFromFirstArgument,
/* commands operating on HyperLogLog */
'PFADD' => $getKeyFromFirstArgument,
'PFCOUNT' => $getKeyFromAllArguments,
@@ -184,6 +211,9 @@ abstract class ClusterStrategy implements StrategyInterface
/* cluster */
'CLUSTER' => [$this, 'getFakeKey'],
/* control */
'ACL' => [$this, 'getFakeKey'],
];
}
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+2 -2
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -16,7 +16,7 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
/**
* This class implements an hashring-based distributor that uses the same
* algorithm of memcache to distribute keys in a cluster using client-side
* algorithm of memcached to distribute keys in a cluster using client-side
* sharding.
* @author Lorenzo Castelli <lcastelli@gmail.com>
*/
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+7 -6
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -87,7 +87,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
{
return array_reduce(
$this->slotRanges,
function ($carry, $slotRange) {
static function ($carry, $slotRange) {
return $carry + $slotRange->toArray();
},
[]
@@ -102,7 +102,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
public function getNodes()
{
return array_unique(array_map(
function ($slotRange) {
static function ($slotRange) {
return $slotRange->getConnection();
},
$this->slotRanges
@@ -192,7 +192,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
return array_reduce(
$intersections,
function ($carry, $slotRange) {
static function ($carry, $slotRange) {
return $carry + $slotRange->toArray();
},
[]
@@ -264,6 +264,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
foreach ($this->slotRanges as $slotRange) {
if (!$slotRange->hasSlot($slot)) {
$results[] = $slotRange;
continue;
}
if (static::isValidRange($slotRange->getStart(), $slot - 1)) {
@@ -287,7 +288,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
public function count()
{
return array_sum(array_map(
function ($slotRange) {
static function ($slotRange) {
return $slotRange->count();
},
$this->slotRanges
@@ -370,7 +371,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
{
usort(
$slotRanges,
function (SlotRange $a, SlotRange $b) {
static function (SlotRange $a, SlotRange $b) {
if ($a->getStart() == $b->getStart()) {
return 0;
}
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
+1 -1
View File
@@ -4,7 +4,7 @@
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.

Some files were not shown because too many files have changed in this diff Show More