Compare commits

..

1982 Commits

Author SHA1 Message Date
Till Krüss f49e13ee3a tag stable 2.4.0 2025-04-30 08:16:02 -07:00
Vladyslav Vildanov 6e3e2c0e78 [2.x] 8.0-RC2 testing (#1532) 2025-04-29 08:25:13 -07:00
Vladyslav Vildanov c35c422eda [2.x] Fix the problem of protocol loss during cluster MOVED/ASK (#1530)
Co-authored-by: Lynn Club <lynncho@live.com>
Co-authored-by: Lynn Club <10293848+lynnclub@users.noreply.github.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-04-17 08:49:19 -07:00
Till Krüss 1b5ed7d516 ZPOPMIN & ZPOPMAX prefix tests 2025-04-15 13:25:42 -07:00
vladvildanov 5df852f227 Added tests cases 2025-04-15 09:16:08 -07:00
Till Krüss 9418df1924 fix changelog branch check 2025-04-15 09:15:52 -07:00
Till Krüss 0e4b3829a7 fix changelog check 2025-04-15 09:07:26 -07:00
Till Krüss 65f6127fab add changelog check 2025-04-15 08:54:08 -07:00
Till Krüss 7ff24b19ae Merge pull request #1528 from predis/vv-2.x-readme-8.0-support
(2.x) Update README.md (Redis 8.0 support)
2025-04-14 09:11:07 -07:00
vladvildanov 2babfc91d7 Update README.md (Redis 8.0 support) 2025-04-14 18:42:11 +03:00
Till Krüss fdd52d0284 Tag v2.4.0-RC1 (#1523) 2025-03-24 10:07:15 -07:00
Vladyslav Vildanov 48a861053e Added new hash-field expiration commands (#1520)
* Added new hash-field expiration commands

* Changed argument default value

* Marked test as skipped

* Removed version restriction

* Updated CHANGELOG.md
2025-03-24 17:50:12 +02:00
messikiller 7bf1f6eb29 optimize redis cluster slotmap with compact slot range object (#1493)
Co-authored-by: heqiming <heqiming@kingsoft.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-03-19 09:24:53 -07:00
Vladyslav Vildanov 067b051900 Added missing FT._LIST and BITFIELD_RO commands (#1521)
* Added missing FT._LIST and BITFIELD_RO commands

* Codestyle fixes
2025-03-19 09:57:52 +02:00
Till Krüss df4a318b80 remove performance rambling from FAQ 2025-03-18 12:50:00 -07:00
Vladyslav Vildanov a904a3a273 Backport #1517 (#1518)
* Backport #1517

* Added versions restrictions

* Removed Relay for cluster with coverage

* Added phpcov package
2025-03-05 19:29:38 +02:00
Vladyslav Vildanov 8b240d15a5 Backport #1512 (#1515)
* Backport #1512
* Removed outdated test
2025-02-25 09:12:10 -08:00
Vladyslav Vildanov 02e2a7e1cc Added test coverage for compatibility with Redis 8.0 (#1513)
* Added testing with 8.0

* Removed old service

* Moved checkout stage above image

* Changed service name

* Override config options for Redis < 7

* Exported to github env

* Print major version output

* Added double quotes

* Test fixes

* Merge cluster and standalone infrastructure

* Removed separate cluster job and merge together with standalone

* Merge stack tests into main test job

* Fixed annotation condition

* tweaks

* Moved docker-compose.yml to root folder

* Added compose file to expected

* fixed in v0.10.1

* move docker file

* Added -all profile in docker-compose

* Removed redis official image, reduce test matrix, moved docker-compose.yml

* Revert docker-compose moving

* Added test coverage to verify compatibility with 8.0

* Mark tests as relay-incompatible

* Codestyle fix

* Marked as relay-incompatible

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-02-24 09:22:45 -08:00
Vladyslav Vildanov 9a22450a65 Added testing with 8.0 (#1510)
* Added testing with 8.0

* Removed old service

* Moved checkout stage above image

* Changed service name

* Override config options for Redis < 7

* Exported to github env

* Print major version output

* Added double quotes

* Test fixes

* Merge cluster and standalone infrastructure

* Removed separate cluster job and merge together with standalone

* Merge stack tests into main test job

* Fixed annotation condition

* tweaks

* Moved docker-compose.yml to root folder

* Added compose file to expected

* fixed in v0.10.1

* move docker file

* Added -all profile in docker-compose

* Removed redis official image, reduce test matrix, moved docker-compose.yml

* Revert docker-compose moving

* test php 8.0 and redis 4.0

* Revert changes related to official image

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-02-20 17:47:05 +02:00
zxin ac933cc548 Fix eval_ro cluster support (#1449) 2025-02-13 09:40:23 -08:00
Stephan 355faa099f ClientInterface: update watch command accepting string and string[] (#1476) 2025-02-13 09:39:51 -08:00
Radu Neacsu 549889b198 Mark GEOSEARCH as read-only to ensure execution on replica instead of… (#1481) 2025-02-13 09:39:19 -08:00
Denny Septian Panggabean d1c657aac5 refactor: use parallel on PHP-CS-Fixer (#1489) 2025-02-13 09:06:51 -08:00
Jan Nedbal b196809d3a Prevent named arguments runtime failure (#1509) 2025-02-12 09:13:01 -08:00
Till Krüss 52489ea703 Update CHANGELOG.md 2025-01-22 09:26:10 -08:00
Till Krüss ba66e22c92 bump year to 2025 2025-01-22 09:24:26 -08:00
Nicolas Chapleau 37aa6fb515 PHP 8.4.0 compatibility with call to stream_context_set_option (#1503)
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-01-22 09:08:12 -08:00
Till Krüss deed24c418 update year 2025-01-20 09:52:18 -08:00
Till Krüss 93895d02b6 Update composer.json 2025-01-16 08:48:12 -08:00
asafpamzn 275606843e Update composer.json 2025-01-16 08:48:12 -08:00
asafpamzn 976c9daa4f Update composer.json 2025-01-16 08:48:12 -08:00
Till Krüss 205ae75bd8 Update README.md 2025-01-16 08:48:12 -08:00
asafpamzn a5f46d0913 Update README.md to include that the client is compatible with Valkey
Added documentation clarifying that predis is compatible with Valkey. This information could be really helpful for developers using Valkey in their projects, saving them time and ensuring they are confident in their choice of predis.
2025-01-16 08:48:12 -08:00
Till Krüss b36c2f928f Update .editorconfig (#1494) 2024-11-25 09:58:29 -08:00
Vladyslav Vildanov bf6e97e7fb Fixed broken search test (#1492) 2024-11-22 07:54:01 -08:00
Till Krüss da40e1253c bump dev version [skip ci] 2024-11-21 12:14:32 -08:00
Till Krüss bac46bfdb7 Prepare v2.3.0 (#1491)
* mark as redis 7.4 compatible
* run more tests on 8.4
* add 2.3.0 changelog
* don't skip errors
2024-11-21 12:00:02 -08:00
Till Krüss 7631d317fd update year 2024-11-21 11:37:10 -08:00
Vladyslav Vildanov aaec13d074 Added support for INDEXMISSING and INDEXEMPTY arguments (#1464)
* Added support for INDEXMISSING and INDEXEMPTY arguments

* Added version restriction for test

* Codestyle fixes

* Updated test case to remove DIALECT 5

* Updated another test case

* Added correct versions restriction

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2024-11-21 10:19:51 -08:00
Vladyslav Vildanov 52bdcf0c1f Added test case for enhanced exact matching (#1466)
* Added test case for enhanced exact matching

* Added version restriction for test

* Updated test case to use Tag Field instead

* Codestyle fix

* Added edge to stack matrix

* Updated test case to switch DIALECT

* Updated version restriction
2024-11-21 10:00:34 -08:00
Vladyslav Vildanov 1726db0f47 Codestyle updates (#1485) 2024-10-22 09:16:07 -07:00
Vladyslav Vildanov 8fbd34c6b3 Added support for hash field expiration commands (#1456)
* Added support for hash field expiration commands

* Added support for HSETF, HGETF commands

* Removed non-printable ASCII chars from docs

* Removed more non-printable ASCII

* Fixed code style issues

* Extended codespell ignore words list

* Added FIELDS argument, fixes related to comments

* Codestyle fixes

* Fixed typo

* Removed HSETF, HGETF commands

* Added 7.4-rc1 to test matrix

* Fixed test with new response types

* Updated tests against 7.4-rc2 image
2024-10-15 10:01:39 -07:00
Christian Flothmann 0a92618fa1 keep key and value when filtering SET arguments (#1471) 2024-07-11 09:46:52 +03:00
Vladyslav Vildanov d8bb9ac46e Added support for new IGNORE filter (#1458)
* Added support for new IGNORE filter

* Fixed arguments to be mandatory

* Added more test cases

* Codestyle fixes

* Added missing test case

* Updated test cases

* Added additional timeout after index creation

* Fixed broken test and removed non-related functionality

* Fixed tests version requirements

* Updated error message
2024-07-11 09:35:52 +03:00
Vladyslav Vildanov 274e0c17cd Fixed bug with null arguments in SET command (#1470) 2024-07-09 14:10:58 +03:00
Vladyslav Vildanov c27dafa40d [2.x] Added Redis 7.4 commands interface changes (#1459)
* [2.x] Added Redis 7.4 commands interface changes

* Removed RESP3 test case

* Added 7.4-rc1 to test matrix

* Added 7.4.0-rc1 to stack matrix

* Added version restriction for test

* Updated stack image to edge
2024-07-05 16:36:58 +03:00
Vladyslav Vildanov 8c2aac4f66 Added GEOSHAPE field and test polygon search (#1467)
* Added GEOSHAPE field and test polygon search

* Added version restriction for test

* Added edge to stack amtrix

* Added same values assertion

* Codestyle changes
2024-07-05 16:16:16 +03:00
Alexander Mohorev 5d22ed775a Fix prefix for SMISMEMBER (#1468) 2024-07-02 12:41:07 -07:00
Vladyslav Vildanov c5fdfc81ef Added tests case with FLOAT16 and BFLOAT16 vectors (#1465)
* Added tests case with FLOAT16 and BFLOAT16 vectors

* Added version restriction for test

* Updated version restrictions
2024-06-28 11:18:07 -07:00
Markus Reinhold cbef71090b Fix prefixes for LMOVE and BLMOVE (#1455)
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2024-05-02 08:55:20 -07:00
mahshidhp 4dc72458e8 Fix prefix for GEOSEARCH (#1453) 2024-04-30 12:29:30 -07:00
Christian Flothmann e83b393e09 explicitly mark nullable parameters as nullable (#1448)
* explicitly mark nullable parameters as nullable
* add job to run tests with PHP 8.4
2024-04-30 12:14:13 -07:00
Till Krüss ed90750c1f fix prefixes for ZPOPMIN, ZPOPMAX and ZMSCORE (#1451) 2024-04-10 18:07:03 -07:00
René Højbjerg Larsen 45b18eb2e0 Filter out available slaves based on master-link-status flag (#1440) 2024-03-06 08:19:48 -08:00
Till Krüss d44f07339a Run tests under PHP 8.3 (#1396) 2023-10-25 10:08:55 -07:00
Till Krüss a9d18b182c tweak fixer rules 2023-10-24 09:17:43 -07:00
Tobias Bengtsson 5c8b19ebaa Fix operator precedence (#1405)
&& binds tighter than ?? so a parentheses is needed for desired result
2023-09-26 09:11:00 -07:00
Stephan 577bd39872 ClientInterface: using set with NX flag can return null (#1394)
Calling `$client->set('key', '1', 'EX', 7200, 'NX')` for a key that is already set will return null instead of Status
2023-09-14 09:44:52 -07:00
Jiří Bok 6372661dbf Make Relay work with Redis cluster (#1397) 2023-09-13 09:59:50 -07:00
Till Krüss 4846e2ab94 back to dev version 2023-09-13 09:55:14 -07:00
Sergei Predvoditelev 92b284967e Fix cmsincrby method annotation in ClientInterface (#1333) 2023-09-13 09:50:19 -07:00
Till Krüss 08d5298080 fix typos 2023-09-13 09:49:11 -07:00
Igor Malinovskiy d88153b63e Add 7.2 to supported Redis versions (#1367) 2023-09-13 09:47:35 -07:00
Till Krüss b1d3255ed9 tag v2.2.2 2023-09-13 09:42:03 -07:00
Till Krüss cbf394b882 Disable CLIENT SETINFO calls by default (#1399)
Add `client_info` parameter
2023-09-13 09:35:49 -07:00
Till Krüss c6bf644872 bump dev version 2023-09-13 09:34:52 -07:00
Vladyslav Vildanov 16bdd83d23 Added EXPIRETIME command to KeyPrefixProcessor (#1369)
* Added EXPIRETIME command to KeyPrefixProcessor

* Fixed test responses for Redis 7.2

* Marked test as relay-incompatible
2023-08-25 14:27:24 -07:00
Vladyslav Vildanov 912af82bfd Added support for CLUSTER container command (#1360)
* Added support for CLUSTER container command

* Codestyle fixes
2023-08-17 09:34:01 +03:00
Vladyslav Vildanov 2d74db1bde Changes related to Redis 7.2 image update (#1366)
* Added new assertion, fixed RESP3 JSON responses and versions

* Removed expectations for error messages

* Changed tests group for RESP3 not supported tests

* Removed 3.x test case

* Added missing test decorators

* Fixed typo

* Removed redisgraph module upload, as not a part of a redis-stack anymore
2023-08-16 08:18:45 -07:00
Till Krüss c5ee202179 bump version (#1365)
* bump version

* Update Client.php
2023-08-15 16:06:03 -07:00
Till Krüss 5f2b410a74 Update CHANGELOG.md (#1364)
* Update CHANGELOG.md

* Update CHANGELOG.md

* Update CHANGELOG.md
2023-08-15 16:01:46 -07:00
Vladyslav Vildanov f6cf2afe47 Updated CHANGELOG.md (#1363)
* Updated CHANGELOG.md

* Added quotes to CHANGELOG.md

* Codestyle fix
2023-08-15 08:43:46 -07:00
Vladyslav Vildanov 311cd2b79e Added support for WAITAOF command (#1357)
* Added support for WAITAOF command

* Added call to parent setUp method
2023-08-14 09:18:19 +03:00
Vladyslav Vildanov ffd31cfdef Added missing redis-stack commands to KeyPrefix processor (#1358) 2023-08-10 18:57:16 +03:00
Vladyslav Vildanov 1b2fd527ed Added support for Redis 7.0 arguments (#1359) 2023-08-10 18:57:00 +03:00
Vladyslav Vildanov 4172d2265f Client set name and version on connection (#1347)
* Added client metadata on server connection

* Added try...catch around server exception to supress CLIENT command errors

* Added exclusion for Relay connection
2023-08-03 09:04:04 +03:00
Vladyslav Vildanov a3311d6869 2.2.1 version changes (#1349) 2023-08-03 09:03:21 +03:00
Vladyslav Vildanov df14e11c3a Added support for tests running against redis cluster (#1236)
* Added support for tests running against redis cluster

* Test coverage

* Added comment about master nodes

* Codestyle fix

* Revert changes

* Revert DBNUM

* Added cluster endpoints to relay tests env configuration

* Exclude cluster tests from relay tests environment

* Removed TODO comment

* Changed cluster image version to unstable

* Updated configuration to match unstable cluster

* Fixed path

* Updated cluster CI configuration

* Removed redundant flag

* Removed backslash

* Updated file path

* Updated file path variable

* Added docker cluster initialization as additional step

* Run cluster tests as separate workflow

* Codestyle fixes

* Updated exported files

* Added additional timeout so cluster image could be settled

* Added support for different cluster image, use docker compose for cluster tests CI

* Remove unused flag

* Removed variable from volume path

* Added sleep timeout to allow docker setup after running

* Added timeout before tests run

* Updated linter settings

* Include indent changes for.sh files

* Added missing coverage

* Revert expected files and mark docker folder as exclusion

* Specify folder itself as excluded

* Moved cluster tests as separate job in tests.yml

* Updated name to contain cluster word

---------

Co-authored-by: Chayim <chayim@users.noreply.github.com>
2023-07-24 10:21:43 +03:00
Vladyslav Vildanov 7c2e8e01d8 Added support for FUNCTION KILL, FUNCTION LIST, FUNCTION STATS commands (#1334)
* Added support for FUNCTION KILL, FUNCTION LIST, FUNCTION STATS commands

* Marked tests as relay-incompatible
2023-07-12 09:58:00 +03:00
Vladyslav Vildanov 0b6ab4dea4 Added support for CLIENT NO-EVICT command (#1335) 2023-07-12 09:57:42 +03:00
Vladyslav Vildanov dd64569e06 Added support for FUNCTION DUMP, FUNCTION FLUSH, FUNCTION RESTORE commands (#1332) 2023-07-03 10:41:32 +03:00
Vladyslav Vildanov 90da582efc Fixed bug with incorrect multiple words processing (#1325)
* Fixed bug with incorrect multiple words processing

* Convert subcommand string to lower case

* Update SubcommandStrategyResolver.php

* Added test coverage

* Codestyle fixes

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-06-21 12:00:58 +03:00
Till Krüss 732abc88a2 Update CHANGELOG.md 2023-06-14 13:42:52 +03:00
Till Krüss 33b70b971a Update CHANGELOG.md 2023-06-14 13:37:31 +03:00
Vladyslav Vildanov e46d56c45c Fixed subcommand test bug (#1313) 2023-06-08 11:33:25 -04:00
Vladyslav Vildanov c57a6744bb Added support for JSON.MSET command (#1307) 2023-06-08 17:35:04 +03:00
Vladyslav Vildanov df83c94bb3 Added support for JSON.MERGE command (#1304) 2023-06-08 12:16:14 +03:00
Vladyslav Vildanov a711ef96e2 Added GETDEL command to KeyPrefixProcessor (#1306)
* Added GETDEL command to KeyPrefixProcessor

* Added test coverage

* Codestyle fixes

* Added timeout after FT.CREATE call
2023-06-08 11:32:05 +03:00
Vladyslav Vildanov 3c322fc4e3 Codestyle changes related to php-cs-fixer update (#1311)
* Codestyle changes

* Added missing type-hints
2023-06-07 17:05:36 +03:00
Till Krüss 95c23fb94d tag 2.2.0-RC1 2023-05-09 10:45:20 -07:00
Till Krüss 946c4b7bd7 [v2.x] Relay support (#1263) 2023-05-09 10:39:00 -07:00
Vladyslav Vildanov 538c65946d Added timeout to prevent search before create (#1269) 2023-05-03 11:00:31 -07:00
Till Krüss e8ea05dafe spacing 2023-04-19 13:52:53 -07:00
Nicolas Grekas bf2075a176 Add missing @return annotations (#1265)
* Add missing `@return` annotations

* formatting

* formatting

* Update ProcessorChain.php

* Update Handler.php

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-04-19 13:51:42 -07:00
Till Krüss d2cd99492d don't export bin 2023-04-13 09:51:16 -07:00
Vladyslav Vildanov 971e47672d Added Redis stack support (JSON, Search, TimeSeries, Bloom) (#1253) 2023-04-11 08:09:14 -07:00
Till Krüss f9b755ece9 changes [skip ci] 2023-04-05 08:33:26 -07:00
Jess Archer 98d4f80263 Add missing stream key prefixes (#1230)
* Added missing stream key prefixes

* Tested stream command key prefixing
2023-03-29 07:03:45 -07:00
Vladyslav Vildanov 0e019cc08d Extended core support by implementing ACL SETUSER, GETUSER, DRYRUN (#1193)
* Added support for ACL GETUSER, SETUSER, DRYRUN commands

* Change test to support Redis > 6.0.0

* Removed selectors check
2023-03-15 14:57:12 +02:00
Till Krüss b898172009 typo 2023-03-12 09:22:07 -07:00
Vladyslav Vildanov f68543af37 Extended core support by implementing FCALL_RO command (#1191) 2023-03-12 08:52:20 -07:00
Till Krüss a77a43913a tag v2.1.2 2023-03-02 10:32:04 -08:00
Till Krüss fea402743f Deprecate webdis and phpiredis (#1179)
* Deprecate webdis and phpiredis

* remove space
2023-02-28 13:09:56 -08:00
Vladyslav Vildanov 84844acb93 Added CODEOWNERS file (#1181)
* Added CODEOWNERS file

* Update CODEOWNERS

* Applied whole Redis commands path as @vladvildanov codeowner

* Set @predis/team as Redis commands codeowners

* Update CODEOWNERS

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-02-28 13:07:06 -08:00
Till Krüss 26c625230f match MasterSlaveReplication (#1175)
* match `MasterSlaveReplication`

also the name of this method 😬

* Update SentinelReplication.php
2023-02-21 08:30:43 -08:00
David Bomba 8ef75ba6b2 Add option for disabling reads to slaves in replication topologies (#1168)
* Add option for disabling reads to slaves in replication topologies

(cherry picked from commit e132c312a9)

* remove empty line

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-02-21 08:15:58 -08:00
Stephan 8a5ced5251 Fix return type of ReplicationInterface::getSlaves (#1111) 2023-02-08 07:26:27 -08:00
Vladyslav Vildanov 29350952d0 Added stream commands to KeyPrefixProcessor (#1051)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-31 08:50:14 -08:00
Vladyslav Vildanov 98222f47b0 Added support for container commands (#1049)
* Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL

* Changed ContainerInterface and AbstractContainer

* Re-implement logic of abstract methods

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-31 08:48:48 -08:00
Till Krüss 38e955bc26 fix deprecated call 2023-01-29 11:58:46 -08:00
Vladyslav Vildanov db65e5ebd3 Extended core support by implementing SORT_RO command (#1044)
* Added support for SORT_RO command

* Codestyle fixes

* Added command description

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-29 11:38:30 -08:00
Vladyslav Vildanov 50e005bfe3 Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) 2023-01-25 08:00:23 -08:00
Vladyslav Vildanov c541617333 Added support for new arguments for BITPOS, BITCOUNT commands (#1045) 2023-01-25 07:59:44 -08:00
Till Krüss 0a8e0c2f96 remove CONTRIBUTING file 2023-01-21 17:20:25 -08:00
Till Krüss 793de36822 Update README.md 2023-01-21 17:17:25 -08:00
Till Krüss fa13640ddd try another format 2023-01-21 17:05:13 -08:00
Viktor Szépe 5331d943fe Upgrade static analysis to PHPStan level 2 (#1043)
* Upgrade static analysis to PHPStan level 2

* Fix CS and CI

* Fix coverage path

* Start debugging

* Stop debugging
2023-01-21 17:03:53 -08:00
Viktor Szépe 74d5ad22dd Add Coverage badge to README (#1042) 2023-01-21 15:59:53 -08:00
Till Krüss a04bcb94fc try different license format 2023-01-21 14:10:06 -08:00
Till Krüss 9f77e5178f fix license header 2023-01-21 14:08:25 -08:00
Viktor Szépe ac259bdb6f Add complete CI (#1036)
* Add complete CI

* Fix CI

* Fix spelling

* Fix indentation

* Fix CI

* Fix CI

* Revert disabling unit tests

* Add coverage driver to CI

* Start coverage debugging

* Fix debugging
ignored, and an empty message aborts the commit.

* Stop debugging

* Move TODO-s from source to GitHub issues

* Ignore too long lines in certain files

* Revert requiring php-parallel-lint/php-parallel-lint

* formatting

* try shorter formatting

* formatting

* fix syntax

* try two paths?

* Update .editorconfig

Co-authored-by: Viktor Szépe <viktor@szepe.net>

* indentation

* make it a group

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-21 13:22:13 -08:00
Till Krüss 6e45ca5154 Create README.md 2023-01-21 13:17:31 -08:00
Viktor Szépe c201af5ad3 Fix PHPStan level 2 problems (#1025)
* Fix almost all PHPStan level 2 problems

* Fix master loop and remove empty line

* Fix variadic functions

* Fix CS

* Disable xdebug in CI and improve a condition

* Fix CI fix
2023-01-20 14:20:53 -08:00
Vladyslav Vildanov 1c6c5feb3a Extended core support by implementing EVALSHA_RO command (#1034) 2023-01-20 11:15:39 -08:00
Vladyslav Vildanov a8c5794b8a Added support for LCS command (#1035) 2023-01-20 11:14:50 -08:00
Vladyslav Vildanov ccc2860ad2 Added support for EVAL_RO command (#1032) 2023-01-20 11:13:46 -08:00
Till Krüss 1cd78095e6 drop phpcs version to 3.3 for php 7.2 support 2023-01-19 09:49:27 -08:00
Till Krüss f6f4830b3c tweak composer config 2023-01-19 09:28:33 -08:00
Vladyslav Vildanov e3ad353125 Extended Sets support by implementing SINTERCARD command (#1027)
* Added support for SINTERCARD command

* Codestyle fixes, added support for php-cs-fixer

* Moved php-cs-fixer dependency to dev

* Removed trailed comma

* Added support for php 7.2

* update scripts

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-19 09:17:15 -08:00
Vladyslav Vildanov e00d1a0bd3 Added support for EXPIRETIME command (#1029)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-19 09:15:20 -08:00
Vladyslav Vildanov 64604de751 Added support for PEXPIRETIME command (#1031)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-19 09:14:55 -08:00
Viktor Szépe 20dcb4bb73 Fix LICENSE file (#1026)
GitHub has problems with it
`curl "https://api.github.com/repos/predis/predis" -H "Accept: application/vnd.github.drax-preview+json" -s | jq '.license'`
2023-01-18 16:03:08 -08:00
Fran Moreno 3daf75508d Add phpstan level 0 (#1022)
* Remove unused arguments

* Fix return types

* Removed unused parameter and argument

* Add phpstan job

* merge files

* Delete phpstan-baseline.neon

* Delete static-analysis.yml

* merge workflows

* Update composer.json

* format yaml

* install composer reps

* fix yaml

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-18 13:33:51 -08:00
Till Krüss 7a4b3d1d0f Update .editorconfig 2023-01-18 13:27:04 -08:00
Till Krüss 3cf958580a Update .editorconfig 2023-01-18 13:26:53 -08:00
Fran Moreno d6dc6e51e1 Add CS job (#1024)
* Add CS job

* Apply PHP71Migration ruleset
2023-01-18 10:02:26 -08:00
Till Krüss 113145f306 more code formatting 2023-01-17 15:08:18 -08:00
Till Krüss 47a7cbc862 unify code formatting 2023-01-17 15:08:18 -08:00
Till Krüss 3c8a811ca3 update examples 2023-01-17 15:08:18 -08:00
Till Krüss f4bd6d44b1 update cs-fixer config 2023-01-17 15:08:18 -08:00
Till Krüss 6b6179ee44 don’t run tests twice 2023-01-17 15:08:18 -08:00
Till Krüss 82791e55e1 format tests 2023-01-17 15:08:18 -08:00
Till Krüss ea7698e12f use single quotes 2023-01-17 15:08:18 -08:00
Till Krüss af2e5cc553 order imports 2023-01-17 15:08:18 -08:00
Till Krüss b1009f46ac unify spacing 2023-01-17 15:08:18 -08:00
Till Krüss a09da4f3b0 trailing multiline commas 2023-01-17 15:08:18 -08:00
Till Krüss 06c00ac43f import global namespace 2023-01-17 15:08:18 -08:00
Till Krüss f3deda22cd no @link tags 2023-01-17 15:08:18 -08:00
Till Krüss c412594217 align phpdoc vertically 2023-01-17 15:08:18 -08:00
Till Krüss cc40219268 use short array syntax 2023-01-17 15:08:18 -08:00
Till Krüss 31b65f614b Remove @author tags 2023-01-17 13:41:35 -08:00
Till Krüss c9babb1984 update copyright comments 2023-01-17 13:41:35 -08:00
Till Krüss c2af9427c5 update MIT license template 2023-01-17 13:41:35 -08:00
Till Krüss c5b60884e8 tag v2.1.1 2023-01-17 12:57:35 -08:00
Till Krüss 836ab07d40 Fix support options array in ZINTERSTORE and ZUNIONSTORE (#1018)
* support old options array

* fix zinterstore as well

* single override
2023-01-17 12:50:15 -08:00
Fran Moreno 2bfc8a9316 Fix Client template (#1017) 2023-01-17 12:48:39 -08:00
Till Krüss d21576669d remove phpiredis suggestion 2023-01-17 09:42:23 -08:00
Till Krüss 65fe24e346 bump version 2023-01-17 09:42:15 -08:00
Till Krüss fbf270156f tweak workflow formatting 2023-01-16 15:33:05 -08:00
Till Krüss 24630fbd5b tag 2.1.0 2023-01-16 15:21:30 -08:00
Till Krüss bded73f516 tweak release draft template [skip ci] 2023-01-16 15:21:19 -08:00
Till Krüss 6a3f4a4c08 Update release-drafter-config.yml 2023-01-16 15:12:32 -08:00
Vladyslav Vildanov 47896f1be7 Extended core support by implementing BLMPOP command (#1015)
* Added support for LMPOP command

* Added support for BLMPOP command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-16 08:46:59 -08:00
erikn69 586b039289 Fix builds badge (#1014) 2023-01-16 08:45:19 -08:00
Vladyslav Vildanov d1acca607e Added support for LMPOP command (#1013)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-16 08:45:04 -08:00
Vladyslav Vildanov 721c829042 Extended server functionality by implementing FAILOVER command (#875)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added test coverage for tratis

* Added support for FAILOVER command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-29 12:19:17 -08:00
Vladyslav Vildanov b8cc7c643a Extended Key Space support by implementing COPY command (#866)
* Added support for COPY command

* Revert getCLient signature changes, used createClient instead

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-29 12:18:08 -08:00
Vladyslav Vildanov b47aa7ad3a Extended Geospatial support by implementing GEOSEARCHSTORE command (#873)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added support for GEOSEARCHSTORE command

* Added test coverage for tratis

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Chayim <chayim@users.noreply.github.com>
2022-12-29 12:16:51 -08:00
Vladyslav Vildanov bb65b31580 Extend Geospatial support by implementing GEOSEARCH command (#867)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added test coverage for tratis

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Chayim <chayim@users.noreply.github.com>
2022-12-28 09:10:03 -08:00
Vladyslav Vildanov e540ca062b Added support for SISMEMBER command (#871)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:18:50 -08:00
Vladyslav Vildanov 9c543ef5b1 Added support for HRANDFIELD command (#870)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:18:33 -08:00
Vladyslav Vildanov 83fb0020a1 Added support for GETEX command (#872)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:17:24 -08:00
Vladyslav Vildanov 4a77aea9ef Added support for GETDEL command (#869)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-20 09:32:58 -08:00
Vladyslav Vildanov 72bc11eb63 Extended Sorted Set support by adding ZINTER command (#859)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Added support for ZINTER command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-14 08:54:30 -08:00
Vladyslav Vildanov f26fd899f9 Extend Sorted Set support by implementing BZPOPMAX command (#864)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Keys trait to handle cases when no numkeys modifier needed

* Added support for BZPOPMIN command

* Added command link and description

* Added support for BZPOPMAX command

* Added absract command to fix inheritance chain

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 10:26:47 -08:00
Vladyslav Vildanov 65447807ed Extended Sorted Set support by adding ZUNION command (#860)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Added support for ZUNION command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 08:41:56 -08:00
Vladyslav Vildanov 5418cd5813 Extended Sorted Set support by adding BLMOVE command (#865)
* Added support for LMOVE command

* Added support for BLMOVE command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 08:38:35 -08:00
Vladyslav Vildanov bc5892e260 Extended Sorted Set support by adding BZPOPMIN command (#862)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Keys trait to handle cases when no numkeys modifier needed

* Added support for BZPOPMIN command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:38:26 -08:00
Vladyslav Vildanov 7c0cc7bdbe Extended Sorted Set support by adding ZINTERCARD command (#861)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Limit trait to handle integer values

* Updated Limit trait to return previous arguments if limit argument isn't set

* Added support for ZINTERCARD command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:38:06 -08:00
Vladyslav Vildanov 87ecd7bde2 Added support for LMOVE command (#863)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:37:28 -08:00
Vladyslav Vildanov f9e77a0562 Refactored ZUNIONSTORE, ZINTERSTORE, removed Numkeys trait, improved Withscores response parsing (#858) 2022-12-09 07:37:22 -08:00
Vladyslav Vildanov d2b05ff58a Added mixin annotations for traits (#835)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-07 09:19:04 -08:00
Chayim e24ecbbf90 Fixing the release drafter, to honour the main branch (#857) 2022-12-07 12:08:16 +02:00
Vladyslav Vildanov 9f3bdd5616 Extend Sorted Set support by implementing ZRANGESTORE command (#829)
* Added support for ZRANGESTORE command

* Added missing test coverage, added new filter method

* Added test coverage for new traits

* Updated offset for unexpected value tests

* Added missing offset

* Removed version annotation for inconsistency

* Update ZDIFF.php

* Update ZRANGESTORE.php

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-12-06 08:40:06 -08:00
Chayim 57a24413c2 Adding the release drafter for release management (#811) 2022-12-05 09:25:47 -08:00
Vladyslav Vildanov 0e6126ba9d Added support for BZMPOP command (#833) 2022-12-05 08:33:43 -08:00
Vladyslav Vildanov 7904fed6da Added support for ZMPOP command (#831)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-01 12:10:20 -08:00
Vladyslav Vildanov cfd6f030bc Extend Sorted Set support by implementing ZDIFFSTORE command (#828)
* Added support for ZDIFF, added new WITHSCORE trait

* Added trait to resolve numkeys argument

* Added trait for unpacking keys array

* Added static binding for Numkeys trait

* Added ZDIFFSTORE command support

* Changed access modifier type to more strict

* Removed version annotation for inconsistency

* Update ZDIFFSTORE.php

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-11-30 13:23:08 -08:00
Vladyslav Vildanov 35d18d739a Added response parser for WithScore trait (#830)
* Added response parser for WithScore trait

* Added test coverage for new method

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-11-30 13:20:56 -08:00
Vladyslav Vildanov 573c54ac4c Extend Sorted Set support by implementing ZDIFF command (#826)
* Added support for ZDIFF, added new WITHSCORE trait

* Added trait to resolve numkeys argument

* Added trait for unpacking keys array

* Added static binding for Numkeys trait

* Changed access modifier type to more strict

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-11-28 13:16:30 -08:00
Vladyslav Vildanov 169604bf74 Extend Sorted Set support by implementing ZRANDMEMBER command (#825)
* Added support for ZRANDMEMBER, added test coverage

* Changed key to more specific on exception testing

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
2022-11-21 08:37:04 -08:00
vladvildanov 94bd54b2af Extend Sorted Set support by implementing ZMSCORE (#823) 2022-11-17 07:48:16 -08:00
Josh England bdebad7d62 added annotations to suppress PHP 8.1 return type deprecation warning… (#810)
* added annotations to suppress PHP 8.1 return type deprecation warning for `IteratorAggregate::toIterator()`

* move import

Co-authored-by: Josh England <joshua.england@trinet.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-11-02 17:07:32 -07:00
Till Krüss 1a411d2ad7 back to dev version 2022-10-11 09:57:28 -07:00
Till Krüss 1400689df8 switch to actions/checkout@v3 [skip ci] 2022-10-11 09:56:57 -07:00
Till Krüss ff59f74581 bump version 2022-10-11 09:52:29 -07:00
Mehmet Tolga Avcioglu 1a0eb7ee85 sentinel default to no password when replica authentication is used (#807)
* set default nopass if password is not provided

* remove debug output

* added tests for noauth sentinel

* Update SentinelReplication.php

Co-authored-by: Mehmet Tolga Avcioglu <mehmet.avcioglu@pusula.net.tr>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-10-06 08:14:47 -07:00
Tobias Bengtsson bb6c1a7b6d Add partial support for Stream commands (#804)
Adds support for the following commands not related to groups/consumers:
XADD, XDEL, XLEN, XRANGE, XREVRANGE, XTRIM.
2022-09-27 09:39:17 -07:00
streamingsystems 42c33a406f Check if socket is resource before reading (#802) 2022-09-18 15:01:02 -07:00
Stefano Borghi 7ad74217c2 check resource before writing, w/ test (#800) 2022-09-16 17:03:13 -07:00
Alexandru Pătrănescu 72d7675563 improve PHP 8.2 support (#797)
* use static::class . '::<method>' instead of 'static::method'

* extract concatenation so it can be improved easier at a later point

one improvement at some point could be to replace static::class . '::<method>' with static::<method>(...) in PHP 8.1+

Co-authored-by: Alexandru Patranescu <alexandru.patranescu@payu.com>
2022-09-08 11:25:37 -07:00
Till Krüss 8b5fa92856 mention php version [no ci] 2022-09-06 07:34:14 -07:00
Till Krüss 076a62e3d3 bump version to 2.0.2 2022-09-06 07:32:44 -07:00
Dries Vints 85dc1752b7 PHP 8.2 Support (#796) 2022-09-06 07:13:46 -07:00
Till Krüss 7683215023 bump tag to v2.0.1 2022-09-04 14:57:36 -07:00
Till Krüss dd4ddf6504 Update CHANGELOG.md 2022-08-03 11:53:59 -07:00
Till Krüss 6468e6cc2e Update CHANGELOG.md 2022-08-03 11:51:22 -07:00
digital2real 12f6d30502 Add retry logic to support temporary redis cluster failure (#788)
* Add retry logic to support temporary redis cluster failure

* formatting

* Use exponential backoff retries.
$minRetryAfter cant be changed if needed with RedisCluster::setMinRetryAfter

* fix formating

* (hotfix) formaing + import import  \Predis\Response\Error and \Predis\Connection\ConnectionException

* Update RedisCluster.php

* formatting

* tweaks

* Update RedisCluster.php

* Update RedisCluster.php

* Update RedisCluster.php

* Update unit tests regarding renaming of "retryInterval"

* spacing

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-08-03 11:49:56 -07:00
Linc a602fc7425 Fix sentinel reconnect issue on long-running PHP processes (#784)
* Fix no sentinel server available for autodiscovery on Swoole

* Fix errors in PHPUnit 9.5

the reason: https://github.com/sebastianbergmann/phpunit/commit/68582043e149039cfa3596b42ed35753dcf54fb2?fbclid=IwAR1qy1jFNFeJ3hUt5k7XAflqyCTUTWZhEqVSeizkybVHUEqXjBZ1gJM739U

* add restart sentinel test
2022-07-12 09:44:28 -07:00
John Paul E. Balandan, CPA 4ec74cc5fe Declare $parameters property of Predis\Connection\Parameters (#781) 2022-06-29 07:58:14 -07:00
BrightQi 78fd4cb998 bugfix for srem type to accept array #779 (#780)
* bugfix for srem  type to accept array #779

* add test to test SREM accept members as array type #779
2022-06-28 08:23:35 -07:00
Tomáš Fedor 2a8dd6a7f1 Add array as possible return type to spop (#774)
* Add array as possible return type to spop

* Update ClientInterface.php

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-06-14 19:59:10 -07:00
Jayin Taung 7d7b3416a8 Add example for installing predis by Composer (#772)
* Add example for installing predis by Composer

* Update README.md

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-06-13 07:54:46 -07:00
Till Krüss 99c253733d tweak changelog format 2022-06-08 06:14:56 -07:00
Till Krüss 69bb8fa082 bump version to v2.0.0 stable 2022-06-08 06:11:35 -07:00
Josias Montag e5221fa13b Allow PubSub / MultiExec with Replication 2022-05-28 08:18:01 -07:00
Till Krüss 15244c9642 cleanup readme 2022-05-26 12:01:30 -07:00
Till Krüss 4cc119a03c tag 2.0.0-beta.1 2022-05-26 11:48:12 -07:00
Till Krüss 619890f715 fix test 2022-05-26 11:45:35 -07:00
Till Krüss b060d43157 port changes from v1.1 branch 2022-05-26 11:29:45 -07:00
Till Krüss a5ab2bce6b truncate changelog 2022-05-26 11:12:41 -07:00
Hubert Lenoir 89f20dc968 add TOUCH command (#767) 2022-05-23 08:46:48 -07:00
Michal Lulco 6af5394a89 Added ZPOPMIN and ZPOPMAX (#758)
* Added ZPOPMIN and ZPOPMAX

* Added ZPOPMIN and ZPOPMAX

* Applied patch
2022-05-16 08:00:06 -07:00
Zaher Ghaibeh c508086b0e remove redundant variables (#765) 2022-05-15 09:51:28 -07:00
Zaher Ghaibeh 3c01ccc94c Testing code against Redis 7 (#764)
* redis 7 init

fix typo

add the new returns

* having a full sentence for the exception message
2022-05-12 12:23:51 -07:00
Jordi Boggiano e382bedb27 Update method tags (#762) 2022-05-12 09:13:06 -07:00
Zaher Ghaibeh a2449da7c8 PHP 8.1 tests (#760)
* - init 8.1 tests
- adding `#[\ReturnTypeWillChange]`
- Fix deprecation message: strlen(): Passing null to parameter #1 ($string) of type string is deprecated
- null is not allowed
- cleanup
- default values should be same type

* Mirror `v1.1` fixes for these files

* add null as type too since we also accept null as default value

Signed-off-by: Zaher Ghaibeh <zaher@zaher.dev>

* revert back to assertNull

* Update CHANGELOG

* Update CHANGELOG.md

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-05-07 08:03:53 -07:00
♚ PH⑦ de Soria™♛ b3a5bdf940 Remove invalid input for actions/cache (#737)
https://github.com/actions/cache/blob/main/examples.md#php---composer
2022-01-14 08:22:59 -08:00
Georges.L 4c1aada5ae Updated set, setex, setexp type hint (#710) 2021-09-08 09:05:55 -07:00
Mehdi Baaboura 54775a0295 Update LICENSE (#704) 2021-07-19 09:27:37 -07:00
Ruslan Bekenev 367bd72a0b Test optional count argument for LPOP (#700)
First added in Redis 6.2
2021-06-09 09:46:24 -07:00
Till Krüss 1d7ccb64ab Merge pull request #670 from charescape/patch-1
Update README.md
2021-04-04 10:33:08 -07:00
Till Krüss e29ae9065f some spacing 2021-04-04 10:31:53 -07:00
Till Krüss 64fc7774c6 stick to PHPUnit 9.4.* for now
`getAnnotations()` was removed in 9.5:

https://github.com/sebastianbergmann/phpunit/commit/68582043e149039cfa3596b42ed35753dcf54fb2
2021-04-04 10:31:45 -07:00
Till Krüss 554c36b329 Merge pull request #688 from open-source-contributions/improve_assertions
Improve PHPUnit assertions
2021-04-04 10:20:39 -07:00
Till Krüss be9d477564 fix for Redis 6 error message 2021-04-04 10:16:44 -07:00
Till Krüss 0e4e8f41cc fix 2021-04-04 10:14:13 -07:00
Till Krüss aa0c30809b fix test when using Redis 6 2021-04-04 10:11:29 -07:00
Peter 20f8faee6f Improve PHPUnit assertions 2021-04-04 23:30:14 +08:00
Till Krüss aa436263f8 Merge pull request #684 from andrew-demb/patch-2
CommandInterface::parseResponse() can accept array and null argument
2021-03-09 08:43:59 -08:00
Till Krüss 3c8856b05a Merge pull request #683 from andrew-demb/patch-1
Status::get() always return self
2021-03-09 08:43:39 -08:00
Andrii Dembitskyi d935f6e5c2 CommandInterface::parseResponse() can accept array and null argument 2021-03-09 07:15:08 -05:00
Andrii Dembitskyi 87fcc69e7a Status::get() always return self 2021-03-09 07:09:15 -05:00
charescape 407ddeca92 Update README.md 2020-11-12 11:39:48 +08:00
Till Krüss 338ba6d73d Merge pull request #665 from danwall/patch-1
Fix typo
2020-09-26 19:08:13 -07:00
Dan Wall 25db9bfec5 Fix typo 2020-09-26 11:52:44 +10:00
Daniele Alessandri 0e9aeee90f Fix PhpiredisSocketConnection for PHP 8.
Removed is_resource() check as socket_create() now returns an object.
2020-09-20 15:29:16 +02:00
Daniele Alessandri f07f8d01fe Where the heck did my beloved flat-style for badges go? 2020-09-10 21:51:36 +02:00
Daniele Alessandri f133a3660c Various updates to options class and interface. 2020-09-10 21:23:45 +02:00
Daniele Alessandri fa44ff0846 Improve code used for client initialization.
Also provide a more detailed description of methods in phpdocs.
2020-09-10 21:23:10 +02:00
Daniele Alessandri 985343a992 Merge remote-tracking branch 'github/pr/656' into main
Local branch v2.0-clientoptions-aggregateconnections
2020-09-10 21:19:52 +02:00
Daniele Alessandri d954e9f43f Merge branch 'v1.1' into main 2020-09-10 21:16:58 +02:00
Daniele Alessandri 9e5371f5ce Back to development.
[ci skip]
2020-09-10 15:40:46 +02:00
Daniele Alessandri 8ca99f91e4 Update CHANGELOG and bump VERSION (v1.1.5) 2020-09-10 15:35:23 +02:00
Qusonann c778843b0d Fix zrevrangebyscore pipeline annotation
[ci skip]
2020-09-09 23:42:03 +02:00
Daniele Alessandri b3b81fce9f Merge remote-tracking branch 'github/pr/657' into main 2020-09-09 23:39:18 +02:00
Qusonann ccc2ea24cb Fix zrevrangebyscore pipeline annotation 2020-09-08 21:23:35 +03:00
Daniele Alessandri dca201291c Fix CHANGELOG for broken Markdown rendering.
[ci skip]
2020-09-05 16:50:25 +02:00
Daniele Alessandri 2e76410e65 Support password-based authentication for sentinel instances.
Password-based authentication for sentinels has been added in Redis 5.
Predis was actively ignoring any "password" parameter for sentinels when
creating connections to them to avoid issues when this parameter is set
in the default "parameters" array passed via client options, as they are
applied to **every** connection created by Predis (see #346).

We need to find a better way to specify a common password for sentinels
to be handled in a different way than the ones for Redis nodes. For now
each sentinel node protected by password must have an explicit password
set in its parameters list even if this password, by design, is the same
for all sentinels. Since we cannot use default "parameters" as explained
above but we still need to pass a common value for all sentinels an idea
could be using a dedicated client option like we did with "service", but
we will see later.

In this commit we also explicitly reset any "username" parameter as it
would trigger an `AUTH $username $password` but sentinels do not support
ACL authentication.

Fixes #594.
2020-09-05 16:25:06 +02:00
Daniele Alessandri ca468b785c Throw exception on FALSE passed to "replication" option.
While "replication" do accept values evaluating to TRUE, the same cannot
be said for values evaluating to FALSE. TRUE is used to tell the client
that we want replication handled using the default backend for unmanaged
replication setups. For using redis-sentinel the "sentinel" string value
must be passed.

Setting "replication" to FALSE led to a failure (and a PHP warning) on
client initialization because this condition was not handled properly.
Being able to do so would not make sense anyway: when the client does
not need to be set up to rely on replication, users simply have to omit
the option. Furthermore, users must always specify either "replication"
or "cluster" and not both with one of them set to FALSE.

Unfortunately options for aggregate connections in Predis v1.1 are a bit
of a mess, they did not scale well with the addition of new features and
are also quite inconsistent (e.g. "cluster" does not accept TRUE).

This has been largely fixed in Predis v2.0-dev but required implementing
a few breaking changes. It also means that this change does not need to
be ported to the main branch.

Addresses #381 using a different approach.
2020-09-05 14:18:30 +02:00
Daniele Alessandri b1ea4374d4 [tests] Fix the very few remaining warnings emitted by test suite.
Basically assertMatchesRegularExpression() replaces assertRegExp() which
has been deprecated since PHPUnit 9.1 and will be removed in PHPUnit 10,
unfortunately we still depend on PHPUnit 8.4 to support PHP 7.2 and this
version does not have assertMatchesRegularExpression() so we implemented
it in our base testcase class with a fallback to the old assertRegExp()
when tests are executed on older versions of PHPUnit.
2020-09-04 21:00:46 +02:00
Daniele Alessandri 4a7fb55058 [tests] Add utility method to skip tests on CI environment.
We still have disabled all PUB/SUB related tests on CI for now, until we
understand why they fail at random.

Backported from main branch (ref. 5133706, f723f67, eb8a89e)
2020-09-04 18:42:38 +02:00
Daniele Alessandri fdf663ebba Fix WebdisConnection with IPv4 hosts.
Apparently something changed since last time in cURL internals and now
an IPv4 wrapped by square brackets (which are used for IPv6 addresses)
returns a malformed request error.

m
2020-09-04 18:06:36 +02:00
Daniele Alessandri 880ad09cad Restore broken change from a few years ago.
After this change there was no check to prevent the user from using SSL
with PhpiredisStreamConnection (it does not work due to the fact that
internally is uses stream_socket_recvfrom()).

Pretty obvious phpiredis was not installed on my system when I made that
change or the test suite would have caught the wrong behaviour (like it
just happened now that I build it from scratch).
2020-09-04 18:05:26 +02:00
Daniele Alessandri e5f44c33a2 No need for socket_import_stream() to set TCP_NODELAY since PHP 7.1. 2020-09-04 17:56:19 +02:00
Daniele Alessandri 67487528eb Fix WebdisConnection with IPv4 hosts.
Apparently something changed since last time in cURL internals and now
an IPv4 wrapped by square brackets (which are used for IPv6 addresses)
returns a malformed request error.
2020-09-04 17:53:16 +02:00
Daniele Alessandri ac543999ef Restore broken change from a few years ago.
After this change there was no check to prevent the user from using SSL
with PhpiredisStreamConnection (it does not work due to the fact that
internally is uses stream_socket_recvfrom()).

Pretty obvious phpiredis was not installed on my system when I made that
change or the test suite would have caught the wrong behaviour (like it
just happened now that I build it from scratch).
2020-09-04 17:19:57 +02:00
Daniele Alessandri bffa1d020b [tests] Just a lone leftover... 2020-09-04 13:54:51 +02:00
Daniele Alessandri 9e48aef4b0 [tests] Adapt after changes in aggregate connection initialization.
See commit dd5d665 for the above mentioned changes.

Tests for Option\Aggregate, Option\Replication and Option\Cluster should
be refactored because code is a bit too repetitive and a bunch of tests
are shared among them (replication and cluster options extend aggregate
and share the same logic after all).
2020-09-03 15:12:34 +02:00
Daniele Alessandri dd5d665156 Dramatically improve aggregate connections initialization.
This is a complete overhaul of how aggregate connections are created and
initialized, now everything is self-contained in our usual 3 supported
client options: "aggregate", "cluster" and "replication".

The usage of callables acting as connection initializerss is now more
consistent through the various options. When the callable is invoked it
receives 3 arguments (the original set of connection parameters passed
by reference, the options container, the current option) and must return
an instance of Predis\Connection\AggregateConnectionInterface otherwise
an InvalidArgumentException is thrown.

When using "cluster" and "replication" the returned aggregate connection
is automatically populated by adding the list of nodes in $parameters,
on the other hand "aggregate" skips this automatism so it is up to the
user. In any case the user-supplied callable receives $parameters as a
reference, setting $parameters to NULL inside the body of the callable
makes the client skip automatic aggregation regardless of the option in
use.

In addition to this the actual procedure of adding nodes to an aggregate
connection has been moved directly into the respective options instead
of being spread between the client (which instead should just pass a set
of parameters and get back a fully-configured aggregate connection) and
the connection factory (and the scope of a connection factory is only to
create new connetion instances to single Redis servers).
2020-09-03 12:43:15 +02:00
Daniele Alessandri efbe80222e Merge remote-tracking branch 'github/pr/655' into main
Local branch v2.0-commandfactory-raw
2020-09-03 12:41:00 +02:00
Daniele Alessandri eb8a89ee7a [tests] Skip integration tests for DispatcherLoop on CI.
Same reason as of PubSub/Consumer, still need to investigate the random
failures. Anyone can help?
2020-09-03 12:33:12 +02:00
Daniele Alessandri f723f67c3f [tests] Use new utility method to skip PUB/SUB tests on CI. 2020-09-03 12:32:38 +02:00
Daniele Alessandri 5133706c36 [tests] Add utility method to skip tests on CI environment. 2020-09-03 12:31:53 +02:00
Daniele Alessandri ae1befb740 Merge remote-tracking branch 'github/pr/654' into main
Local branch v2.0-testsuite-improvements
2020-09-03 12:10:47 +02:00
Daniele Alessandri 0fdca9e805 Remove check for PHP <= 5.4 from Predis\Session\Handler. 2020-09-01 20:39:34 +02:00
Daniele Alessandri eabbd100c9 No need to check for PHP >= 7.0 anymore for persistent SSL.
Leaving assertParameters() for now but in general we should review how
connection backends are initialized to simplify things and remove some
protected methods, at least from base classes.
2020-09-01 20:21:11 +02:00
Daniele Alessandri 1285951243 Predis\Command\RawCommand is now a final class.
The behaviour of a raw command should not ever be overridden by users,
so this change is actually to enforce consistency through the library.
For the most part, raw commands are used internally by Predis to handle
management commands such as CLUSTER SLOTS, ROLE, etc...
2020-09-01 14:45:39 +02:00
Daniele Alessandri 6d6c970ae2 [tests] Replace deprecated TestCase::at().
The "at" matcher will be removed in PHPUnit 10 but it is not a bad thing
after all because it was cumbersome and error-prone.

Took the opportunity to improve some tests while converting them.
2020-09-01 14:03:19 +02:00
Daniele Alessandri c6f2ce4b83 [tests] Replace generic MockObject::will() with specialized methods. 2020-09-01 14:03:19 +02:00
Daniele Alessandri 36c9bb047e [tests] Start improving test suite.
- Make use of more typehints for function parameters
- Make use of typehints for function return values
- Use @var where needed to give proper hints to IDEs and avoid warnings
- Replace MockObject::setMethods() with addMethods() and onlyMethods()
- Rewording of some phpdocs
2020-09-01 13:58:14 +02:00
Daniele Alessandri 5eccc65d42 Fix handling of username when using "redis://".
The username is now correctly retrieved from the userinfo fragment of
the URI when using the "redis" scheme and a "username:password" pair is
present. Values retrieved from the userinfo fragment always override the
ones specified in `username` and `password` if those fields are present
in the query string.
2020-09-01 11:40:30 +02:00
Daniele Alessandri f225c55a01 Back to development.
[ci skip]
2020-08-31 12:39:52 +02:00
Daniele Alessandri c2ede30394 Merge remote-tracking branch 'github/pr/653' into main
Local branch v2.0-connections-phpiredisconfig
2020-08-31 10:54:40 +02:00
Daniele Alessandri c2c1812b87 Merge remote-tracking branch 'github/pr/651' into main
Local branch v2.0-commandfactory-reworkinterface
2020-08-31 10:54:19 +02:00
Daniele Alessandri 743be10f6e Merge remote-tracking branch 'github/pr/650' into main
Local branch v2.0-parameters-filterempty
2020-08-31 10:53:43 +02:00
Daniele Alessandri 7b86a7b54d Merge branch 'v1.1' into main 2020-08-30 23:40:36 +02:00
Daniele Alessandri dc067b3dac Extend "commands" option to support Predis\Command\RawFactory.
The option handler has been extended to accept descriptive string values
in order to create and configure an appropriate command factory.

Accepted string values are:

- "predis" creates the usual command factory
- "raw" creates a raw command factory
- "default" is simply an alias of "predis"
2020-08-30 15:24:12 +02:00
Daniele Alessandri 30a065ad86 Implement Predis\Command\RawFactory.
Any command ID will produce a command instance even for unknown commands
not implemented by Redis (the server will return a -ERR error response).

When using this factory the client does not process arguments before
sending commands to Redis and server responses are not further processed
before being returned to the caller.
2020-08-30 15:01:43 +02:00
Daniele Alessandri 8be2418f01 Update CHANGELOG and bump VERSION (v1.1.4) 2020-08-30 00:15:08 +02:00
Daniele Alessandri b9ebe8a376 [tests] Fix mistype in TODO comments.
... and yay for copypasting it too!
2020-08-30 23:26:42 +02:00
Daniele Alessandri e2d26926d2 Update README. 2020-08-30 21:33:14 +02:00
Daniele Alessandri 309248042f Update .gitignore
Removing annoying .phpunit.result.cache left around when switching back
and forth branches from main to v1.1 for development.
2020-08-30 10:38:47 +02:00
Daniele Alessandri 87452e62d0 Fix authentication to support ACL with Redis 6.0.
When passing both "username" and "password" to connection parameters the
client now uses the extended AUTH command to support ACL authentication
with Redis 6.0.

The plain old authentication method is still supported like usual simply
by passing only "password" to connection parameters.
2020-08-29 14:11:55 +02:00
Daniele Alessandri 31baa9b241 Do not push AUTH and SELECT on empty "password" and "database".
NULL or zero-length string values passed to "password" and "database" in
the connection parameters list do not trigger spurious AUTH and SELECT
commands anymore when connecting to Redis.

Fixes #436.
2020-08-29 13:39:12 +02:00
Daniele Alessandri bd68b55456 Merge remote-tracking branch 'github/pr/649' into main 2020-08-29 11:42:38 +02:00
Daniele Alessandri cc2a7657db Rework Predis\Command\FactoryInterface and related classes.
We have renamed most methods to drop the "command" suffix as it is quite
redundant. Due to this change and thanks to variadic methods introduced
with PHP 5.6 we took the opportunity to replace both "supportsCommand()"
and "supportsCommands()" with a single new method "supports()".

Added more stringent typehints for method arguments and typehints for
return values now that we do not need to support anything below PHP 7.2.
Also moved from using array() to [] in source code of class involved.
2020-08-28 14:23:12 +02:00
Daniele Alessandri 5348c4025e Merge remote-tracking branch 'github/pr/648' into main 2020-08-28 10:28:17 +02:00
Daniele Alessandri 6f942400a1 [tests] Skip integration tests for PUB/SUB consumer on CI.
Changes backported from the main branch (ref. 04d5c10, 5afadb5).

This is just a temporary solution, we will revert this change as soon as
the actual cause for the spurious failures is identified.
2020-08-27 17:44:23 +02:00
Daniele Alessandri 5afadb560f [tests] Skip testPubSubAgainstRedisServer on CI environments.
See 04d5c10.
2020-08-27 17:38:38 +02:00
Daniele Alessandri e58d5fceef Add "redis" scheme in configuration for phpiredis.
Forgot about it! While "redis" is perceived simply as an alias for "tcp"
it must be explicitly mapped in the connection factory.
2020-08-27 16:38:38 +02:00
Daniele Alessandri 56d704f5dd Add "default" as accepted string for "connections".
Using "default" returns a connection factory instance with the default
configuration. Basically it is no different than omitting "connections"
in the client options array but it can be useful when applications want
to automatically configure Predis to use phpiredis when it is loaded:

$client = new Predis\Client('tcp://127.0.0.1', [
  'connections' =>
      extension_loaded('phpiredis')
        ? 'phpiredis'
        : 'default'
]);

This is in response to ISSUE #397.
2020-08-27 15:59:14 +02:00
Daniele Alessandri 2c732c46c8 Make configuration easier for phpiredis based connections.
The "connections" client option now accepts certain string values that
are mapped to specific and most used configurations for the connection
factory. This is used to make it easier to configure Predis to load our
phpiredis-based connection backends without having to manually pass a
map of URI schemes and fully-qualified class names.

  - "phpiredis-stream" maps `tcp` and `unix` to the connection backend
    based on PHP streams (Predis\Connection\PhpiredisStreamConnection).
  - "phpiredis-socket" maps `tcp` and `unix` to the connection backend
    based on ext-socket (Predis\Connection\PhpiredisStreamConnection).
  - `phpiredis` is simply an alias of `phpiredis-stream`.

An InvalidArgumentException is thrown on unsupported string values.
2020-08-27 15:09:35 +02:00
Daniele Alessandri accb030eb5 [tests] Minor adjustments for callable connection initalizers. 2020-08-26 00:57:03 +02:00
Daniele Alessandri 04d5c10193 [tests] Skip testPubSubAgainstRedisServerBlocking on CI environments.
NOTE: this specific test fails at random without any apparent reason
when executed on our CI environments and these failures are not tied
to a particular version of PHP or Redis. It is most likely some weird
timing issue on busy systems as it is really rare to get it triggered
locally. The chances it is a bug in the library are pretty low so for
now we just mark this test skipped on our CI environments (but still
enabled for local test runs) and "debug" this issue using a separate
branch to avoid having spurious failures on main development branches
which is utterly annoying.

We will restore this test on CI environments as soon as we understand
what is the reason behind its random failures.
2020-08-25 17:52:19 +02:00
Daniele Alessandri 4e605ea233 Revert "[tests] Try fixing random failures in one test of PUB/SUB abstraction."
Whoops, wrong test :)

This reverts commit 5c2b31c566.
2020-08-25 17:47:23 +02:00
Daniele Alessandri 5c2b31c566 [tests] Try fixing random failures in one test of PUB/SUB abstraction.
These failures are random and rarely reproducible on a local development
environment but sometimes they affect the success of a test run and it's
annoying. I think it is just a weird timing issue on busy hosts so let's
try with a couple of simple usleep() after SUBSCRIBE and PUBLISH and see
if anything changes in the next few test runs.
2020-08-25 17:16:19 +02:00
Daniele Alessandri 030e8a080c Remove references to Phar from README.
We have removed the utility script for building phar archives out of the
repository, but if you still need to build a phar archive for Predis you
should still be able to use "./bin/create-phar" from the v1.1 branch.
2020-08-25 16:38:04 +02:00
Daniele Alessandri 15eadb3426 Merge branch 'v1.1' into main 2020-08-25 16:07:06 +02:00
Daniele Alessandri 5e220a0b57 Update CHANGELOG. 2020-08-25 15:57:51 +02:00
Daniele Alessandri 0eb2633348 Merge remote-tracking branch 'github/pr/554' into v1.1 2020-08-25 15:42:13 +02:00
Daniele Alessandri b014d5de5a Filter NULL and zero-length string values for parameters.
Having NULL values or zero-length strings for connection parameters does
not make much sense and actually it proved to be an issue with certain
parameters like "password" where an empty string would trigger an AUTH
command with an empty password (and obviously Redis was not happy with
that). The main offenders were a few libraries and frameworks that kept
passing empty values for parameters such as "database" and "password"
even when users left them unconfigured. This fix should make things more
robust and avoid such occurrences in the future.

Related to PR #436 (rejected).
2020-08-25 12:20:53 +02:00
Daniele Alessandri 78041126fc Merge remote-tracking branch 'github/pr/646' into main 2020-08-24 22:43:21 +02:00
Daniele Alessandri 7113e31954 Merge branch 'v2.0-merge-into-main' into main 2020-08-24 22:41:44 +02:00
Daniele Alessandri 6441f34ec5 Merge branch 'v1.1' into main 2020-08-24 22:36:38 +02:00
Daniele Alessandri cbbd6bba88 Update CHANGELOG.
[ci skip]
2020-08-24 22:33:48 +02:00
Daniele Alessandri 3702f24efc Fix more @method tags in interfaces. 2020-08-24 22:27:21 +02:00
Daniele Alessandri 82fefe057b Merge remote-tracking branch 'github/pr/456' into v1.1-annotations 2020-08-24 21:56:13 +02:00
Daniele Alessandri 42336537dc Merge remote-tracking branch 'github/pr/497' into v1.1 2020-08-24 17:10:28 +02:00
Daniele Alessandri 802abac55e Fix pear builder script to generate UTF-8 encoded package.xml.
Fixes issue #531.

[ci skip]
2020-08-24 16:20:06 +02:00
Daniele Alessandri 61e75816ce Apply few changes in .gitattributes file.
Remove .github from directories exported in our release packages and fix
to ignore .php_cs.dist (the actual file commited) instead of .php_cs.

[ci skip]
2020-08-24 14:04:10 +02:00
Daniele Alessandri 0ffaa864e1 Apply few changes in .gitattributes file.
Remove .github from directories exported in our release packages and fix
to ignore .php_cs.dist (the actual file commited) instead of .php_cs.

This also reverts commit 7489690 (slipped into main after merging v1.1),
we do not need it since there is no patching going on for PHPUnit after
our target version was bumped to ^8.0 || ^9.0 on main.
2020-08-24 14:00:05 +02:00
Daniele Alessandri c662ec7b2a Merge branch 'v1.1' into main 2020-08-24 12:03:34 +02:00
Daniele Alessandri 17f0c08cb6 [tests] Fix expected response for COMMAND INFO (Redis >= 6.0).
Starting with Redis 6.0 and the introduction of Access Control Lists,
COMMAND INFO returns an additional array for each specified command in
the request with a list of the ACL categories associated to a command.
2020-08-24 11:45:20 +02:00
Daniele Alessandri 2b8af1eef2 Update CHANGELOG. 2020-08-23 18:38:07 +02:00
Daniele Alessandri c5f2b441b4 Merge branch 'github/pr/545' into v1.1 2020-08-23 18:11:49 +02:00
GITSRC 2440a61cba Fix HashRing to use method defined by HashGeneratorInterface. 2020-08-23 18:09:09 +02:00
Daniele Alessandri 7100884201 Update CHANGELOG. 2020-08-23 17:48:38 +02:00
Daniele Alessandri 2a932d7292 Merge remote-tracking branch 'github/pr/556' into v1.1 2020-08-23 17:47:26 +02:00
Daniele Alessandri 0a6306b73e Back to development. 2020-08-23 17:46:12 +02:00
Peter Gribanov 4363345f7c iterate not iterable connections #552 2020-08-23 15:00:22 +03:00
Daniele Alessandri f06a41cfdc Change method to undefine commands in factory.
The previous implementation was not good because we were exposing in the
public API an internal implementation detail of the base factory class,
furthermore it made Predis\Command\Factory::define() confusing. Having a
separate method to undefine commands in the factory is self-explanatory.

We also changed `Predis\Configuration\Option\Commands` accordingly when
a dictionary of $commandID => $classCommand is passed to the "commands"
client option and $classCommand is NULL.

A few minor changes (mostly cosmetic or documentation) were applied too.

From feedback to PR #644.
2020-08-21 14:30:52 +02:00
Daniele Alessandri 5a7548bc81 Remove useless argument in Predis\Client::getClientBy().
There was no real meaning to have a callback here, for the most part it
was just a leftover of a previous approach implemented with ee7104d and
quickly superseded by the current approach that simply returns the new
client instance instead of using callbacks.

From feedback to #644.
2020-08-21 14:00:13 +02:00
Daniele Alessandri d4bcf912f4 [tests] Drop TODO and implement type check in utility method.
From feedback to PR #644.
2020-08-21 11:20:24 +02:00
Daniele Alessandri a772f0b16b [tests] Drop now useless method.
From feedback to PR #644.
2020-08-21 11:20:07 +02:00
Anatoly Pashin 44cf08e691 Fix PHPUnit installation on PHP 8 2020-08-20 17:53:34 +10:00
Till Krüss 2ce537d75e bump version to v1.1.3 2020-08-18 14:00:59 -07:00
Till Krüss 7489690306 include patch files in exports just to be safe
See #642
2020-08-18 13:55:36 -07:00
Till Krüss 371b481f12 Merge pull request #641 from heithemmoumni/patch-1
use present for copyright range
2020-08-18 08:30:48 -07:00
Till Krüss d5106c9f00 Update LICENSE
Co-authored-by: Anatoly Pashin <anatoly.pashin@gmail.com>
2020-08-18 08:30:33 -07:00
Daniele Alessandri 4b2b35202a [tests] Restore new message for failed assertion. 2020-08-18 16:12:45 +02:00
Daniele Alessandri c26909699b Merge remote-tracking branch 'github/pr/639' into main 2020-08-18 16:03:10 +02:00
moumni 593920085e use present for copyright range 2020-08-17 20:58:03 +01:00
Daniele Alessandri 592dd91454 Fix class name for OBJECT command.
Starting with PHP 7.2 "object" is a reserved word and cannot be used as
a name for classes, interfaces or traits.
2020-08-17 18:32:14 +02:00
Daniele Alessandri 33f5a0ec8c Merge branch 'stale-master' into main 2020-08-17 17:43:13 +02:00
Raza Mehdi 36a02cf807 Fix test. 2020-08-16 04:31:52 +05:00
Raza Mehdi d6ee18bf21 Merge remote-tracking branch 'github/main' into main 2020-08-16 02:04:16 +05:00
Raza Mehdi 5edf443141 Fix tests. 2020-08-16 01:59:41 +05:00
Till Krüss bf777f3529 Merge pull request #626 from predis/remove-pear
Remove PEAR/PHAR
2020-08-14 10:40:13 -07:00
Till Krüss 390adfb3b8 Merge branch 'main' into remove-pear 2020-08-14 10:39:52 -07:00
Till Krüss 25b6b824b4 update badges 2020-08-14 10:35:25 -07:00
Till Krüss d4a170d890 drop Travis 2020-08-14 10:27:07 -07:00
Till Krüss 71b2119436 bump version 2020-08-14 10:15:57 -07:00
Till Krüss 7376902b20 update org references 2020-08-14 10:11:49 -07:00
Till Krüss 7636d55e10 rename github org 2020-08-14 10:10:01 -07:00
Till Krüss 80191d6487 Merge pull request #634 from srmkliveforks/main
Setup Github Actions Workflows
2020-08-14 10:02:37 -07:00
Raza Mehdi 882d59001f Use PHPUnit 9. 2020-08-14 21:59:48 +05:00
Raza Mehdi f01a0cf5d0 Use specific php version. 2020-08-14 21:53:25 +05:00
Raza Mehdi 7d753f236a Move redis versions into matrix. 2020-08-14 18:36:08 +05:00
Raza Mehdi 7b1924528b Add Badge. 2020-08-14 17:51:06 +05:00
Raza Mehdi 9b355d1766 Use Redis 4 to 6. 2020-08-14 17:40:41 +05:00
Raza Mehdi 787d68f1c4 Set Github actions 2020-08-14 15:55:18 +05:00
Till Krüss ffadffb71c Merge pull request #628 from b1rdex/patch-1
Test on Redis 3-6
2020-08-13 08:45:29 -07:00
Till Krüss b637be9e4a ignore phpunit cache 2020-08-13 08:42:32 -07:00
Till Krüss 64937f725b get phpunit running 2020-08-13 08:41:43 -07:00
Till Krüss 44f98e6635 Merge pull request #631 from b1rdex/patch-2
Fix php version requirement
2020-08-13 08:08:26 -07:00
Anatoly Pashin 1eeef0e5d7 Change the php version constraint 2020-08-13 19:19:12 +10:00
Anatoly Pashin 5b4de508ba Fix php version requirement 2020-08-13 16:22:22 +10:00
Till Krüss c30c60d6f9 trigger travis
Travis CI wasn't set up during the move the `predishq`.
2020-08-12 19:56:40 -07:00
Anatoly Pashin 96e286aaf7 Test on Redis 3-6 2020-08-13 12:47:29 +10:00
Till Krüss 4edfda0669 remove single file script 2020-08-12 12:29:48 -07:00
Till Krüss 36e7cb487d remove patch files 2020-08-12 12:13:09 -07:00
Till Krüss 6cd919c43c remove pear stuff 2020-08-12 12:10:19 -07:00
Till Krüss 3104874887 Merge remote-tracking branch 'origin/v1.1' into main 2020-08-12 12:00:41 -07:00
Till Krüss a6bd25412e remove gitter badge 2020-08-12 12:00:08 -07:00
Till Krüss 3a3a7fb349 use correct php 8 id 2020-08-12 11:57:53 -07:00
Till Krüss 3d68a59505 remove hhvm badge
# Conflicts:
#	README.md
2020-08-12 11:57:52 -07:00
Till Krüss c380b434b0 readme tweaks
# Conflicts:
#	README.md
2020-08-12 11:57:31 -07:00
Till Krüss ca6daea582 add code of conduct 2020-08-12 11:55:34 -07:00
Till Krüss c85434bbbb bump phpunit from 4 to 8
# Conflicts:
#	composer.json
2020-08-12 11:55:33 -07:00
Till Krüss fa73623c75 drop php 7.1 and older; add php 8
# Conflicts:
#	.travis.yml
2020-08-12 11:54:28 -07:00
Till Krüss 60cc950a58 remove Predis\Async from readme 2020-08-12 11:53:52 -07:00
Till Krüss db82dd9f23 format psr-4 2020-08-12 11:53:12 -07:00
Till Krüss 1bc08d9bcc add funding to composer.json; update authors 2020-08-12 11:50:57 -07:00
Till Krüss 11e4bb44d0 more reference updates to predishq 2020-08-12 11:50:07 -07:00
Till Krüss cddb849812 remove gitter 2020-08-12 11:49:42 -07:00
Till Krüss f2298dd186 update references to predishq 2020-08-12 11:49:37 -07:00
Till Krüss bceda1d8e6 Merge pull request #625 from AhmedRaafat14/add-php8-support
Support PHP 8.0 in v1.1.x
2020-08-12 08:42:08 -07:00
Till Krüss 9f87c849c5 Update .travis.yml 2020-08-12 08:41:50 -07:00
Ahmed Raafat 1382146b03 Add php 8.0 (nightly) to the lines that is allowed to faoil (allow_failures) 2020-08-12 12:22:42 +02:00
Ahmed Raafat cbc08aa5e7 Add php 8.0 to travis 2020-08-12 11:45:43 +02:00
Till Krüss de9cd905bb Update issue templates 2020-08-11 12:05:47 -07:00
Till Krüss 6dd55d7f96 move cweagans/composer-patches as dev dep 2020-08-11 11:08:18 -07:00
Till Krüss 82eb18c6c3 bump version to 1.1.2 2020-08-11 10:28:15 -07:00
Till Krüss ac6b813ba9 Merge pull request #616 from nrk/support-php-74
Support PHP 7.4 in v1.1.x
2020-08-11 09:48:35 -07:00
Till Krüss 6482956d96 patch tests
Taken from: https://github.com/yiisoft/yii/pull/4306 by @samdark
2020-08-11 09:41:04 -07:00
Till Krüss cf15dd9857 add 7.4 to travis matrix 2020-08-11 08:55:49 -07:00
Till Krüss 597c61a098 fix out of range exception test 2020-08-11 08:43:17 -07:00
Till Krüss 9aa99349b1 Merge pull request #574 from matthewbaggett/v1.1-travis-fixup
V1.1 travis fixup
2020-08-11 08:30:12 -07:00
Till Krüss b6f60f0d72 add funding 2020-08-10 17:02:18 -07:00
Till Krüss 10235d62dc adjust error message regex 2020-08-10 13:48:17 -07:00
Till Krüss ec2b1eacd2 Merge pull request #614 from nrk/revert-611-patch-2
Revert "Bring travis config up to date"
2020-08-10 13:31:37 -07:00
Till Krüss 9c3605ab33 Merge pull request #613 from nrk/revert-610-patch-1
Revert "Add more build targets"
2020-08-10 13:31:20 -07:00
Till Krüss 55e6094954 Revert "Bring travis config up to date" 2020-08-10 13:31:03 -07:00
Till Krüss 15314b726b Revert "Add more build targets" 2020-08-10 13:30:45 -07:00
Till Krüss 292604edbf fix HHVM lowercase issue
Fatal error: Uncaught Error: Keyword __HALT_COMPILER must be written in lowercase
2020-08-10 13:02:49 -07:00
Till Krüss fc8f9f5604 Merge pull request #585 from gladx/v1.1
Fix test error exception for SELECT command
2020-08-10 12:41:25 -07:00
Till Krüss 77132e6c6b Merge pull request #589 from funivan/patch-1
Fix wiki link
2020-08-10 12:40:46 -07:00
Till Krüss a7571ef0c7 Merge pull request #583 from Miljan9602/v1.1
Fixed wrong annotation for spop method.
2020-08-10 12:40:27 -07:00
Till Krüss 4901408b08 Merge pull request #611 from hannesvdvreken/patch-2
Bring travis config up to date
2020-08-10 12:29:13 -07:00
Till Krüss dd3897b755 Merge pull request #610 from hannesvdvreken/patch-1
Add more build targets
2020-08-10 12:28:53 -07:00
Hannes Van De Vreken 6e7dbe05fb Bring travis config up to date 2020-07-29 03:33:50 +02:00
Hannes Van De Vreken f0f9d68a8e Add more build targets 2020-07-29 03:18:56 +02:00
Ivan Shcherbak bb6f1ee0e3 Fix wiki link 2019-11-25 14:23:35 +02:00
Ali Yousefi ffcc4bba8c Fix test error exception for SELECT command 2019-10-06 22:10:17 +03:30
Miljan Rakita 83359dff9a Fixed wrong annotation for spop method.
Spop method has return annotation string, but it returns array.
2019-09-10 19:26:00 +02:00
Matthew Baggett 710b4f901b Apparently 5.4 and 5.5 aren't available outside of trusty? 2019-08-09 11:54:35 +02:00
Matthew Baggett f3e46683b9 Sometimes, timing-related tests (read: KeyExpireAtTest::testCanExpireKeys) can fail but then succeed on a retry. So lets automate that retry. 2019-08-09 11:07:43 +02:00
Matthew Baggett 945e05819b Rejig. 2019-08-09 10:54:47 +02:00
Matthew Baggett a64b7354e1 Travis fixup 2019-08-09 10:37:19 +02:00
Mark Fettig 39ff616e86 update sort command to be a write operation 2019-03-18 12:10:26 -04:00
Geoffrey Hoffman 738ec0c50f Correcting the return type hint for BRPOPLPUSH method 2018-04-10 18:09:42 -07:00
Teoh Han Hui 1828222e27 Add null return value to PHPDoc 2017-08-14 19:36:11 +08:00
Daniele Alessandri 111d100ee3 Make examples scripts executable only via CLI.
This is meant as a basic layer of protection for those cases where the whole
Predis repository is cloned into a path which is publicly exposed by the web
server.

Closes #408
2017-07-12 16:39:17 +02:00
Daniele Alessandri 893215a1d4 Push same changes of #446 to Predis\ClientContextInterface.
This also adds a couple of missing changes into the original PR.
2017-07-12 15:34:57 +02:00
Daniele Alessandri f5d8b9fe2d Merge remote-tracking branch 'github/pr/446' into v1.1 2017-07-12 15:24:15 +02:00
Daniele Alessandri 722b513cea Upgrade .php_cs configuration file for php-cs-fixer 2.x 2017-07-12 15:22:58 +02:00
Daniele Alessandri 62774c6cc5 Merge remote-tracking branch 'github/pr/442' into v1.1 2017-07-12 13:37:06 +02:00
Daniele Alessandri 8aa2ded5b0 Merge remote-tracking branch 'github/pr/445' into v1.1 2017-07-12 13:36:17 +02:00
Daniele Alessandri 795c3e41b0 Merge remote-tracking branch 'github/pr/434' into v1.1 2017-07-12 13:31:24 +02:00
Daniele Alessandri 59e616b124 Remove broken badge.
Looks like hhvm.h4cc.de is dead.

[ci skip]
2017-07-12 13:30:52 +02:00
Daniele Alessandri 157f658f0b Fix iterators abstractions for HSCAN and ZSCAN when using PHP 7.2.
Closes #488.
2017-07-12 11:59:35 +02:00
Daniele Alessandri 343afd312a Fix wrong CRC16 calculated on integer value.
Closes #450.
2017-07-12 11:29:25 +02:00
Daniele Alessandri d77b77bbd9 Merge remote-tracking branch 'github/pr/443' into v1.1 2017-07-12 10:59:41 +02:00
gitomato 34b678192f Add string type to $keys argument
Reveals the ability to use a string for $keys argument.
2017-06-29 10:25:14 +02:00
Jorrit Schippers 4de246cfee Correct link to GitHub releases page 2017-06-27 09:35:15 +02:00
Anatoly Pashin 6fd6933580 Create .travis.yml 2017-06-11 00:28:43 +10:00
Anatoly Pashin c7b38abe71 use trusty dist 2017-06-09 18:05:11 +10:00
Anatoly Pashin 574ef78f86 fix typehint 2017-06-09 17:57:00 +10:00
Andrii Volin 1ebabaf8f8 fix typo in tests/README.md 2017-05-01 17:12:25 +03:00
Fabien Villepinte 3acf867cac Fix PHPDoc of \Predis\Connection\Aggregate\SentinelReplication::assertConnectionRole() 2016-11-22 15:33:03 +01:00
Daniele Alessandri 98ec0cc27e Merge remote-tracking branch 'github/pr/376' into v1.1
[ci skip]
2016-11-22 15:32:30 +01:00
orvice 9b7897b2da fix typo 2016-11-22 15:31:43 +01:00
Daniele Alessandri caf8a46cbb Merge remote-tracking branch 'github/pr/373' into v1.1
[ci skip]
2016-11-22 15:30:42 +01:00
Remi Collet ce2cbfd929 fix test for ArgumentCountError exception with PHP 7.1 2016-11-17 18:13:12 +01:00
Remi Collet 0b3af06e6b enable 7.1 on travis 2016-11-17 18:13:00 +01:00
Daniele Alessandri 944a16d7c0 Merge remote-tracking branch 'github/pr/393' into v1.1 2016-11-17 17:55:23 +01:00
Remi Collet d1290dfde0 fix test for ArgumentCountError exception with PHP 7.1 2016-11-17 15:24:54 +01:00
Remi Collet 9489d9e5aa enable 7.1 on travis 2016-11-17 15:12:24 +01:00
Fabien Villepinte 94ccb2cc3b Fix PHPDoc of \Predis\Connection\Aggregate\SentinelReplication::assertConnectionRole() 2016-09-14 17:20:55 +02:00
orvice 6c848db2a0 fix typo 2016-08-19 16:48:00 +08:00
Daniele Alessandri ea28d82681 More updates to README to reflect changes in parameters handling.
[ci skip]
2016-06-21 10:51:35 +02:00
Daniele Alessandri bb81f67a0f Update README to reflect changes in parameters handling.
[ci skip]
2016-06-20 18:14:00 +02:00
Daniele Alessandri a4d63e2510 [tests] Fix preassigned slots in slotmap tests. 2016-06-18 21:54:01 +02:00
Daniele Alessandri 89840412d5 [tests] Fix preassigned slots in cluster tests. 2016-06-18 21:53:49 +02:00
Daniele Alessandri 6ab10b2b70 [tests] Fix preassigned slots in cluster tests. 2016-06-18 21:51:10 +02:00
Daniele Alessandri 2d4377fc81 Back to development. 2016-06-18 21:37:42 +02:00
Daniele Alessandri 67c0fb8eb1 Separate id and alias in predis cluster (client-side sharding).
This change does not affect distribution but simply separates the two
concepts of connection ID (ip:port pair) and alias (value set via the
"alias" connection parameter), the method getConnectionByAlias() has
been added to reflect this change.

The method getConnectionBySlot() has also been added.
2016-06-18 17:12:20 +02:00
Daniele Alessandri 0a7ddf7bba Fix spacing in phpdocs. 2016-06-18 15:52:15 +02:00
Daniele Alessandri 184d583895 Implement the concept of role for connections.
When using replication backends, now the role of a connection is not
defined by its alias but by the new connection parameter "role" that
can be set to "master", "slave" and (for redis-sentinel) "sentinel".

This also led to a redesign of how connections can be retrieved from
replication backends: the method getConnectionById() now retrieves a
connection only by its ID (ip:port pair), to get a connection by its
alias there is the new method getConnectionByAlias(). This method is
not supported by the redis-sentinel backend due to its dynamic nature
(connections are retrieved and initialized at runtime from sentinels)
but it is still possible to get a single connection from the pool by
using its ID. It is also possible to retrive a connection by its role
using the method getConnectionByRole().

NOTE: the "role" parameter is an hint for the internals of aggregate
connection backends so it is still possible that the actual role of
a connection changes during the execution of a script (e.g. a slave
gets promoted to the role of master): in this case the parameters of
that connection will not be changed as they are immutable, but the
method getConnectionByRole() will return the appropriate connection.

Predis\Client::getClientBy() has been updated with the addition of
"role" and "alias" as supported selectors.
2016-06-18 15:32:53 +02:00
Daniele Alessandri 69e40dab2b Extract slot map logic to separate class.
In addition to that, the methods askSlotsMap() and buildSlotsMap() of
the redis-cluster connection backend have been renamed respectively
to askSlotMap() and buildSlotMap().
2016-06-17 22:18:38 +02:00
Daniele Alessandri 028992cf1b Remove useless method. 2016-06-17 14:13:02 +02:00
Daniele Alessandri 8de97ffe1a Fix snippet for replication in README.
[ci skip]
2016-06-17 13:58:08 +02:00
Daniele Alessandri d38cf2788b Update CHANGELOG. 2016-06-17 12:38:56 +02:00
Daniele Alessandri 0b226ff1d5 [tests] Missing test case for redis-cluster strategy. 2016-06-17 12:32:32 +02:00
Daniele Alessandri e38df19fac Implement "crc16" client option for redis-cluster.
By default Predis chooses automatically which hash generator to use:
if a suitable version of ext-phpiredis is loaded (that is, a version
that implements the phpiredis_utils_crc16() function) it uses the new
Predis\Cluster\Hash\PhpiredisCRC16 generator, otherwise it falls back
to the usual pure-PHP Predis\Cluster\Hash\CRC16 generator.
2016-06-17 12:32:29 +02:00
Daniele Alessandri 509a330bca Implement CRC16 hash generator based on ext-phpiredis.
Generating the hash of a string of 10 bytes is 10 times faster than
the equivalent pure-PHP implementation of CRC16 (PHP 7.0.7).

This generator requires a version of phpiredis that implements the
function "phpiredis_utils_crc16()".
2016-06-17 12:32:29 +02:00
Daniele Alessandri 0c4a90d809 Update CHANGELOG.
[ci skip]
2016-06-16 19:14:41 +02:00
Daniele Alessandri f0210e3888 Update CHANGELOG and bump VERSION. 2016-06-16 18:22:20 +02:00
Daniele Alessandri b3b35a9ae2 Remove Predis\Client::getConnectionById(). 2016-06-16 16:10:46 +02:00
Daniele Alessandri 7bb2192294 Replace Predis\Client::on() with getClientBy().
This method improves the previous one, which worked only by picking a
connection by ID, allowing users to specify a selector type among the
following ones: "id", "key", "slot", "command". These selectors are
expanded internally to methods, invoked against the connection object
in use by the client, that follow the getConnectionByXXX() convention
already in use through the library:

  id      => getConnectionById()
  key     => getConnectionByKey()
  slot    => getConnectionBySlot()
  command => getConnectionByCommand()

The underlying connection does not necessarily need to implement the
aggregate connection interface as the client relies on a duck-typing
approach by using method_exists().
2016-06-16 16:10:42 +02:00
Daniele Alessandri 53b2cc340a Apply same fix of 8437fbc to ClientContextInterface. 2016-06-16 10:53:23 +02:00
Felix Sandström 99f1e3290e Correcting the PHPDocs 2016-06-16 10:53:23 +02:00
Daniele Alessandri 5e88200ed6 Merge branch 'github/pr/344' into v1.1 2016-06-16 10:47:45 +02:00
Daniele Alessandri aed1a7bdf1 Apply same fix of 8437fbc to ClientContextInterface. 2016-06-16 10:47:01 +02:00
Daniele Alessandri 9d8adee1b1 Rename to getConnectionByCommand($command). 2016-06-16 10:39:44 +02:00
Daniele Alessandri a70971549e Fix GC issues with closures for phpiredis reader handlers.
The following code, despite not being something you would do in real
world scenarios, eventually ended up generating an exception for "Too
many open files".

  for ($i = 0; $i < 10000; $i++) {
    $client = new Predis\Client();
    $client->connect();
  }

The reason was that the destructor for the connection was not invoked
by PHP as expected when the client instance went out of scope, so the
underlying stream resource were not being properly released.
Even without an actual "connect()" operation, the memory usage of PHP
kept growing until exhausting the configured value of max memory.

The source of the issue is related to the use of closures as handlers
for the phpiredis reader resource, to be more precise it seems to be
some kind of circular reference memory leak. Apparently PHP does not
like the fact that a closure, automatically bound to "$this" starting
with PHP 5.4, is stored in the reader resource which in turn is kept
referenced by "$this". This ends up the refcount not going down thus
the GC does not collect those connection objects going out of scope.
This is confirmed by the fact that this issue is not triggered when
using PHP 5.3 where the ZE does not automatically bind closures to
"$this", unless you capture "$this" with the "use()" directive (and
the usual "$that = $this" trick).

Using a static assignement instead of simply returning new closures
in "getStatusHandler()" and "getErrorHandler()" is kind of an hack
that seems to be working fine, the added value of this solution is
that we do not have to break the internal API of the three connection
backends based on ext-phpiredis.

This commit fixes #345.
2016-06-14 21:27:42 +02:00
Daniele Alessandri 2290042680 Fix GC issues with closures for phpiredis reader handlers.
The following code, despite not being something you would do in real
world scenarios, eventually ended up generating an exception for "Too
many open files".

  for ($i = 0; $i < 10000; $i++) {
    $client = new Predis\Client();
    $client->connect();
  }

The reason was that the destructor for the connection was not invoked
by PHP as expected when the client instance went out of scope, so the
underlying stream resource were not being properly released.
Even without an actual "connect()" operation, the memory usage of PHP
kept growing until exhausting the configured value of max memory.

The source of the issue is related to the use of closures as handlers
for the phpiredis reader resource, to be more precise it seems to be
some kind of circular reference memory leak. Apparently PHP does not
like the fact that a closure, automatically bound to "$this" starting
with PHP 5.4, is stored in the reader resource which in turn is kept
referenced by "$this". This ends up the refcount not going down thus
the GC does not collect those connection objects going out of scope.
This is confirmed by the fact that this issue is not triggered when
using PHP 5.3 where the ZE does not automatically bind closures to
"$this", unless you capture "$this" with the "use()" directive (and
the usual "$that = $this" trick).

Using a static assignement instead of simply returning new closures
in "getStatusHandler()" and "getErrorHandler()" is kind of an hack
that seems to be working fine, the added value of this solution is
that we do not have to break the internal API of the three connection
backends based on ext-phpiredis.

This commit fixes #345.
2016-06-14 21:25:14 +02:00
Daniele Alessandri 295e9175ad Update CHANGELOG.
[ci skip]
2016-06-14 18:21:36 +02:00
Pascal Hofmann d92f31dc66 Don't send AUTH and/or SELECT command after connecting to sentinels 2016-06-14 17:20:08 +02:00
Daniele Alessandri e88ffc767d Merge remote-tracking branch 'github/pr/346' 2016-06-14 17:19:32 +02:00
Pascal Hofmann ce8b3fb683 Don't send AUTH and/or SELECT command after connecting to sentinels 2016-06-14 16:38:59 +02:00
Felix Sandström 8437fbc84f Correcting the PHPDocs 2016-06-14 10:02:47 +02:00
Daniele Alessandri e0b4b2c20a [tests] Add test for Predis\Cluster\Hash\CRC16. 2016-06-13 18:58:02 +02:00
Daniele Alessandri 4d58928efd [tests] Add test for Predis\Cluster\Hash\CRC16. 2016-06-13 18:57:06 +02:00
Daniele Alessandri 2640062803 Use master for connect() when sentinel reports no slaves.
Fixes #342.
2016-06-13 16:32:45 +02:00
Daniele Alessandri a523cf7731 Use master for connect() when sentinel reports no slaves.
Fixes #342.
2016-06-13 15:51:23 +02:00
orvice 1811288009 fix typos
possibile -> possible
indentify -> identify
publis ->  publish
2016-06-13 15:22:31 +02:00
Daniele Alessandri 1ad0effb0a Merge remote-tracking branch 'github/pr/343' 2016-06-13 15:21:26 +02:00
Daniele Alessandri 0607d84d0c Back to development. 2016-06-13 15:20:48 +02:00
orvice a1ee7b68ef fix typos
possibile -> possible
indentify -> identify
publis ->  publish
2016-06-12 16:27:14 +08:00
Daniele Alessandri fa643ac20c Apply CS fixes. 2016-06-10 11:12:26 +02:00
Daniele Alessandri eb1e686ff9 [tests] Change indentation of mock method expectations. 2016-06-10 11:08:26 +02:00
Daniele Alessandri f02f3b6d37 [tests] Improve code coverage.
There is still some work to improve coverage in other classes though.
2016-06-09 16:41:19 +02:00
Daniele Alessandri d72a1b5550 Do not extend EVALSHA for ScriptCommand class. 2016-06-09 14:02:22 +02:00
Daniele Alessandri 8b466d05df Get string of basic connection parameters from parameters class. 2016-06-08 18:36:35 +02:00
Daniele Alessandri b553c6b9d0 Pass dispatcher loop instance to callback.
This should not break existing code but allows users to retrieve more
easily the current dispatcher loop instance without resorting to some
tricks (like relying on the "use()" directive with closures).
2016-06-08 12:12:31 +02:00
Daniele Alessandri c10479e238 Remove executeCommandOnNodes() from predis cluster backend.
It is still possible to achieve the same simply by iterating over the
connection or, even better, over the client instance.
2016-06-08 12:01:54 +02:00
Daniele Alessandri 228ccaebe3 Use static instead of self. 2016-06-07 21:01:59 +02:00
Daniele Alessandri 82c256422a Fix failure on PHP 5.3.
Also use get_called_class() where possible.
2016-06-07 20:42:08 +02:00
Daniele Alessandri ee7104d2e5 Replace "getClientFor()" with "on()" in Client.
This new method acts exactly like "getClientFor()" by returning a new
client instance for the specified node unless a callback is passed as
the second argument, in this case the callback is invoked and the new
client instance is passed to it. The value returned by the callback
is used as the return value of the "on()" method.
2016-06-07 20:00:11 +02:00
Daniele Alessandri 7c4c4ae58a Change methods of replication connection interface.
Promoted the "switchToMaster()" and "switchToSlave()" methods to be
part of the replication connection interface and demoted the method
"switchTo($connection)".
2016-06-07 18:50:11 +02:00
Daniele Alessandri 185e31e080 Make some fields of Predis\Client private. 2016-06-07 18:22:57 +02:00
Daniele Alessandri 64b3a4805c Apply CS fixes. 2016-06-07 15:23:32 +02:00
Daniele Alessandri 5b4e942112 Add notice about dangers of using master branch. 2016-06-07 15:23:32 +02:00
Daniele Alessandri b2547fc7f4 [tests] Ignore code coverage for Predis\Autoloader. 2016-06-07 15:23:32 +02:00
Daniele Alessandri d34bdd38c3 Reorganize and improve client options.
All option classes have been moved in the Predis\Configuration\Option
namespace and some have been optimized to have less impact on client
initialization timings.

Furthermore the accepted values for some options have been changed,
this is the complete list of accepted values:

- _aggregate_: callable returning an aggregate connection.
- cluster: string value ("predis", "redis"), callable returning an
  aggregate connection.
- replication: string value ("predis", "sentinel"), callable returning
  an aggregate connection.
- commands: command factory, named array mapping command IDs to PHP
  classes, callable returning a command factory or a named array.
- connections: connection factory, callable returning a connection
  factory, named array mapping connection schemes to PHP classes.
- _prefix_: string value, command processor, callable.
- _exceptions_: boolean value.

Note that the cluster and replication options now return a closure
acting as initializer instead of an aggregate connection.
2016-06-07 15:23:32 +02:00
Daniele Alessandri 1028599ac5 Split Predis\Connection\Aggregate namespace.
Now we have two namespaces for cluster and replication backends:

  - Predis\Connection\Cluster
  - Predis\Connection\Replication
2016-06-07 15:23:32 +02:00
Daniele Alessandri 822f02b8eb Implement new logic to load command classes.
By default Predis now uses a convention-over-configuration approach
by looking for a command class in the Predis\Command\Redis namespace
if it is not already defined in the commands class map.

This change allow us to decrease the time needed to load Predis on
each request since we removed 99% of the mappings in the commands
class map. Classes defined in the internal class map still take the
precedence over this mechanism, so users can still define their own
command classes to handle each command.
2016-06-07 15:23:28 +02:00
Daniele Alessandri 4b47639f9e Rename command classes using command ID as name.
Some notable exceptions are EVAL and ECHO because having these names
as class names would raise a syntax error.
2016-06-04 20:54:41 +02:00
Daniele Alessandri e4872af747 Modify ctor signature of Predis\Command\RawCommand. 2016-06-04 20:54:36 +02:00
Daniele Alessandri c1d34f022f Drop useless method from base command class. 2016-06-04 15:57:12 +02:00
Daniele Alessandri 62b421f20e Switch from server profiles to commands factory.
This change reduces some unnecessary complexity in the library, Redis
commands do not change much after all. Developers can still implement
their own commands factory, inject new commands or override existing
ones. The "profile" client options has been renamed to "commands" and
it accepts instances of Predis\Command\FactoryInterface.

The test suite checks at runtime the version of the running instance
of Redis for integration tests to adapt itself automatically.
2016-06-04 15:36:21 +02:00
Daniele Alessandri 6e3f301588 Move commands classes in Predis\Command\Redis. 2016-06-04 15:36:16 +02:00
Daniele Alessandri 3dccd6bf87 Back to development.
The master branch now hosts the development of Predis v2.0.0-dev.
2016-06-02 09:10:25 +02:00
Daniele Alessandri 0e17edbefb Update CHANGELOG and bump VERSION. 2016-06-02 00:06:21 +02:00
Daniele Alessandri 81c0a8f051 Ensure big ints are not truncated on 32 bits PHP.
We check if the string value is different than the casted int value,
if so it means that the integer is beyond PHP_INT_MAX or PHP_INT_MIN
and we simply return the string value. This is also useful on Windows
builds of PHP since the maximum integer size (prior to PHP 7.0) is 32
bits even for 64 bit builds.
2016-06-01 23:49:23 +02:00
Daniele Alessandri 1065edc8d1 Apply last round of CS fixes. 2016-06-01 22:31:06 +02:00
Daniele Alessandri 843ad23ea7 [tests] Move utility method into base test class. 2016-06-01 22:27:36 +02:00
Daniele Alessandri e386f5c732 Update README.
[ci skip]
2016-06-01 22:20:58 +02:00
Daniele Alessandri a06063d2e6 Update CHANGELOG.
[ci skip]
2016-06-01 21:59:28 +02:00
Daniele Alessandri d58929e5a5 Update README.
Let's try using Gitter...

[ci skip]
2016-06-01 20:59:25 +02:00
Daniele Alessandri ecab7e4642 Implement IteratorAggregate interface for Client.
Now it is possible to iterate over traversable aggregate connections
and get a key/value pair of $connectionId => $clientInstance for each
node.
2016-06-01 12:33:20 +02:00
Daniele Alessandri a22fc17800 Update CHANGELOG.
[ci skip]
2016-05-30 17:45:08 +02:00
Daniele Alessandri 7a50b02c36 [tests] Do not allow failures for HHVM on Travis CI. 2016-05-30 17:09:15 +02:00
Daniele Alessandri f6bf2b5977 [tests] Troubles with HHVM <= 3.6.6 and float timeouts.
HHVM is still being used by Travis CI but this bug makes the build to
take 14 minutes to complete, which is unacceptable.
2016-05-30 17:09:02 +02:00
Daniele Alessandri 5850029f89 Update README.
[ci skip]
2016-05-28 20:28:18 +02:00
Daniele Alessandri f64bd83f9d Update README.
[ci skip]
2016-05-28 20:27:10 +02:00
Daniele Alessandri 922e56b480 Iterate only over connections mapped in slots map.
Iterating over Predis\Connection\Aggregate\RedisCluster returns all
the connections currently mapped in the slots map instead of just the
ones initialized in the pool.

When the slots map is retrieved from Redis (which by default is done
automatically) this allows to iterate over all of the current master
nodes of the cluster. When the underlying use of "CLUSTER SLOTS" is
disabled the iteration returns only connections with a slots range
associated in their parameters or initialized by `-MOVED` responses
to make the behaviour of the iteration consistent between the two
modes of operation.
2016-05-28 17:58:38 +02:00
Daniele Alessandri 5a0dfc3602 Fix parameters overriding for sentinels.
Different fix than PR #339 but thanks @phofmann-trust for spotting.
2016-05-28 15:53:23 +02:00
Daniele Alessandri 39a6e18d71 Update README of test directory.
[ci skip]
2016-05-27 22:03:32 +02:00
Daniele Alessandri a19de6356c Update README.
[ci skip]
2016-05-27 21:31:54 +02:00
Daniele Alessandri 2d01a27e17 Fix fetching slots map from unreachable nodes.
When various nodes in the configuration are unreachable while trying
to send a command, we should attempt to contact a reachable node to
fetch an updated slots map up to $retryLimit times or until there are
no more servers in the pool before giving up.

It is possible that the slots map fetched from Redis contains stale
data and points to a dead server, this happens when the nodes still
have to agree that a master server is down before promoting a slave
to the role of master. In this case no further attempts to execute
the command are performed and an exception is thrown.

This still needs some more testing and will delay v1.0.4 a few days
past its scheduled release.
2016-05-27 14:30:07 +02:00
Daniele Alessandri ad7b8b08cb Run php-cs-fixer. 2016-05-26 09:54:09 +02:00
Daniele Alessandri 0ebfc0e7d2 Update README.
[ci skip]
2016-05-25 21:33:07 +02:00
Daniele Alessandri 9303029c13 Discard slave even when flag is "o_down". 2016-05-25 16:03:12 +02:00
Daniele Alessandri 0477499418 Fix ROLE expectation for read commands with no slaves.
This commit fixes #337.
2016-05-25 15:56:33 +02:00
Daniele Alessandri 9398a793a5 Bump default server profile to Redis 3.2. 2016-05-25 11:25:12 +02:00
Daniele Alessandri 0dff761a61 Merge branch 'v1.1-commands-redis-3.2' 2016-05-24 23:17:33 +02:00
Daniele Alessandri 02ed5a2f4e Update SPOP's @method signature in phpdoc.
SPOP accepts the optional "count" argument since Redis 3.2.
2016-05-24 23:16:00 +02:00
Daniele Alessandri 51932d82e8 Add new command: GEORADIUSBYMEMBER (Redis 3.2.0). 2016-05-24 22:35:27 +02:00
Daniele Alessandri 00000fde4e Add new command: GEORADIUS (Redis 3.2.0). 2016-05-24 22:30:06 +02:00
Daniele Alessandri aeb9b7ccae Check that STORE key in SORT ends up in same slot. 2016-05-24 22:08:41 +02:00
Daniele Alessandri 4273a2a8b6 Improve detection of STORE in SORT command arguments. 2016-05-24 21:38:16 +02:00
Daniele Alessandri b2284d015f Add new command: GEODIST (Redis 3.2.0). 2016-05-24 17:09:35 +02:00
Daniele Alessandri c4e0044269 Add new command: GEOPOS (Redis 3.2.0). 2016-05-24 17:09:33 +02:00
Daniele Alessandri 0b6b3b2558 Add new command: GEOHASH (Redis 3.2.0). 2016-05-24 16:00:08 +02:00
Daniele Alessandri 7ef9619f5c Add new command: GEOADD (Redis 3.2.0). 2016-05-24 16:00:06 +02:00
Daniele Alessandri 3362e474b6 Add new command: BITFIELD (Redis 3.2.0). 2016-05-24 16:00:04 +02:00
Daniele Alessandri 7b3f6e1db5 [tests] Add missing test for key prefix in HSTRLEN. 2016-05-24 15:11:49 +02:00
Daniele Alessandri 1536b2aa82 Add missing @method tag for HSTRLEN in phpdocs.
[ci skip]
2016-05-24 12:27:30 +02:00
Daniele Alessandri 1ab65da368 [tests] Missing @requiresRedisVersion for HSTRLEN. 2016-05-24 11:51:04 +02:00
Daniele Alessandri b11fb84282 Update description in package.ini. 2016-05-24 10:27:57 +02:00
Daniele Alessandri da009e59dd [tests] Test count argument for SPOP in Redis 3.2. 2016-05-23 15:53:30 +02:00
Daniele Alessandri 763acd232d Add new server profile for Redis 3.2 (new stable). 2016-05-23 12:43:00 +02:00
Daniele Alessandri 75a8253ee4 Apply minor grammar fix in comment.
[ci skip]
2016-05-23 12:09:43 +02:00
Daniele Alessandri 9368d98ac3 Update phpunit.xml.* 2016-05-22 20:21:58 +02:00
Daniele Alessandri 8f514fe893 Update description in composer.json. 2016-05-22 20:05:58 +02:00
Daniele Alessandri 6964f060b3 Fix README.
[ci skip]
2016-05-22 15:33:21 +02:00
Daniele Alessandri c125c218ae Apply fix to README for grammar slip.
[ci skip]
2016-05-22 15:10:37 +02:00
Daniele Alessandri 1f3a010681 Update CHANGELOG.
[ci skip]
2016-05-22 15:07:01 +02:00
Daniele Alessandri 49f6b46942 Update and improve README.
[ci skip]
2016-05-22 15:06:56 +02:00
Daniele Alessandri c1795de1f3 Fix README.
[ci skip]
2016-05-21 17:12:20 +02:00
Daniele Alessandri 528cd090d8 Update README.
Improved the section about replication by rewriting some parts of it
and adding details about redis-sentinel.

[ci skip]
2016-05-21 17:05:14 +02:00
Daniele Alessandri 5b3a5bbef9 Run php-cs-fixer. 2016-05-21 15:46:58 +02:00
Daniele Alessandri 349a70a08a Merge branch 'v1.1-sentinel'
This merge resolves #131.
2016-05-21 15:30:22 +02:00
Daniele Alessandri c1de65c4ee Swap params order in redis-sentinel constructor. 2016-05-21 15:23:24 +02:00
Daniele Alessandri ecbdaa1951 Update CHANGELOG.
[ci skip]
2016-05-20 22:33:29 +02:00
Daniele Alessandri 05209e6e7d Switch to next slave on -LOADING error response.
This prevents an early failure of the command execution on the client
when one slave gets back online but is still loading the dataset from
disk (when this happens, Redis returns the -LOADING error response).

This commit fixes #280.
2016-05-20 21:59:40 +02:00
Daniele Alessandri 803a5cfd5b Remove old references about HHVM being unstable. 2016-05-20 20:34:03 +02:00
Daniele Alessandri faaf853cbe [tests] Rename old branch for exclusion.
[ci skip]
2016-05-20 20:14:44 +02:00
Daniele Alessandri 257791edcf Update badges in CHANGELOG.
[ci skip]
2016-05-20 18:34:54 +02:00
Daniele Alessandri d0cc7a5947 Try again on connection failure to node in cluster.
When the connection to a node in the cluster fails in the attempt to
execute a command, Predis now removes the failed connection from the
cluster pool and contacts a random node to ask for a fresh slots map
and tries to execute the command once again.

When the cluster is configured to have each master replicated to one
or more slaves, one the slaves is automatically promoted to the role
of master by redis-cluster with this change being reflected in the
output of CLUSTER SLOTS, so the next execution should run just fine.

Our current approach is relatively naive as CLUSTER SLOTS is executed
against a random master node, meaning that the client must open a new
connection and execute one more roundtrip only to fetch the new slots
map. For now it is enough, it is still better than having the client
fail when you actually have somes slaves in your redis-cluster setup,
but one improvement could consist in caching the list of slaves for
each master returned in the response of CLUSTER SLOTS so that when a
connection fails the client can try to guess which connection should
use for the next attempt.

This commit closes #173, closes #215, and closes #314.
2016-05-20 13:17:06 +02:00
Daniele Alessandri 5adafb352c Evict connection from slots cache when removed. 2016-05-20 11:43:06 +02:00
Daniele Alessandri d6d307696a [tests] Add tests for redis-sentinel connection. 2016-05-19 22:15:55 +02:00
Daniele Alessandri f3999660fe Fix bug during assertion of connection role.
ROLE was not being sent to master when still disconnected and with an
empty slaves pool preventing the client from checking the actual role
of the server upon connect().
2016-05-19 19:06:49 +02:00
Daniele Alessandri 18e846c2ad Fix bug trying to switch to an unknown connection. 2016-05-19 17:42:51 +02:00
Daniele Alessandri 7e4800010a Add minor comment for clarity. 2016-05-19 15:59:21 +02:00
Daniele Alessandri 6b5181b030 Do not wipe server list when removing connection. 2016-05-19 12:58:07 +02:00
Daniele Alessandri 01483234c7 [tests] Fix assertion.
PHPUnit_Util_Type::export() has been removed a while ago...
2016-05-19 11:43:39 +02:00
Daniele Alessandri cdadb796ad Bump min. version of PHPUnit (require-dev). 2016-05-19 11:43:29 +02:00
Daniele Alessandri 354e5e26da Improve handling of slots mapping via parameters.
When using redis-cluster it is now also possible to pass one slot or
non-contiguous ranges of slots via connection parameters in order to
improve the ability to pre-configure the slots map on the client.

Here is an example:

  $parameters = [
    'tcp://10.0.0.1:6379?slots=0-5460,5500-5600,11000',
    'tcp://10.0.0.2:6379?slots=5461-5499,5600-10921',
    'tcp://10.0.0.3:6379?slots=10922-10999,11001-16383',
  ];

This commit fixes #312 (props to @kenotr0n for the original PR).
2016-05-18 15:04:37 +02:00
Daniele Alessandri d55826f35c [tests] Fix tests from previous commit.
They did work, but I am not exactly sure why. Also added a missing
test for Predis\Connection\CompositeStreamConnection.
2016-05-17 20:06:30 +02:00
Daniele Alessandri 26d7147646 Update CHANGELOG. 2016-05-17 19:47:25 +02:00
Daniele Alessandri 973e8592e3 Throw when command sent in connect() returns error.
Common failures are the use of SELECT with a database index outside
the bound of the configured number of databases in redis.conf or the
use of a wrong password for authentication with AUTH.

This resolves #322.
2016-05-17 19:15:21 +02:00
Daniele Alessandri f696ed125e Update CHANGELOG. 2016-05-17 15:31:59 +02:00
Daniele Alessandri 9f6759ca1c Implement discovery in basic replication.
Now the client can discover the whole replication configuration by
asking to one of the servers (master has the precedence) using the
INFO REPLICATION command. This is obviously a best-effort fallback
and there is no strong guarantee about reliability and efficiency.

By enabling auto-discovery, the client automates this process when
the execution of a command fails because one of the target servers
is unreachable. The replication connection requires an instance of
connection factory associated to it in order to be able to create
new connections on the fly.

It is possible to enable the auto-discovery procedure easily via
client options:

  $client = new Predis\Client($servers, [
    'replication' => true,
    'autodiscovery' => true,
  ]);
2016-05-17 14:24:52 +02:00
Daniele Alessandri 89a1e236ce Use custom ID when adding connection with no alias. 2016-05-16 17:28:13 +02:00
Daniele Alessandri 97dfba1e98 Remove useless use directive. 2016-05-16 16:57:24 +02:00
Daniele Alessandri be8ac3e205 Handle error responses returned by redis-sentinel.
Fixes #289.
2016-05-16 16:50:28 +02:00
Daniele Alessandri a933a13087 [tests] Fix wrong method in mock. 2016-05-16 15:38:29 +02:00
Daniele Alessandri ce3d42b9cf Fix CHANGELOG.
[ci skip]
2016-05-15 22:03:34 +02:00
Daniele Alessandri 629329ac76 Fix failing test.
This was exactly what I meant with the @todo annotation, too bad I
forgot to temporarily adjust the test accordingly.
2016-05-15 21:54:00 +02:00
Daniele Alessandri a95860ce00 Bump year in LICENSE. 2016-05-15 21:38:50 +02:00
Daniele Alessandri 51e8d6c46e Update CHANGELOG. 2016-05-15 21:38:21 +02:00
Daniele Alessandri 126998631b Merge branch 'replication-improvements' 2016-05-15 21:37:35 +02:00
Daniele Alessandri d7f3b8c9d2 Update CHANGELOG. 2016-05-15 21:36:31 +02:00
Daniele Alessandri c9366212d0 Add methods to switch to master or random slave. 2016-05-15 21:27:43 +02:00
Daniele Alessandri 5b76b41fda Use master for connect() on empty slaves pool.
Internally the replication class uses this order to pick which server
it should connect to: current connection, one of the slaves, master.

If there is at least 1 slave, connect() will not fail even if master
is undefined. If there are no slaves, connect() will pick master. If
there are no connections registered for replication, connect() will
fail immediatly.
2016-05-15 20:53:09 +02:00
Daniele Alessandri b491dff126 Send read-only commands on next slave on failure.
If no other slave is available try again on master as last resort
before giving up and throwing an exception.
2016-05-15 20:53:06 +02:00
Daniele Alessandri 774b4014d9 Use master for read requests on empty slaves pool.
This is the last resort in case all of the slaves are unreachable.
2016-05-15 17:20:58 +02:00
Daniele Alessandri 00c5d7de19 Apply minor styling fix. 2016-05-15 17:09:43 +02:00
Daniele Alessandri e3412c4a1b Move member variable initialization. 2016-05-15 16:56:50 +02:00
Daniele Alessandri 44ebf5a5e4 Prevent warnings picking slave from empty pool. 2016-05-15 16:54:57 +02:00
Daniele Alessandri 0c99f9ef28 Disconnect before eventually throwing exception. 2016-05-15 15:56:16 +02:00
Daniele Alessandri 6e0743a29a Change method signature. 2016-05-15 15:53:14 +02:00
Daniele Alessandri b047e8b6a1 Rewrite the connection class for redis-sentinel.
Now we do not extend Predis\Connection\Aggregate\MasterSlaveReplication
anymore in order to obtain a more coherent implementation with the logic
of redis-sentinel and apply more optimizations by avoiding useless round
trips with sentinel servers.
2016-05-14 10:39:39 +02:00
Daniele Alessandri 7be83a1fd6 Merge remote-tracking branch 'github/pr/332' 2016-05-13 16:59:33 +02:00
Daniele Alessandri 367ed2c11c [tests] Remove deprecated phpunit directive. 2016-05-13 16:35:10 +02:00
Daniele Alessandri f0b3014cb4 Merge remote-tracking branch 'github/pr/333' 2016-05-13 16:32:48 +02:00
Daniele Alessandri a816adf6e7 Set default parameters via client options.
This is mostly useful when configuring the client to use redis-cluster
or redis-sentinel in order to set a common password for authentication
or database. In these kind of configurations it is impossible to pass
them via connection parameters as connections are created dinamically
by the client depending on the server response.
2016-05-13 14:56:40 +02:00
Ante Braovic 7cb20f5a0c updated .gitignore 2016-05-12 16:38:46 +02:00
Ante Braovic 62c547601c added zrevrangebylex in the list of available methods 2016-05-12 16:27:17 +02:00
Daniele Alessandri f8b3f18abf Implement ROLE for proper redis-sentinel support.
Once the client discovers the address of the master or a slave instance,
it must connect to that node and issue a ROLE command to verify that its
role still matches what the client got from the sentinel server.
2016-05-11 10:52:09 +02:00
Daniele Alessandri 0ec9f3351f Cap the number of retries on connection failure.
I think it is better to have a default limit to the number of attempts
when trying to send a command after a connection failure, I am just not
sure if 20 is a good value but we can adjust it later.
2016-05-10 17:36:30 +02:00
Daniele Alessandri 622e6c6ba2 Apply fixes on error responses from sentinel.
Fixes manually picked from @djagya's fork, thanks for spotting!
2016-05-10 17:09:37 +02:00
Daniele Alessandri bc212ad2b0 Update phpdoc. 2016-05-10 15:29:17 +02:00
Daniele Alessandri e896d89fa8 Merge remote-tracking branch 'github/pr/306' into v1.1-sentinel 2016-05-10 15:19:21 +02:00
Daniele Alessandri e851aaa21d Automatically assign aliases to slave connections. 2016-05-10 14:55:30 +02:00
Daniele Alessandri 7664f1f29b Improve client configuration for redis-sentinel.
Predis\Client now requires a list of connection parameters pointing to
sentinel instances and mandatory options "replication" and "service" set
respectively to "sentinel" and the chosen name for the master instance.

  $sentinels = ['tcp://127.0.0.1:5381', 'tcp://127.0.0.1:5382'];
  $options   = ['replication' => 'sentinel', 'service' => 'mymaster'];
  $client    = new Predis\Client($sentinels, $options);

Despite being nice and clean on the outside I am not really fond of the
code being used internally to make this kind of configuration possible.
Improvements in this respect would require a few breaking changes (not
even an option for a minor release) so things will change for the good
with Predis 2.0.
2016-05-10 14:19:05 +02:00
Daniele Alessandri 104e42cfe0 [tests] Fix test executed on current Redis unstable. 2016-05-10 10:58:46 +02:00
Daniele Alessandri b6a14cda04 [tests] Fix test executed on current Redis unstable. 2016-05-10 10:51:43 +02:00
Daniele Alessandri e61cb4e4f2 [tests] Fix wrong @group annotation 2016-05-09 17:49:12 +02:00
Daniele Alessandri 1349666494 Update CHANGELOG.
[ci skip]
2016-05-08 18:56:25 +02:00
Daniele Alessandri a0487ec5f4 Prevent failures serializing commands with "holes" in arguments array.
This could be triggered when passing an array with "holes" to variadic commands.
Connection classes based on the protocol serialized exposed by phpiredis were
not affected by this bug.

Fixes #316.
2016-05-08 18:43:50 +02:00
Remi Collet 57a7d5d3e6 fix tests, list of allowed commands have changed (redis 3.0.6) 2016-05-08 16:52:05 +02:00
Alexander Cheprasov 8235228acd Update ClientInterface.php 2016-05-08 16:46:27 +02:00
John Maguire 3ceaa39a3c Update useClusterNodes() docs to indicate default 2016-05-08 15:21:11 +02:00
Daniele Alessandri 0baad16064 Fix bug in HSCAN-based iterator when hash have integer fields.
When iterating a hash containing integer fields our iterator abstraction
based on HSCAN was always returning "0" as a field name after the first
$field => $value pair due to a wrong assumption on how the PHP function
array_shift() (which is used internally to advance to the next pair in
our buffered response to HSCAN) works.

The ZSCAN-based iterator had this very same bug which was already fixed
in 24e19a9 so I am not sure how this one went unnoticed until now.
2016-05-08 15:16:05 +02:00
Ante Lucic 939c0821dd add docblocks to MasterSlaveReplication 2016-05-05 14:22:32 +02:00
Chris Butler eb154cd43d Replace automatic retry yes/no with a retry limit 2016-01-27 12:35:46 +00:00
Daniele Alessandri d8da74adac Update documents. 2015-08-16 20:25:42 +02:00
Daniele Alessandri fda293b573 Add example of replication configuration using redis-sentinel. 2015-08-16 20:25:42 +02:00
Daniele Alessandri 24fb72a732 Implement ability to fetch an updated list of sentinels from active sentinel.
This can be optionally done automatically but is disabled by default, just use
SentinelReplication::setUpdateSentinels() accordingly to enable the automatic
fetching of an updated list of sentinels.
2015-08-16 20:25:42 +02:00
Daniele Alessandri 8d15503d6c Implement transparent auto-retry of commands upon server failure.
By default, when the current server dies while executing a command Predis asks
for a new configuration to one of the sentinels and re-issues the same command.

This behavior can be disabled calling SentinelReplication::setAutomaticRetry().
2015-08-16 20:25:39 +02:00
Daniele Alessandri 587fbbc446 Specify a timeout for the connect() operation to sentinel servers.
This value should be reasonably low so that the client can fallback to the next
sentinel if the connect() operation is taking too much and slowing things down.

When the connection parameters of sentinels contain a "timeout" parameter, its
value takes the precedence over the default sentinels timeout.
2015-08-16 16:28:21 +02:00
Daniele Alessandri 370d4e72c2 Add initial support for redis-sentinel.
This is a first implementation that is based on the work of @vmattila but some
more changes and missing bits are required in order to be considered complete.

To leverage redis-sentinel the client must be configured using the "aggregate"
option instead of the usual "replication" option, thought this may change for
the release of Predis v1.1.0 (it __will__ change for Predis v2.0.0 but this is
a whole different matter). This is a configuration example:

  use Predis\Connection\Aggregate\SentinelReplication;

  $sentinels = [
    'tcp://127.0.0.1:5381',
    'tcp://127.0.0.1:5382',
    'tcp://127.0.0.1:5383',
  ];

  $client = new Predis\Client($sentinels, [
    'service' => 'nrk-master',
    'aggregate' => function() {
      return function ($sentinels, $options) {
        $service = $option->service;
        $connections = $options->connections;

        return new SentinelReplication($sentinels, $service, $connections);
      };
    },
  ]);

The missing bits right now are:

  - A more solid handling of failures when querying sentinels.
  - When the connection fails while executing a command on one of the servers,
    we should query again a sentinel and then re-issue the command accordingly.
2015-08-16 16:28:13 +02:00
Daniele Alessandri 6bc1a38123 Fix wrong link in phpdoc.
Fixes #270.

[ci skip]
2015-07-30 20:51:15 +02:00
Daniele Alessandri f7d7cd59c4 Update CHANGELOG with release details of v1.0.3.
[ci skip]
2015-07-30 20:38:21 +02:00
Daniele Alessandri d46de81d91 Fix severe regression on HHVM.
Apparently HHVM is more strict than PHP in stream_socket_client() and does not
like at all IPv4 addresses and hostnames eclosed in square brackets. Note that
it is not that weird as square brackets are mandatory only when IPv6 addresses
are embedded in URI strings, so it is more like a weird incompatiblity of HHVM
with the behaviour of the standard PHP interpreter. The connect() attempt fails
but not due to the server being unavailable or some connectivity issue.

The important lesson is: never rely on undocumented behaviours especially when
targeting different runtimes, and do not forget to run the test suite on every
platform right before release like I unfortunately did.
2015-07-30 20:22:37 +02:00
Daniele Alessandri f4b6c578be Update CHANGELOG with release details of v1.0.2.
[ci skip]
2015-07-30 11:21:36 +02:00
Daniele Alessandri 2fc0e56a09 Preserve remainder of path in URI after database (redis scheme). 2015-07-30 11:11:30 +02:00
Daniele Alessandri 8106c8b00a Use PHP_VERSION_ID constant. 2015-07-30 10:57:20 +02:00
Daniele Alessandri b8bfd1405d Update README.
[ci skip]
2015-07-30 10:50:14 +02:00
Daniele Alessandri a7ee80702c Implement full support for IPv6.
Using IPv6 with Predis was basically impossible due to various inconsistencies
and bugs through the library, now it is supported by all the connection classes.

Following the standard for IPv6 literal addresses in URI strings, the IP literal
must be enclosed within square brackets when passing the parameters as a string:

  $parameters = 'tcp://[2001:db8:0:f101::1]:6379';

See https://tools.ietf.org/html/rfc3986#section-3.2.2 for further details.

This commit also fixes #239 making redis-cluster usable with nodes using IPv6.
2015-07-29 23:01:55 +02:00
Daniele Alessandri 0eaa1d929d Reduce unneeded code duplication in URI parsing. 2015-07-29 17:00:12 +02:00
Daniele Alessandri a26390915d Strip brackets from host when parsing embedded IPv6 address.
I don't know why PHP's parse_url() does not do that, it does not make
sense when the IP is by itself so maybe it is a bug?
2015-07-29 16:44:11 +02:00
Daniele Alessandri 24c0f846c7 Use static:: for invoking static methods in key prefix processor.
This trivial change makes it possible to use overridden static methods
when extending Predis\Command\Processor\KeyPrefixProcessor. PHP always
invokes the static methods of a parent class when using self:: even if
the extended classes override them.
2015-07-29 12:28:44 +02:00
Daniele Alessandri f43433baf1 Add new command: HSTRLEN (Redis 3.2.0).
Also bump the unstable profile version to 3.2.
2015-07-29 11:50:20 +02:00
Daniele Alessandri 3dfe62a5b5 Change format required for URI strings when using "unix" scheme.
Instead of using "unix://" you should just use "unix:":

  $old = 'unix:///path/to/redis.sock';
  $new = 'unix:/path/to/redis.sock';

The old format should be considered obsolete and will not be supported
starting from the next major release of Predis.
Meh
2015-07-28 11:23:33 +02:00
Daniele Alessandri ebb72377bb Implement TLS/SSL-encrypted connections.
This is handy for accessing remote Redis instances over a secure SSL connection
which is currently a popular option or even requirement with many cloud hosting
environments.

In order to configure the client to use an SSL-encrypted connection the scheme
in the connection parameters must be either "tsl" or "rediss" and a set of SSL
options (see http://php.net/manual/en/context.ssl.php) must be provided via the
"ssl" parameter as a named array.

The following example (which does not necessarily represent an example of good
practices!) illustrates how to set the "ssl" parameter using a named array and
the equivalent URI string:

  // Parameters as named array
  $parameters = [
    'scheme' => 'tls',
    'host'   => '127.0.0.1',
    'ssl'    => [
        'cafile'            => '/home/adaniele/redis.pem',
        'verify_peer_name'  => false,
    ],
  ];

  // Parameters as URI string
  $parameters = 'tls://127.0.0.1?ssl[cafile]=redis.pem&ssl[verify_peer_name]=1';

Support for SSL is currently limited to the Predis\Connection\StreamConnection
backend but we intend to investigate if it is possible to extend this feature
to Predis\Connection\PhpiredisStreamConnection in the future.

Be aware that using encrypted connections may lead to a performance degradation
especially in the connect() operation due to the overhead of the TLS handshake.
Unfortunately there is no real way to reuse SSL sessions from userland, aside
from enabling persistent connections, but this will work only on PHP >= 7.0.0
because previous versions of PHP do not provide enough info about a stream from
get_stream_meta_data().

NOTE: Redis does not have built-in support for SSL-encrypted connections, but if
you want to expose it to public networks you may want to rely on "stunnel".
2015-07-27 19:16:20 +02:00
Daniele Alessandri cb91ad1aee Rephrase latest entries of the CHANGELOG.
[ci skip]
2015-07-26 22:34:20 +02:00
Daniele Alessandri 5172555009 Rephrase some parts of the README.
[ci skip]
2015-07-26 22:28:58 +02:00
Daniele Alessandri 4dea992cd2 [tests] Fix typo. 2015-07-25 21:58:52 +02:00
Daniele Alessandri 80af1af459 [tests] Require pcntl extension to run blocking PubSub\Consumer test. 2015-07-25 21:56:36 +02:00
Daniele Alessandri abf2ce0bd1 [tests] Exlude persistent connections tests under PHP 5.3.
The get_resource_type() function does not differentiate between normal streams
and persistent streams, so we cannot really test this case.
2015-07-25 21:52:55 +02:00
Daniele Alessandri c7cae66a97 [tests] Improve code-reuse in tests for the Predis\Connection namespace. 2015-07-25 21:32:36 +02:00
Daniele Alessandri 4f30ac6370 Run php-cs-fixer. 2015-07-25 19:13:05 +02:00
Daniele Alessandri 1c8eb7ff6b [tests] Share common test among connection classes. 2015-07-25 19:13:01 +02:00
Daniele Alessandri cb09a7a2b5 [tests] Use @requires annotation. 2015-07-25 18:37:11 +02:00
Daniele Alessandri d69d6c726d Remove Connection\Aggregate\RedisCluster::setDefaultParameters().
The redis-cluster connection relies on a client-initialized connection factory,
so use Connection\Factory::setDefaultParameters() to set the default parameters
that must be applied to new nodes discovered through -MOVED or -ASK responses.
2015-07-25 18:37:11 +02:00
Daniele Alessandri 2b0c8fbb26 Remove "timeout" as a default parameter in Connection\Parameters.
Falling back to a default timeout values should be done by the connection class
as it is an implementation detail that may vary depending on the backend.
2015-07-25 18:37:11 +02:00
Daniele Alessandri 55aab86800 Add support for default connection parameters in Connection\Factory.
These parameters augment the set of user-supplied parameters when creating a new
connection, but they do not override specific parameters when already defined.

An example of self-contained configuration using client options:

  $client = new Predis\Client('tcp://127.0.0.1', [
    'parameters' => [
      'timeout' => 10,
    ],
    'connections' => function ($options) {
      $factory = $options->getDefault('connections');
      $factory->setDefaultParameters($options->parameters);

      return $factory;
    },
  ]);

This change will be useful for both redis-cluster and redis-sentinel as it makes
it easy to apply shared parameters such as a common password for authentication
when the server returns one ore more new nodes from response (think of -MOVED).
2015-07-25 18:37:11 +02:00
Daniele Alessandri 6cce9eb35c Run php-cs-fixer. 2015-07-25 18:37:10 +02:00
Daniele Alessandri 8277afc7a8 Use "persistent" with non-bool strings to open different persistent connections.
stream_socket_client() has the undocumented ability to open different persistent
streams by providing a path in the $address string. Previously we supported this
behaviour with a combination of "persistent" and "path" (see #139) but this can
be confusing, especially now that we support the redis:// scheme which uses the
path part of an URI string to specify a database number.

After this change, instead of using an URI string such as:

  $parameters = 'tcp://127.0.0.1/first?persistent=1&database=5';

You should use the following ones:

  $parameters = 'tcp://127.0.0.1?persistent=first&database=5';
  $parameters = 'redis://127.0.0.1/5?persistent=first';

Avoiding "path" makes even more sense when using array connection parameters:

  $parameters = [
    'host'       => '127.0.0.1',
    'database'   => 5,
    'persistent' => 'first',
  ]

This feature is not supported when using UNIX domain sockets because the path
trick of stream_socket_client() does not play well with the actual path of the
socket file. The client will throw an InvalidArgumentException exception to
notify the user.

NOTE: unfortunately we have to disable the tests for persistent connections when
running under HHVM due to a bug in their implementation of get_resource_type()
preventing us to recognize a persistent stream from userland code.
2015-07-25 18:34:51 +02:00
Daniele Alessandri b012af3247 Reorganize stream resource creation for stream-based connections. 2015-07-25 14:39:05 +02:00
Daniele Alessandri 7fa3c55f51 Move assertion for connection parameters out of abstract connection class.
Each connection class should implement its own checks for connection parameters,
even at the cost of some code duplication (inheritance is not just about code
reuse after all).
2015-07-25 14:37:22 +02:00
Daniele Alessandri 73c9b9d5be [tests] Fix some tests methods names. 2015-07-25 10:04:27 +02:00
Daniele Alessandri 59798e1f9e [tests] Apply small changes to commands tests with expirations. 2015-07-25 10:04:24 +02:00
Daniele Alessandri d0012e67ff [tests] Cover SET modifiers EX, PX, NX|XX (Redis >= 2.6.12). 2015-07-25 09:10:07 +02:00
Daniele Alessandri 65727ca07d Update .gitattributes file.
[ci skip]
2015-07-24 23:30:21 +02:00
Daniele Alessandri 4ac1a81aa4 Restore alignment for a few equals symbols. 2015-07-24 23:17:05 +02:00
Daniele Alessandri 8dd9893a2f Run php-cs-fixer with new configuration. 2015-07-24 23:17:02 +02:00
Daniele Alessandri 35e97967fd Add .php_cs configuration file for php-cs-fixer. 2015-07-24 23:16:19 +02:00
Daniele Alessandri 7282ca2b52 Remove unneeded "use" imports. 2015-07-24 21:25:40 +02:00
Daniele Alessandri c436e01353 Fix cluster strategy to handle variadic EXISTS (Redis >= 3.0.3). 2015-07-24 18:30:00 +02:00
Daniele Alessandri df2e9f4e71 Fix prefix processor to handle variadic EXISTS (Redis >= 3.0.3). 2015-07-24 18:29:51 +02:00
Daniele Alessandri 6590c44a27 Run php-cs-fixer against codebase in src/ and tests/. 2015-07-24 18:04:42 +02:00
Daniele Alessandri bb89cf67e2 [tests] Fix me being stupid here. 2015-07-24 17:35:27 +02:00
Daniele Alessandri 7c1d324f30 [tests] Apply some fixes and improvements and remove old stuff. 2015-07-24 17:26:06 +02:00
Daniele Alessandri bb6287f22d [tests] Fix obviously wrong annotation. 2015-07-24 16:20:50 +02:00
Daniele Alessandri f315404649 Update CHANGELOG. 2015-07-24 16:06:31 +02:00
Daniele Alessandri 8c76bd6761 Do not parse response to SETNX into boolean value. 2015-07-24 15:52:59 +02:00
Daniele Alessandri 38fafb22ba Do not parse response to MSETNX into boolean value. 2015-07-24 15:52:53 +02:00
Daniele Alessandri 5ce683be09 Do not parse response to SMOVE into boolean value. 2015-07-24 15:52:50 +02:00
Daniele Alessandri e531d39f53 Do not parse response to SISMEMBER into boolean value. 2015-07-24 15:52:45 +02:00
Daniele Alessandri fda9f022dd Do not parse response to RENAMENX into boolean value. 2015-07-24 15:52:27 +02:00
Daniele Alessandri 44e92d8a2f Do not parse response to PERSIST into boolean value. 2015-07-24 15:50:43 +02:00
Daniele Alessandri e75b69f6fd Do not parse response to MOVE into boolean value. 2015-07-24 15:50:38 +02:00
Daniele Alessandri 082c51146a Do not parse response to EXPIREAT into boolean value. 2015-07-24 15:50:34 +02:00
Daniele Alessandri b02e3f4911 Do not parse response to EXPIRE into boolean value. 2015-07-24 15:50:21 +02:00
Daniele Alessandri 87921f7a05 Do not parse response to PFADD into boolean value. 2015-07-24 15:50:10 +02:00
Daniele Alessandri 3fdfc50683 Do not parse response to HSETNX into boolean value. 2015-07-24 15:50:05 +02:00
Daniele Alessandri ae26ecc8bf Do not parse response to HSET into boolean value. 2015-07-24 15:50:01 +02:00
Daniele Alessandri 231a3440f7 Do not parse response to HEXISTS into boolean value. 2015-07-24 15:49:55 +02:00
Daniele Alessandri ab20c52115 Do not parse response to EXISTS into boolean value.
Starting with Redis 3.0.3 the EXISTS command is variadic so that it is
possible to check for the existence of multiple keys in one request,
with the server returning the number of keys found.

This change could break codebases relying on strict comparison (===)
against a boolean value, but just doing $redis->exists('key') == TRUE
is totally fine.
2015-07-24 15:49:40 +02:00
Daniele Alessandri 2eaf3d8595 Remove useless if condition. 2015-07-24 12:40:08 +02:00
Daniele Alessandri bb909c573d No need to check the scheme here.
Bug introduced in v1.0-dev after changes to support redis scheme.

Fixes #268
2015-07-24 10:39:06 +02:00
Daniele Alessandri 35f135be30 Add support for the 'redis://' scheme in URI strings.
The URI string will be handled following the rules as described by the
the provisional IANA registration document that can be found on IANA's
website: http://www.iana.org/assignments/uri-schemes/prov/redis.
2015-07-23 19:16:05 +02:00
Daniele Alessandri 474f3ddbe7 Add missing command: MIGRATE (Redis 2.6.0).
Fixes #209.
2015-07-23 17:22:53 +02:00
Daniele Alessandri ae054fc7e1 [tests] Fix minor oversight. 2015-07-23 16:46:07 +02:00
Daniele Alessandri 8168def08f Switch to container-based builds on Travis CI.
We do not need "sudo" anyway.
See http://docs.travis-ci.com/user/migrating-from-legacy/ for details.
2015-07-23 12:15:14 +02:00
Daniele Alessandri 15f3b6030c [tests] Improve assert failure messages for replication stategy tests. 2015-07-23 11:38:49 +02:00
Daniele Alessandri c0d1a74447 Fix missing BITPOS in replication strategy. 2015-07-23 11:30:32 +02:00
Daniele Alessandri 6882d08373 Add missing BITPOS command in key prefix processor.
See #265.
2015-07-23 11:06:57 +02:00
Daniele Alessandri 871d526300 Exclude .php-version file.
[ci skip]
2015-07-19 09:35:52 +02:00
Richard Heelin d84bca131b Emit socket error if ipredis connection has been lost/reset.
The current code is checking for a failure (return false) or an empty buffer string, however
neither of these will be the case if the connection has been reset or has errored. According
to the docs for socket_recv, $buffer will be set to null if the connection is reset or their
is no data. As currently null is not allowed for, we enter an infinite loop, to prevent this
I've added null to the things we check before we emit a socket error. This prevents the
infinite loop and correctly results in an Exception if the connection is lost/reset.

Conflicts:
	src/Connection/PhpiredisSocketConnection.php
2015-07-07 18:51:00 +02:00
Daniele Alessandri 5cd4f41424 [tests] Fix base test case class to handle required Redis versions.
This change is needed due to some internal changes in one of the
latest minor releases of PHPUnit 4.x that essentially broke how we
were checking for the required Redis version from method annotations.
2015-07-07 17:43:49 +02:00
Daniele Alessandri b3bcf466f5 [tests] Adapt to internal encoding changes for lists in Redis 3.0. 2015-07-07 16:09:20 +02:00
Daniele Alessandri 24d8f68e7f Support ZADD modifiers when using simplified command signature.
The NX|XX, CH and INCR modifiers for ZADD are available in Redis since
version 3.0.2. See http://redis.io/commands/ZADD for additional info.
2015-07-07 16:05:56 +02:00
Daniele Alessandri 0a8754f9b6 Merge remote-tracking branch 'github/pr/235' 2015-07-07 14:48:41 +02:00
Daniele Alessandri 614049cd12 [tests] Remove hhvm-nightly from Travis CI configuration.
See https://github.com/travis-ci/travis-ci/issues/3788 for details.
2015-07-07 14:42:10 +02:00
Daniele Alessandri 5911145d9f [tests] It's 7.0 and not 5.7! 2015-07-07 14:40:34 +02:00
Daniele Alessandri 8029faf72a [tests] Add PHP 5.7 to Travis CI configuration. 2015-07-07 13:23:09 +02:00
Daniele Alessandri e2c08cfe88 Minor tweak in .editorconfig file.
[ci skip]
2015-07-06 18:42:41 +02:00
Daniele Alessandri 3b31b91ad8 Commit .editorconfig file.
See http://editorconfig.org for more info about EditorConfig

[ci skip]
2015-07-06 18:39:28 +02:00
Daniele Alessandri 7a984e7b76 Fix wrong phpdoc.
Thanks @Aliance for spotting this oversight.
2015-07-03 12:12:39 +02:00
Daniele Alessandri 33e6ee2e48 [tests] Implement test for #257 to guard against regressions. 2015-07-03 12:01:47 +02:00
Daniele Alessandri c577c20481 Merge remote-tracking branch 'github/pr/258' 2015-07-03 11:05:42 +02:00
Dominic Scheirlinck 6fbe2d5fa3 Don't check for __invoke on non-objects
`method_exists` will cause autoloading for strings. Fixes #257
2015-06-16 15:55:20 +12:00
Michal Humpula af48b30398 add zrevrangebylex command 2015-01-23 23:06:40 +01:00
Daniele Alessandri b8decc75a8 Update CHANGELOG.
[ci skip]
2015-01-02 14:37:26 +01:00
Daniele Alessandri 32774c925a Bump year in LICENSE.
[ci skip]
2015-01-02 13:44:54 +01:00
Daniele Alessandri 216795e475 Update CHANGELOG.
[ci skip]
2015-01-02 13:43:29 +01:00
Daniele Alessandri 08129999f8 Merge remote-tracking branch 'srhnsn/v1.0' 2015-01-02 13:33:40 +01:00
Daniele Alessandri 0400d7b581 Merge remote-tracking branch 'blocktrail/hhvm-pubsub-blockingread-test-v1.0' 2015-01-02 13:00:38 +01:00
Daniele Alessandri 08fd312fb5 Temporarily allow failures for HHVM on Travis-CI.
[ci skip]
2015-01-02 12:57:45 +01:00
Daniele Alessandri c1e641e356 No need to access a private field used by PHPUnit.
Fixes #207.
2015-01-02 12:23:16 +01:00
Daniele Alessandri e9264bb087 Add minimum required Redis version for BITPOS integration tests. 2015-01-02 12:12:47 +01:00
Daniele Alessandri 1e774f4686 Apply minor CS fixes and trim spurious spaces. 2015-01-02 12:12:23 +01:00
Daniele Alessandri a0db60e9ce Merge remote-tracking branch 'nicchap/v1.0'
Conflicts:
	VERSION
	package.ini
	src/Client.php
2015-01-02 12:09:23 +01:00
nicchap d2f7903724 Updated bitpos position 2014-12-20 23:39:56 -05:00
nicchap 0e2b7603a5 Updated test cases
1) updated command sequence profiles
2) fixed exception test syntax error
3) Installed PHPUnit locally and successfully ran test.
2014-12-20 12:12:04 -05:00
nicchap 3eb053a08c Missing updates for BITPOS command
Added BITPOS command to test profiles.
2014-12-20 00:13:41 -05:00
Ruben de Vries f3748e45ef added (failing on HHVM) test for pubsub with read_write_timeout=-1 2014-12-19 11:40:59 +01:00
nicchap a1977c1b61 Edited typos
Changed redeclaration error and added single return
2014-12-18 12:15:54 -05:00
nicchap 5a02204833 Added BitPos command
Added BitPos command
2014-12-18 11:09:00 -05:00
Serhan Şen beb6c28c65 Apply read_write_timeout to Unix socket connections. 2014-12-16 20:40:13 +01:00
Daniele Alessandri 8255003de8 [tests] Test serialization of redis-cluster connection with @medium.
Serializing an instance of a redis-cluster connection with its nodes
can take more than 1 seconds on extremely slow hardware.

See issue #220 for reference.
2014-11-07 14:28:44 +01:00
Daniele Alessandri 5f3723bbd1 [tests] Use round() to avoid issues with floats on certain plaforms.
See issue #220 on GitHub for reference.
2014-11-07 14:28:09 +01:00
Daniele Alessandri 28accc93f0 [tests] Test serialization of redis-cluster connection with @medium.
Serializing an instance of a redis-cluster connection with its nodes
can take more than 1 seconds on extremely slow hardware.

See issue #220 for reference.
2014-11-07 14:24:35 +01:00
Daniele Alessandri 381ca99696 [tests] Use round() to avoid issues with floats on certain plaforms.
See issue #220 on GitHub for reference.
2014-11-07 14:19:08 +01:00
Daniele Alessandri 54d467e530 Add missing doc for zincrby in ClientContextInterface.
[ci skip]
2014-10-26 10:28:56 +01:00
Daniele Alessandri dc984ca60d Add missing doc for zincrby in ClientContextInterface.
[ci skip]
2014-10-26 10:28:33 +01:00
Daniele Alessandri 73a06234a4 Apply minor fix to .travis.yml. 2014-10-26 10:25:19 +01:00
Daniele Alessandri 6db2ca38c2 Apply minor fix to .travis.yml. 2014-10-26 10:23:50 +01:00
Daniele Alessandri 330fb41bdc Update CHANGELOG.
[ci skip]
2014-10-25 17:54:22 +02:00
Daniele Alessandri beb9a5e799 Update CHANGELOG.
[ci skip]
2014-10-25 17:53:40 +02:00
Daniele Alessandri 5e24d85c8a Fix E_NOTICE emitted on empty response to INFO [section].
Empty responses can be returned when requesting an unsupported section
with the INFO command.
2014-10-25 17:46:34 +02:00
Daniele Alessandri e2f4357ca3 Fix E_NOTICE emitted on empty response to INFO [section].
Empty responses can be returned when requesting an unsupported section
with the INFO command.
2014-10-25 17:45:00 +02:00
Daniele Alessandri 24e19a9b76 Fix bug in ZSCAN-based iterator when sorted sets have integer members.
When iterating a sorted set containing integer members, our iterator
abstraction based on ZSCAN was always returning "0" as a member value
after the first $member => $score pair because of a wrong assumption
on how the PHP function array_shift() (used internally to advance to
the next pair in our buffered response to ZSCAN) works.

Fixes #216.
2014-10-21 11:58:11 +02:00
Daniele Alessandri dc2cb3c639 Fix bug in ZSCAN-based iterator when sorted sets have integer members.
When iterating a sorted set containing integer members, our iterator
abstraction based on ZSCAN was always returning "0" as a member value
after the first $member => $score pair because of a wrong assumption
on how the PHP function array_shift() (used internally to advance to
the next pair in our buffered response to ZSCAN) works.

Fixes #216.
2014-10-21 11:57:43 +02:00
Daniele Alessandri 54c8a1ee9b [tests] Relax checks on invalid expire time messages.
Previously there was a bug in Redis that returned the wrong command
in -ERR messages when passing an invalid expire time with SETEX and
PSETEX. Now that the bug has been fixed and that travis-ci uses a an
updated version of Redis, our test suite turned red.
2014-10-21 11:23:19 +02:00
Daniele Alessandri d09c4f32f3 [tests] Relax checks on invalid expire time messages.
Previously there was a bug in Redis that returned the wrong command
in -ERR messages when passing an invalid expire time with SETEX and
PSETEX. Now that the bug has been fixed and that travis-ci uses a an
updated version of Redis, our test suite turned red.
2014-10-21 11:16:55 +02:00
Vitaly Chirkov ed1e541dc6 Add missing doc for zincrby in ClientInterface 2014-10-21 11:10:05 +02:00
Daniele Alessandri ffdb17dacc Merge remote-tracking branch 'github/pr/218' into v1.0 2014-10-21 11:08:47 +02:00
Daniele Alessandri cc51db9009 Connection parameters are not the focus of the client options example. 2014-10-21 11:05:36 +02:00
Jordi Boggiano a123ae9159 Add example for client config 2014-10-21 11:05:08 +02:00
Daniele Alessandri 488c17f8bd Merge branch 'github/pr/217' into v1.0 2014-10-21 10:56:18 +02:00
Daniele Alessandri e18192474a Connection parameters are not the focus of the client options example. 2014-10-21 10:53:52 +02:00
Vitaly Chirkov a3300949fc Add missing doc for zincrby in ClientInterface 2014-10-19 00:39:57 +04:00
Jordi Boggiano 7004a9fd93 Add example for client config 2014-10-10 17:20:11 +01:00
Daniele Alessandri 0533b50c6b Add hhvm-nightly as a testing environment on Travis CI. 2014-09-05 11:03:03 +02:00
Daniele Alessandri 76ee6a2f24 Merge remote-tracking branch 'github/pr/208'
Conflicts:
	README.md
	composer.json
2014-09-05 11:01:47 +02:00
Daniele Alessandri d0b6f7992e Add hhvm-nightly as a testing environment on Travis CI. 2014-09-05 10:49:17 +02:00
Daniele Alessandri 69ad62b59d Merge remote-tracking branch 'github/pr/208' into v1.0 2014-09-05 10:45:02 +02:00
Daniele Alessandri ec099a3b6e Back to development.
Forgot to do so earlier, as usual...

[ci skip]
2014-09-05 10:44:21 +02:00
Thibaud BARDIN 3d10be888c Change order of throws 2014-09-01 03:10:08 +02:00
Thibaud BARDIN 0fc5c5ee77 [phpdoc] Fix missing throws of phpdoc headers. 2014-08-09 23:14:45 +02:00
Daniele Alessandri 99f4312a6f Apply workaround for bug in versions of PHP < 5.3.9.
This change is needed to address a bug in older versions of PHP 5.3
affecting inheritance (see https://bugs.php.net/bug.php?id=66818).
2014-08-08 15:49:05 +02:00
Daniele Alessandri cc748d509f Bump minimum required version of PHP to 5.3.9.
This change is needed to address a bug in older versions of PHP 5.3
affecting inheritance (see https://bugs.php.net/bug.php?id=66818).

We will most likely resort to a workaround in v1.0 to stick with the
currently required minimum version of PHP (>= 5.3.2), but v1.1 will
surely require => 5.3.9.

[ci skip]
2014-08-08 15:29:32 +02:00
Graham Campbell 6b088e4bda Removed hhvm from allow failures 2014-08-08 14:29:47 +02:00
Daniele Alessandri 8775fdfd80 Merge pull request #204 from GrahamCampbell/patch-1
Removed hhvm from allow failures
2014-08-08 14:26:30 +02:00
Graham Campbell fee8e709cf Removed hhvm from allow failures 2014-08-08 13:12:33 +01:00
Daniele Alessandri 72ebf5d064 Add more badges to README. 2014-08-08 13:57:35 +02:00
Daniele Alessandri 65c2f4bc4f Back to development.
[ci skip]
2014-08-08 13:57:05 +02:00
Daniele Alessandri e9598b65f4 Add more badges to README. 2014-08-08 13:52:28 +02:00
Daniele Alessandri 180fcdbe5a Merge pull request #200 from GrahamCampbell/patch-1
Updated master branch alias
2014-08-01 15:10:21 +02:00
Graham Campbell 80a5bfa4c1 Added a 1.1 branch alias 2014-08-01 13:49:39 +01:00
Daniele Alessandri 88fa032c33 Remove extras from composer.json.
[ci skip]
2014-08-01 12:20:02 +02:00
Daniele Alessandri d26db6f0c2 Remove extras from composer.json.
[ci skip]
2014-08-01 12:17:16 +02:00
Daniele Alessandri d4be306d0a ... and here comes Predis v1.0.0! 2014-08-01 11:59:50 +02:00
Daniele Alessandri 25d0008b2f Apply minor fix in CHANGELOG. 2014-08-01 11:46:56 +02:00
Daniele Alessandri 30274aa242 Integrate CHANGELOG notes from v0.8.7. 2014-08-01 11:44:26 +02:00
Daniele Alessandri f5ba47ad74 Change response parser for ZSCAN to match changes applied to ZRANGE. 2014-07-30 16:45:00 +02:00
Daniele Alessandri fbb0236840 Apply minor code-styling changes. 2014-07-30 15:30:02 +02:00
Daniele Alessandri ba5e501346 Use arguments as defined by Redis when calling WATCH internally. 2014-07-30 14:18:20 +02:00
Daniele Alessandri ab9cbe712f Specify type hint in interface. 2014-07-30 11:31:31 +02:00
Daniele Alessandri 16f2d8a768 Stick to 2.8 as the default target for the test suite.
Even though tere are no changes between running the test suite against
3.0 and 2.8, we will stick with the current stable Redis version as
the default target and switch to 3.0 as soon as it will be released.

[ci skip]
2014-07-30 11:08:56 +02:00
Daniele Alessandri 7c9e4ab595 Update CHANGELOG.
[ci skip]
2014-07-28 20:50:01 +02:00
Daniele Alessandri b6389e4a03 Switch to "3.0" as the default server profile.
Redis 3.0 does not really change much in terms of commands (most of
the ones implemented in the "unstable" branch have been backported to
the "2.8" branch after all) aside from a few cluster-related ones, so
we can bump the default version without worries.
2014-07-28 20:36:12 +02:00
Daniele Alessandri dedc1ba0a9 Move command "COMMAND" to the server profile for Redis 2.8.
This command has been backported from the "unstable" branch of Redis
to the "2.8" one, and it is available since 2.8.13.
2014-07-28 20:30:09 +02:00
Daniele Alessandri df653a7c00 Minor code styling and phpdoc changes. 2014-07-28 12:04:07 +02:00
Daniele Alessandri 5c02e4e47b Update README.
[ci skip]
2014-07-28 10:40:01 +02:00
Daniele Alessandri c2b24bd873 Merge branch 'v1.0/inspection-fixes' 2014-07-28 00:02:54 +02:00
Daniele Alessandri 45e351be79 [phpdoc] Fix formatting of phpdoc headers. 2014-07-27 23:59:37 +02:00
Daniele Alessandri b5cdab35c7 Remove useless argument from method signatures in WebdisConnection. 2014-07-27 23:06:21 +02:00
Daniele Alessandri dbfc1a74ba More random fixes after inspection. 2014-07-27 23:06:17 +02:00
Daniele Alessandri 4e1186f845 [phpdoc] Fix undefined classes. 2014-07-27 21:57:50 +02:00
Daniele Alessandri aa5c893d5a [phpdoc] Fix undefined namespaces. 2014-07-27 21:57:40 +02:00
Daniele Alessandri fff303a03b Comply with PSR-2 on intentional fall-through in non-empty case. 2014-07-27 21:57:40 +02:00
Daniele Alessandri 78ec22563a The \Iterator interface returns void for next(). 2014-07-27 21:57:40 +02:00
Daniele Alessandri 30254a2594 [phpdoc] Various phpdoc fixes. 2014-07-27 21:57:13 +02:00
Daniele Alessandri f372029cfc Fix code smells. 2014-07-27 20:13:24 +02:00
Daniele Alessandri 87aba18002 Merge branch 'v1.0/phpdocs' 2014-07-27 19:19:44 +02:00
Daniele Alessandri dc33d62b77 Miscellaneous fixes for "use" directives. 2014-07-27 19:19:20 +02:00
Daniele Alessandri b230e243f5 Predis\PubSub\DispatcherLoop should take a PubSub consumer instance. 2014-07-27 16:53:46 +02:00
Daniele Alessandri 44c9232b13 Update README.
[ci skip]
2014-07-27 15:41:06 +02:00
Daniele Alessandri 776f5831a6 Merge branch 'v1.0/custom-parameters' 2014-07-27 14:19:30 +02:00
Daniele Alessandri 31e2516156 Makes it easier to use a custom parameters class.
Simply overriding one method of the standard connection factory class,
used internally by Predis, allows developers to use their own custom
connection parameters classes through the whole library.

For example, in order to support Heroku-style URIs one can do:

  class HerokuParameters extends Predis\Connection\Parameters
  {
    protected function filter(array $parameters)
    {
      if (
        isset($parameters['scheme']) &&
        $parameters['scheme'] === 'redis'
      ) {
        $parameters['scheme'] = 'tcp';
      }

      if (isset($parameters['pass'])) {
        $parameters['password'] = $parameters['pass'];
      }

      unset($parameters['user'], $parameters['pass']);

      return $parameters;
    }
  }

  class ConnectionFactory extends Predis\Connection\Factory
  {
    protected function createParameters($parameters)
    {
      return HerokuParameters::create($parameters);
    }
  }

  $client = new Predis\Client($_ENV['REDISCLOUD_URL'], [
    'connections' => new ConnectionFactory()
  ]);

This idea comes in response to #196, but since we do not want to bake
support for SaaS-specific URIs in Predis this is the best compromise
we can offer leave developers free to implement their own logic for
handling these kind of URIs with the additional benefit of having it
available through the whole library (think of cluster or replication
where you have multiple nodes, thus multiple instances of connection
parameters to create).
2014-07-27 14:13:30 +02:00
Daniele Alessandri b379d4f1b3 Merge pull request #194 from GrahamCampbell/gitstuff
Added a .gitattributes file
2014-07-27 11:46:51 +02:00
Graham Campbell 60a863f5fc Include docs 2014-07-27 10:40:38 +01:00
Daniele Alessandri f7d8088bba Added @method tags to phpdoc header of Predis\ClientContextInterface. 2014-07-27 10:53:40 +02:00
Daniele Alessandri 38710cd69b Added Predis\ClientContextInterface.
This interface replaces Predis\ExecutableContextInterface and it is
used by client-side contexts such as pipelines or transactions.
2014-07-27 10:46:11 +02:00
Graham Campbell 7fa17b2ebc Added a .gitattributes file 2014-07-26 15:30:23 +01:00
Daniele Alessandri dcb57ea08d Fix method visibility in Predis\Pipeline\ConnectionErrorProof. 2014-07-25 16:44:04 +02:00
Daniele Alessandri 872d953b50 Update README.
[ci skip]
2014-07-25 16:40:21 +02:00
Daniele Alessandri f630ff809f Update README.
[ci skip]
2014-07-25 16:30:38 +02:00
Daniele Alessandri 19bad41582 Update README. 2014-07-25 13:21:12 +02:00
Daniele Alessandri be6b7fe5f0 Update README.
[ci skip]
2014-07-25 13:16:09 +02:00
Daniele Alessandri 647c51a5b3 Update README.
[ci skip]
2014-07-25 13:11:33 +02:00
Daniele Alessandri dd1b63ae3b Update README.
[ci skip]
2014-07-25 13:09:22 +02:00
Daniele Alessandri 7146b69707 Update README.
[ci skip]
2014-07-25 13:08:10 +02:00
Daniele Alessandri 0bd7684d14 Add paragraphs in README on how to configure cluster and replication.
[ci skip]
2014-07-25 13:07:10 +02:00
Daniele Alessandri 558e10963c Merge branch 'v1.0/refactor-cluster-internals' 2014-07-25 10:58:03 +02:00
Daniele Alessandri 14a4303a54 Apply easy micro-optimization. 2014-07-23 17:07:03 +02:00
Daniele Alessandri 7d78600506 Add phpdocs for Redis commands in Predis\ClientInterface.
This commit addresses a long-standing feature request posted in #89.
2014-07-23 16:01:11 +02:00
Daniele Alessandri 784c555b67 Minor phpdoc fix. 2014-07-23 15:33:27 +02:00
Daniele Alessandri a67d35b799 Remove useless interface Predis\BasicClientInterface. 2014-07-23 15:30:18 +02:00
Daniele Alessandri 0ee5233f4f Promote __call() method to Predis\ClientInterface. 2014-07-23 15:18:09 +02:00
Daniele Alessandri 9a05d43737 Fix read/write timeouts with PhpiredisStreamConnection.
This is a regression of commit 4db0017, using stream_socket_recvfrom()
bypasses stream wrappers thus read/write timeouts handled by PHP. The
only way to make them work again is to fetch the raw socket from the
stream resource and use socket_import_stream() which is unfortunately
a PHP 5.4+ function.
2014-07-23 12:26:33 +02:00
Daniele Alessandri 6fe56985fc Simplify implementation of Predis\Connection\Parameters.
Casting values supplied by users should be done by the consumer since
we cannot cover any possible use case anyway. It is still possible to
subclass Predis\Connection\Parameters and override the filter() method
to convert certain values if deemed necessary.
2014-07-23 11:57:23 +02:00
Daniele Alessandri 57363f6d11 Update CHANGELOG.
[ci skip]
2014-07-23 11:33:01 +02:00
Daniele Alessandri fdf5894022 Make connection factory mandatory for RedisCluster constructor. 2014-07-23 11:13:09 +02:00
Daniele Alessandri 6147f34478 [tests] Fix wrong test. 2014-07-23 11:06:35 +02:00
Daniele Alessandri 2ff8c37104 Redesign the whole internals for clustering.
This change actually had a positive impact on the design of the whole
internals for clustering which is now cleaner and easier to maintain.
It is still far from perfect, but we also have to keep performances in
consideration so we can say that we ended up with a good compromise.

Previously Predis assigned an hash to each command instance which was
computed from its key, now we changed approach and the library caches
the slot assigned to each command. This works for both our client-side
sharding cluster and the upcoming redis-cluster, but the former is the
one that needed most changes.

The PredisCluster aggregate connection now only takes an instance of
StrategyInterface, which in turn wraps the chosen distributor. After
all, in order to be able to calculate the assigned slot for a command
or key, the cluster strategy must have access to the distributor that
manages the distribution of the whole keyspace. Nothing really changes
in terms of configurability as it is still possible to decide which
distributor to use for client-side sharding, it is simply different:

  $distributor = new Predis\Cluster\Distribution\KetamaRing();
  $strategy = new Predis\Cluster\PredisStrategy($distributor);
  $cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);

As for the RedisCluster aggregate connection, the only change is that
the mathematical operation of calculating the assigned slot from a key
has been completely moved inside the cluster strategy instance.

The strategy for redis-cluster does not use external distributors so
trying to StrategyInterface::getDistributor() will throw an exception.
This may change in future releases, but this is not a priority since
redis-cluster relies on a fixed, well-defined distribution mechanism.
2014-07-22 18:13:12 +02:00
Daniele Alessandri 69bef7fd35 Update example to avoid breaking when run against Redis 3.0.
[ci skip]
2014-07-21 18:20:41 +02:00
Daniele Alessandri 346986099d Rename method "enableAutoSlotsMap()" to "useClusterSlots()". 2014-07-21 14:38:20 +02:00
Daniele Alessandri 9213f02da8 Fix phpdocs. 2014-07-21 14:37:29 +02:00
Daniele Alessandri 4ab2bcea64 Fetch updated slots map from node indicated by -MOVED response.
This optimization makes it possible to fetch the slots map directly
from the server indicated by the -MOVED response eliminating the need
to use a random node in the pool, which in turn could require Predis
to open a new and useless connection.
2014-07-21 14:02:48 +02:00
Daniele Alessandri 217bd69b7f Minor phpdocs fixes.
[ci skip]
2014-07-21 14:02:48 +02:00
Daniele Alessandri bd00b8cfe2 Fetch cluster slots from node upon first -MOVED response.
This is a more sane default as it allows users to indicate only a few
servers of the whole cluster composition, while it previously required
a more complex configuration of the client using client options.

This feature can be disabled using the "enableAutoSlotsMap()" method.
2014-07-21 14:02:43 +02:00
Daniele Alessandri a32eaf627b Remove useless method.
It is better to wrap explicitly a multibulk response iterator into a
multibulk tuple response iterator instead of hard-coding that into a
specialized method.
2014-07-21 11:18:25 +02:00
Daniele Alessandri e89f5cbc39 Add method to get connection factory from redis-cluster connection. 2014-07-21 11:11:52 +02:00
Daniele Alessandri 4188dc51bf Make it possible to specify a custom strategy for redis-cluster. 2014-07-21 10:56:32 +02:00
Daniele Alessandri 7b41029fd7 Light rewording and reorganization of README.
[ci skip]
2014-07-21 10:47:06 +02:00
Daniele Alessandri eb8de52269 New command: COMMAND (Redis 3.0.0).
The command returns the response as is, but it would probably be not a
bad idea to parse it to restructure returned info using named arrays,
making it easier to access single commands and their info.

We will keep it as is for now, and investigate this change later.
2014-07-18 12:56:34 +02:00
Daniele Alessandri 202c558103 Run php-cs against source code. 2014-07-17 15:59:43 +02:00
Daniele Alessandri 89e662dc89 Use same strategy for both client-side sharding and redis-cluster.
This change is possible because, after a few changes in redis-cluster,
our default cluster strategy used for client side sharding and the one
used for redis-cluster turned out to be exactly the same, except for
the hashing function used to calculate distribution.

Actually some checks used to enforce correctness are redundant in the
context of redis-cluster (e.g. the one used to make sure that keys in
requests performing cross-keys operations will hash to the same slot,
which is performed by the server) so we could also add a more dumb and
permissive cluster strategy that relies on checks performed by Redis.

Differently to v0.8, the strategy for client-side sharding now uses
the same rules for extracting hash tags from keys especially when
empty tags are found in the string.
2014-07-17 12:48:46 +02:00
Daniele Alessandri 356f22a062 Implement PING in PUB/SUB loop abstraction for Redis 3.0.0. 2014-07-17 12:16:54 +02:00
Daniele Alessandri 823f615699 Update CHANGELOG.
[ci skip]
2014-07-16 19:11:58 +02:00
Daniele Alessandri 7e58ded8dc Update CHANGELOG.
[ci skip]
2014-07-16 14:10:07 +02:00
Daniele Alessandri 2969982a4f Update README.
[ci skip]
2014-07-16 13:06:25 +02:00
Daniele Alessandri 88da187344 Add dedicated server profile for Redis 3.0. 2014-07-16 12:59:48 +02:00
Daniele Alessandri a33781e58c Merge branch 'v1.0/psr-4'
This merge closes #168.

Conflicts:
	src/Command/KeyKeysV12x.php
	src/Profile/RedisVersion120.php
2014-07-16 12:56:27 +02:00
Daniele Alessandri a074cdb79b Update CHANGELOG.
[ci skip]
2014-07-16 11:42:01 +02:00
Daniele Alessandri 63992a0a6e Remove parsing of allocation stats from responses to INFO.
The allocation stats section was most likely something available in
betas of some older release of Redis, it is not even reported on the
official documentation.
2014-07-16 11:21:12 +02:00
Daniele Alessandri ca4ec79575 Fix bug when checking for support for the UNWATCH command. 2014-07-16 11:17:21 +02:00
Daniele Alessandri 2e0c55ac57 Remove support for Redis 1.2.
Actually we have just removed the server profile so nothing stops you
from reimplementing it, but Redis 2.0 has been released 4 years ago so
we are speaking of ancient releases that should probably not even be
used anymore.
2014-07-16 11:14:36 +02:00
Daniele Alessandri 9edc11dc8e Switch to CLUSTER SLOTS instead of CLUSTER NODES for redis-cluster.
CLUSTER SLOTS returns a structured response easier to handle compared
to the bulk response of CLUSTER NODES which must be parsed making the
whole thing more fragile.

CLUSTER SLOTS has been added in Redis 3.0.0b7.
2014-07-15 18:52:09 +02:00
Daniele Alessandri 50334ed3f4 Update CHANGELOG.
[ci skip]
2014-07-15 12:39:46 +02:00
Daniele Alessandri 1319574b4e Rewrite pear packager script.
We still use Onion's package.ini for the configuration of the package
to keep things simple, but we might switch to a more compact solution
in the future since we do not really need much of its features.
2014-07-14 18:10:07 +02:00
Daniele Alessandri 029822fe22 Move source files from "lib/" to "src/". 2014-07-14 18:04:18 +02:00
Daniele Alessandri d226923484 Migrate from PSR-0 to PSR-4. 2014-07-14 18:02:42 +02:00
Daniele Alessandri 959734cf8c Porperly handle -ERR instead of +QUEUED inside MULTI ... EXEC.
Error responses such as -OOM or -ERR on invalid arguments in commands
are returned immediatly instead of +QUEUED when using a transaction,
which is a condition that had not been tested enough. This condition
led to a bug in which Predis was not invalidating the transaction, so
when trying to create a new transaction Redis returned a "-ERR MULTI
calls can not be nested".

This commit fixes #187.
2014-07-14 16:28:29 +02:00
Daniele Alessandri dd29068845 Merge branch 'github/pr/188' 2014-07-14 11:35:07 +02:00
Daniele Alessandri 36a04e84d7 Update CHANGELOG. 2014-07-14 11:34:50 +02:00
Ian Babrou 5b4a7970bb returning associative array from zrange command family 2014-07-14 13:16:26 +04:00
Ian Babrou 235427950f prevent uncaught broken pipe error 2014-07-07 11:50:37 +02:00
Daniele Alessandri 45da0fca55 Merge branch 'github/pr/182' 2014-07-07 10:52:58 +02:00
Daniele Alessandri 2d53db7b9b Rework PR to use "goto" instead of a "while ... do" loop. 2014-07-07 10:50:17 +02:00
Gwilym Evans f05cb1b46d use a loop instead of recursion in CursorBasedIterator
servers with large sets of keys will cause memory and stack exhaustion if recursion is used
2014-06-26 12:56:00 +10:00
Daniele Alessandri 4db00173f3 Use stream_socket_recvfrom() in PhpiredisStreamConnection.
Similarly to the socket-ext based connection using phpiredis, in our
stream based PhpiredisStreamConnection class we should read data from
the stream using stream_socket_recvfrom() instead of fread() because
the latter could block until a timeout is reached when the read buffer
contains less data then the specified length.

IMPORTANT: stream_socket_recvfrom() bypasses stream wrappers which
means that TLS/SSL, as requested by PR #158, won't ever work with
this connection class as the function returns the original encrypted
bytes.

This commit fixes issue #180.
2014-06-23 14:31:02 +02:00
Daniele Alessandri a2265b12b3 Remove implementation of Predis\Command\RawCommand::__toString().
See #151 and message of commit 5c5dd40, forgot to apply the same
change to the Predis\Command\RawCommand class.
2014-06-12 11:57:54 +02:00
Daniele Alessandri 0cd56406fe Just rename a couple of local variables. 2014-06-10 10:56:33 +02:00
Daniele Alessandri e575c32cb4 Rename RedisCluster::askClusterNodes() to askSlotsMap().
This is more consistent with the actual purpose of this method and
more in-line with a possible future change in the underlying command
used to retrieve the slots map if redis-cluster will implement the
CLUSTER SLOTS command.
2014-06-10 10:36:17 +02:00
Daniele Alessandri 42f237e306 [tests] Use annotations to specify expected Redis server version.
This change targets only method annotations and aims to make the body
of tests more readable using the @requiresRedisVersion annotation.

Tests using this annotation requires to be assigned the "connected"
group of tests because they create a connection to the Redis instance
specified in phpunit.xml to fetch its the version.

This is a quick example of how this annotation can be used:

    /**
     * @group connected
     * @requiresRedisVersion >= 2.8.9
     */
    public function testExecutedOnlyWithMatchingRedisVersion()
    {
    }

Future improvements (currently not needed) include:

  * Same annotation working on a class-level (but still applied only
    to test methods with an explicitly assigned @group connected).

  * Ability to specify a version range.

Meh

Meh
2014-06-09 17:31:18 +02:00
Daniele Alessandri 940326e5bd New command: ZREMRANGEBYLEX (Redis 2.8.9). 2014-06-09 15:35:28 +02:00
Daniele Alessandri ea32f74512 New command: ZRANGEBYLEX (Redis 2.8.9). 2014-06-09 15:26:17 +02:00
Daniele Alessandri 8dbac3dd73 New command: ZLEXCOUNT (Redis 2.8.9). 2014-06-09 15:17:36 +02:00
Daniele Alessandri 5a474c5a32 Rename alias used in Predis\Client for Predis\Transaction\MultiExec. 2014-06-03 18:56:48 +02:00
Daniele Alessandri 0148743a76 Fix parsing of the output of CLUSTER NODES to fetch slots map.
There was an error in presence of slaves in the cluster configuration,
see #165 for reference.
2014-06-03 16:24:27 +02:00
Daniele Alessandri 5c935d97bd Merge branch 'v1.0.0-dev/connection-namespace' 2014-06-03 15:45:57 +02:00
Daniele Alessandri 1fd113c570 Rename ComposableProtocolProcessor to CompositeProtocolProcessor. 2014-06-03 15:45:40 +02:00
Daniele Alessandri abd284c972 Complete reorganization of the Predis\Connection namespace.
* Renamed SingleConnectionInterface to NodeConnectionInterface since
  this name is better and makes even more sense in the context of
  cluster and replication scenarios.

* Moved specialized aggregate connections (the ones implementing both
  predis and redis cluster and master/slave replication) in a newly
  created Predis\Connection\Aggregate sub-namespace.

* Removed the "Connection" part from names of aggregate connection
  interfaces in the Predis\Connection\Aggregate sub-namespace.

* Changed "Composable" to "Composite" in the name of interfaces and
  classes that can use pluggable protocol processors.
2014-06-03 15:19:32 +02:00
Daniele Alessandri ff2e0823ec Merge remote-tracking branch 'github/pr/174' 2014-05-30 12:32:40 +02:00
Graham Campbell a6c6951bf8 Added 1.0 branch alias
Let's allow people to install predis using "1.0.x@dev", "~1.0@dev", or any other valid version constraint rather than typing "dev-master" which is really horrible.
2014-05-30 11:24:39 +01:00
Daniele Alessandri 87417f4d7e Skip integration tests for HyperLogLog commands on Redis < 2.8.9.
Caught this by running the test suite on TravisCI which still runs an
older version of Redis 2.8. We should find a more decent way to handle
differences in profiles when commands get added between patch releases
of Redis, our custom skip method will do for now.
2014-05-30 12:19:05 +02:00
Daniele Alessandri 2aa0b071fc New commands: PFADD, PFCOUNT, PFMERGE (Redis 2.8.9).
Many thanks to @rubensayshi for his initial commits on this in #163,
but I had to start from scratch for the master branch first.
2014-05-30 11:32:39 +02:00
Alexey Kupershtokh f784dfad84 Enable INCRBYFLOAT in cluster mode 2014-05-28 13:00:24 +02:00
Daniele Alessandri 10c2f321ff Merge branch 'pr170-master' 2014-05-28 12:54:16 +02:00
thbourlove 7da3da776f use phpunit 4.x instead of 3.x 2014-05-28 12:54:04 +02:00
thbourlove 90cb71ac4a isntall requirement with a better way 2014-05-28 12:53:58 +02:00
thbourlove 2d4383c891 add phpunit as dev requirement 2014-05-28 12:53:50 +02:00
Daniele Alessandri 8ea76f79c7 Minor rewording in CHANGELOG. 2014-03-25 15:33:27 +01:00
Daniele Alessandri 5c5dd40527 Remove implementation of Predis\Command\Command::__toString().
Issue #151 pointed to a flaw in how command instances were converted
to strings: we were simply truncating their arguments when exceeding
a certain size as this was mostly intended for logging or debugging,
but this approach breaks strings containing multibyte characters so
we decided to drop this feature altogether for the sake of simplicity.

It is still possible to replicate the same (and eventually improved)
behavior externally by fetching ID and arguments of a command out of
a command instance using the public methods made available by the
Predis\Command\CommandInterface.
2014-03-25 15:32:20 +01:00
Daniele Alessandri 4638e05865 Tweak sentence in CHANGELOG.
[ci skip]
2014-03-25 15:05:37 +01:00
Daniele Alessandri 4784291640 Failures for PHP 5.6 on Travis CI are not allowed anymore. 2014-03-25 14:49:49 +01:00
Daniele Alessandri a51ff2d6e5 Port #156 to the current master branch.
This fix the parsing of responses to INFO when the node is configured
to work with redis-sentinel.
2014-03-25 14:49:25 +01:00
Daniele Alessandri 451d28ee66 Let's set this in stone: next major version is going to be v1.0.0.
[ci skip]
2014-02-12 10:27:42 +01:00
Daniele Alessandri e23fd9bea8 Use redis-cluster rules for empty key tags for client-side sharding.
This commit represents a breaking change when the first occurrence of
"{}" is found in a key because it will produce a different hash than
previous versions of Predis, thus leading to a different partitioning.

If you really need to stick with the old behavior, you can subclass
Predis\Cluster\PredisStrategy and override extractKeyTag() using the
old implementation of this method and pass the strategy instance when
initializing the cluster connection via client options.
2014-02-11 19:06:47 +01:00
Daniele Alessandri 8fbe658ca8 Fix implementation for hash tags extraction from keys.
We now fully comply with the specifications defined by Redis.
2014-02-11 19:06:44 +01:00
Daniele Alessandri d89027d2da Add PHP 5.6 to the build matix of Travis-CI.
Builds are allowed to fail for now as PHP 5.6 is still in alpha stage.
2014-02-11 16:35:39 +01:00
Daniele Alessandri 26289f47ec Add support for key hash tags in redis-cluster (Redis 3.0.0b1).
Multi-keys operations are not allowed even when keys generate the same
hash but this will probably be supported in later betas of Redis which
means we will basically end up reusing the whole strategy used for
client-side sharding.

Ported from the v0.8 branch.
2014-02-11 15:44:37 +01:00
Daniele Alessandri ba0dc12d5b Merge pull request #146 from GrahamCampbell/master
Travis Tweaks
2014-02-10 21:00:02 +01:00
Graham Campbell 42a9489f11 Updated travis.yml 2014-02-10 19:49:26 +00:00
Daniele Alessandri 51febb32a9 Update CHANGELOG. 2014-01-16 15:26:30 +01:00
Daniele Alessandri 0a5363dddf Bump year in LICENSE.
[ci skip]
2014-01-10 17:47:32 +01:00
Daniele Alessandri b852eeed9f [bin] Add missing executable in the repository for new script. 2014-01-08 17:37:02 +01:00
Daniele Alessandri 10dcac8f05 [bin] Add helper script to automate PEAR package creation.
Note that this script takes care of customizing `phpunit.xml.dist` so
that tests can be run as soon as the PEAR package has been installed
as requested in #126.
2014-01-08 17:34:52 +01:00
Daniele Alessandri ae61a0fd2b [tests] Use Predis\Autoload from include_path when not in repository.
This is useful only for running the test suite after installing the
PEAR package, see #126 for reference.
2014-01-08 17:34:41 +01:00
Daniele Alessandri dc6c298960 Reword paragraph in README about HHVM compatibility. 2013-12-22 16:19:05 +01:00
Daniele Alessandri e04c7d51b8 Explicitly return null value. 2013-12-22 16:19:05 +01:00
Daniele Alessandri da8a203a75 Remove useless return statement. 2013-12-22 16:19:04 +01:00
Daniele Alessandri bf32f4b87c [tests] Remove unused "use" directives. 2013-12-22 16:19:04 +01:00
Daniele Alessandri 46671b9095 Run php-cs against test suite.
[ci skip]
2013-12-22 16:18:59 +01:00
Daniele Alessandri 9a38d2caec Move @property-read tags for parameters and options to interfaces.
This actually makes sense since whatever the actual implementation is,
classes implementing these interfaces should provide at least those
properties that are actively used through the library.
2013-12-22 15:03:31 +01:00
Daniele Alessandri cfa456fdd1 [tests] Fix a couple of innocuous glitches. 2013-12-22 15:00:51 +01:00
Daniele Alessandri 6a577a0eb5 Apply more phpdoc fixes. 2013-12-22 15:00:51 +01:00
Daniele Alessandri 8357af177e [test] Fix wrong variable. 2013-12-22 15:00:50 +01:00
Daniele Alessandri 7ebb8a8b42 [tests] Fix a couple of glitches in our base PHPUnit classes. 2013-12-22 15:00:50 +01:00
Daniele Alessandri 728d9dceb5 [tests] No need to reassign $exception. 2013-12-22 15:00:41 +01:00
Daniele Alessandri a092f6d4da Fix phpdocs for fluent interfaces.
[ci skip]
2013-12-22 13:52:57 +01:00
Daniele Alessandri 3befbb3ac2 Make Pipeline::executeCommand() return $this for fluent interface. 2013-12-22 13:40:36 +01:00
Daniele Alessandri 8d8a618d0e Add @property-read tags to client options class.
[ci skip]
2013-12-22 13:28:22 +01:00
Daniele Alessandri 5e1ea94f4a Add @property-read tags to parameters class.
[ci skip]
2013-12-22 12:59:40 +01:00
Daniele Alessandri b9b899eaf0 Fix incorrect usage of instance method in static method.
We also added a test to check that the socket-based connection backend
throws an exception when unable to resolve hostnames.
2013-12-22 12:38:54 +01:00
Daniele Alessandri 5065541cc6 Remove erroneous duplication of INFO in Redis profiles.
This oversight didn't end up in a blatant bug only because the correct
handler definition for INFO replaced the old class in the profile.
2013-12-22 12:23:55 +01:00
Daniele Alessandri f5a7d8ece8 Add a note about missing break in switch statement.
[ci skip]
2013-12-22 12:20:59 +01:00
Daniele Alessandri 25cd43033f Fix some errors in phpdocs.
[ci skip]
2013-12-22 12:12:49 +01:00
Daniele Alessandri 90d8c684f0 Use a more dynamic variant for caching common status responses. 2013-12-22 11:01:54 +01:00
Daniele Alessandri 09f9133df7 Fix small oversight.
Bug was not severe since +QUEUED status responses were returned anyway
but they were not cached as expected. We added a test in the suite.

This fixes #142.
2013-12-22 10:53:32 +01:00
Daniele Alessandri bff7906f68 Apply minor CS fixes.
[ci skip]
2013-12-21 18:24:51 +01:00
Daniele Alessandri b73606de68 Replace remaining occurrences of "boolean" with "bool" in phpdocs.
[ci skip]
2013-12-21 12:48:43 +01:00
Daniele Alessandri c127d02e92 Remove leftover "use" directive.
[ci skip]
2013-12-21 12:46:22 +01:00
Daniele Alessandri 6693980b14 Fix README after renaming of examples.
[ci skip]
2013-12-21 12:43:56 +01:00
Daniele Alessandri 7ba465048f Do not throw exception when connection has been already established.
The base abstract connection class now returns a bool to indicate when
the actual connect() operation has been performed on the underlying
resource. This return value is not part of the interface so extending
classes can decide to not return any value.
2013-12-21 12:32:15 +01:00
Daniele Alessandri 5f81bfcde3 Improve handling of -MOVED and -ASK responses.
This change improves code reusing and simplifies the internals of
our redis-cluster connection backend.
2013-12-21 11:56:40 +01:00
Daniele Alessandri 2aa97e3e61 Apply fixes for consistency.
I know that importing classes and interfaces for the root namespace
using the "use" directive is weird and totally uncommon...
2013-12-21 11:26:09 +01:00
Daniele Alessandri 131a5a4ef9 Fix a few exceptions. 2013-12-21 11:08:29 +01:00
Daniele Alessandri d1ec791ae9 Rename examples and update some comments.
[ci skip]
2013-12-21 10:50:08 +01:00
Daniele Alessandri 8916f9a9ee Fix a few exception messages. 2013-12-21 10:07:56 +01:00
Daniele Alessandri 3ac4141bcb [bin] Minor fix in comments.
[ci skip]
2013-12-21 10:02:26 +01:00
Daniele Alessandri 587bf0b1e5 [tests] Add $message as third parameter for our custom assertions. 2013-12-19 11:50:39 +01:00
Daniele Alessandri 7cf9cfc496 Update phpdocs.
[ci skip]
2013-12-19 11:20:27 +01:00
Daniele Alessandri f7fea2e430 Update README.
[ci skip]
2013-12-18 16:06:34 +01:00
Daniele Alessandri c51485b318 Update README.
[ci skip]
2013-12-18 16:04:22 +01:00
Daniele Alessandri e1fb9ed1d4 Update README.
[ci skip]
2013-12-18 11:52:19 +01:00
Daniele Alessandri 913bcb3b20 Merge branch 'v0.9/hhvm-compatibility' 2013-12-17 16:37:26 +01:00
Daniele Alessandri 2d23edc691 Add a note about Predis on HHVM in the README. 2013-12-17 16:36:03 +01:00
Daniele Alessandri af2548581e Add HHVM to the build matrix on Travis CI.
We allow failures on builds run against HHVM since it is still being
developed and things could break anytime, but at least this gives us
a decent indicator of the level of compatibility of Predis with this
runtime.
2013-12-17 16:20:48 +01:00
Daniele Alessandri fdf63bc03d Make Predis compatible with HHVM (at least 2.3.0).
Achieving compatibility actually required a few marginal changes:

  - HHVM still has some issues with re-entrant calls to __get(). The
    applied change is an hack simply because it is ugly, but it is not
    wrong and does not break the signature of the options interface.
  - Since we cannot rely on the PHP version to detect the availability
    of socket_import_stream(), we switched to function_exists(). As an
    added bonus, using function_exists() is twice faster.
  - In the test suite we removed an assertion for the message of an
    E_WARNING simply because HHVM emits a different message. Checking
    for the warning is actually enough in that context.

While the whole test suite passes on HHVM 2.3.0, please remember that
HHVM is still in development and things could break anytime especially
in some obscure corner cases.
2013-12-17 16:09:20 +01:00
Daniele Alessandri 2a6409590c Run php-cs against test suite. 2013-12-17 12:55:56 +01:00
Daniele Alessandri 02e43143d3 Run php-cs against codebase. 2013-12-17 12:53:36 +01:00
Daniele Alessandri 5529e33047 Rework classes and interfaces in Predis\Command\Processor namespace.
- Renamed `Predis\Command\Processor\CommandProcessorInterface`
  - Removed `Predis\Command\Processor\CommandProcessorChainInterface`
2013-12-17 10:57:43 +01:00
Daniele Alessandri 1125dc1bdd Apply minor change in command serialization. 2013-12-16 18:46:17 +01:00
Daniele Alessandri feb69fb5f2 Update README.
[ci skip]
2013-12-16 17:05:49 +01:00
Daniele Alessandri 1d31a47cf4 Apply some tweaks to FAQ.
[ci skip]
2013-12-16 16:58:28 +01:00
Daniele Alessandri 35b2c99186 Update FAQ.
[ci skip]
2013-12-16 16:52:04 +01:00
Daniele Alessandri 0f34f41ccf Fix and reword some exception messages. 2013-12-16 15:13:18 +01:00
Daniele Alessandri 43f278fb71 Update testing README.
[ci skip]
2013-12-16 11:47:22 +01:00
Daniele Alessandri b7a7b6838b Merge branch 'v0.9/fix-bin-scripts' 2013-12-15 17:06:05 +01:00
Daniele Alessandri 714f9ddc64 [bin] Drop extension from scripts in the bin directory. 2013-12-15 17:05:30 +01:00
Daniele Alessandri d465de7b42 [bin] Handle duplicate class names or aliases in same namespace.
This condition can occur when merging multiple class files (with their
own independent "use" directives) in one big file: when imported class
names or aliases clashes, the script now tries to automatically rename
them by defining a new alias in the "use" directive and renaming the
occurences in the buffer containing the class code.

This fix is naive at best, but seems to work fine so we will just live
with it for now.
2013-12-15 17:05:07 +01:00
Daniele Alessandri 405ae4af65 [bin] Fix broken rendering of "use ... as ..." in output. 2013-12-15 17:04:55 +01:00
Daniele Alessandri 7e89719ceb Revert usage of "short" namespaces in use directives.
We started using partially-qualified names as an experiment but we are
reverting to using fully-qualified names + aliases in use directives.
2013-12-15 17:00:45 +01:00
Daniele Alessandri aa9aafe926 Remove CHANGELOG.NAMING.md.
Will be most likely replaced by UPGRADING.md or something like that.

[ci skip]
2013-12-15 14:04:52 +01:00
Daniele Alessandri 0779c1c24a Trim some more "use" directives in Predis\Client. 2013-12-15 14:01:05 +01:00
Daniele Alessandri e66c33a444 Merge branch 'v0.9/connection-namespace-1' 2013-12-15 13:44:04 +01:00
Daniele Alessandri 001a7c0827 Update CHANGELOG. 2013-12-15 13:42:47 +01:00
Daniele Alessandri 58c5029574 Rename Predis\Connection\AggregatedConnectionInterface. 2013-12-15 12:38:21 +01:00
Daniele Alessandri 6ceebbfbec Rename Predis\Connection\SingleConnectionInterface::pushInitCommand().
The new name is more explicit as it makes obvious that the commands
added with it will be executed upon connect().
2013-12-15 11:25:38 +01:00
Daniele Alessandri c40ad5dd47 Rename Predis\Connection\ConnectionParameters. 2013-12-15 10:22:23 +01:00
Daniele Alessandri 2a7607f128 Rename Predis\Connection\ConnectionFactory. 2013-12-15 10:09:08 +01:00
Daniele Alessandri 278f89924c Set the test suite to run against Redis 2.8 on Travis CI. 2013-12-14 20:44:10 +01:00
Daniele Alessandri cbf015164c Rename Predis\Client::raw() to Predis\Client::executeRaw().
This is more consistent with Predis\Client::executeRaw() and its more
explicit since simply "raw" as a method name was a bit too vague even
despite being nicely short.
2013-12-14 20:37:28 +01:00
Daniele Alessandri fded76bca3 Merge branch 'v0.9/connection-persistent-path' 2013-12-14 14:16:54 +01:00
Daniele Alessandri e7f2d28f23 Use path to differentiate persistent TCP streams.
Closes #139.
2013-12-14 14:15:41 +01:00
Daniele Alessandri 1c05c878f4 Update CHANGELOG. 2013-12-11 13:11:39 +01:00
Daniele Alessandri 5eb975ef69 Improve URI parsing for connection parameters.
Using PHP's "parse_str()" to parse the query string is slightly more
efficient then our own code especially when the number of fields in
the query string grows, with the additional benefit of supporting
arrays for values when brackets are present in fieldnames.

So after this commit, providing this URI string:

  $string = 'tcp://127.0.0.1?metavars[]=foo&metavars[]=hoge';

Is equivalent to providing the following named array:

  $array = [
    'scheme' => 'tcp',
    'host' => '127.0.0.1',
    'metavars' => ['foo', 'hoge'],
  ];

Aside from this improvement, the URI parsing behavior has not changed.
2013-12-11 12:45:47 +01:00
Daniele Alessandri 3fbc012c03 Add "path" in phpdoc of connections supporting UNIX domain sockets. 2013-12-11 12:20:10 +01:00
Daniele Alessandri cebdf889a4 Rename connection to Predis\Connection\PhpiredisSocketConnection. 2013-12-10 22:14:34 +01:00
Daniele Alessandri 863718bd2b Apply another minor fix to README. 2013-12-10 22:11:40 +01:00
Daniele Alessandri b01ac201d6 Fix README.
[ci skip]
2013-12-10 22:00:53 +01:00
Daniele Alessandri d5bd28958a Minor code styling adjustments. 2013-12-10 21:58:53 +01:00
Daniele Alessandri 95b9f63cab Rename write and read methods of the composable connection interface. 2013-12-10 21:26:11 +01:00
Daniele Alessandri 59b5658cf5 Big batch of phpdoc improvements and minor code styling fixes. 2013-12-10 19:21:52 +01:00
Daniele Alessandri 8744285cb3 Ignoring the plural form of "reply" for renames is dumb...
[ci skip]
2013-12-10 18:08:14 +01:00
Daniele Alessandri 14fda643f7 Replace remaining occurrences of "reply" with "response". 2013-12-10 15:54:41 +01:00
Daniele Alessandri 57e778e098 Tweak CONTRIBUTING.md.
[ci skip]
2013-12-09 12:22:25 +01:00
Daniele Alessandri f9fd4525b5 More minor tweaks in the README.
[ci skip]
2013-12-09 12:07:11 +01:00
Daniele Alessandri ac34983635 Pad headers lines in CHANGELOG.
[ci skip]
2013-12-09 11:46:14 +01:00
Daniele Alessandri 978e7ac551 Update CHANGELOG.
[ci skip]
2013-12-09 11:44:42 +01:00
Daniele Alessandri ca11c522d6 Miscellaneous fixes to README after rewrite.
... because spotting errors always happens after committing changes.

[ci skip]
2013-12-08 21:12:15 +01:00
Daniele Alessandri 6eed3d7647 Commit long overdue rewrite of the README.
[ci skip]
2013-12-08 20:54:12 +01:00
Daniele Alessandri 73cb6bbf2a [tests] Fix class name of connection parameters test case.
[ci skip]
2013-12-08 16:09:22 +01:00
Daniele Alessandri 5acdab9176 Merge branch 'v0.9/redis-cluster-fix'
Conflicts:
	lib/Predis/Connection/RedisCluster.php
2013-12-08 15:24:52 +01:00
Daniele Alessandri 35023dd83f Use a more appropriate exception. 2013-12-08 15:12:35 +01:00
Daniele Alessandri 70df7ca64d Apply common parameters to connections created on the fly in cluster.
These parameters are applied only to connections being created on the
fly when not part of the current pool. This condition usually happens
upon -MOVE or -ASK responses returned by Redis to redirect client to
different nodes.
2013-12-08 15:12:28 +01:00
Daniele Alessandri f0549b5dad Rewrite phpdoc comments for the redis-cluster connection backend. 2013-12-08 12:43:24 +01:00
Daniele Alessandri b7ac7595c2 Change signature of the connection parameters class constructor.
Only named arrays are explicitly accepted now, but the old behaviour
of creating a connection parameters instance out of an URI string or
a named array is still available using the "create()" static method.

  $array = ['host' => '127.0.0.1', 'timeout' => 1];
  $uri = 'tcp://127.0.0.1?timeout=1';

  $parameters = new ConnectionParameters($array);      // Arrays only
  $parameters = ConnectionParameters::create($array);  // Arrays OK
  $parameters = ConnectionParameters::create($uri);    // Strings OK

The purpose of the change is to have a more concise constructor with a
well defined signature.
2013-12-08 11:35:53 +01:00
Daniele Alessandri 1f66f4e8f7 Various fixes and improvements to redis-cluster connection backend.
List of changes:

  - The cluster connection can be initialized with a partial list of
    nodes, the full slots map will be fetched from Redis itself using
    the CLUSTER NODES command.
  - The slots map can be optionally retrieved from Redis if the server
    returns a -MOVE response, otherwise only the interested slot will
    be permanently reassigned to the new target node.
  - $cluster->connect() connects to a random connection in the pool
    instead of forcing the connect operation on all the connections.
2013-12-07 21:19:52 +01:00
Daniele Alessandri 73eb09378e Remove obsolete comments.
The phpiredis-based connection backends are not experiments anymore.

[ci skip]
2013-12-07 15:59:28 +01:00
Daniele Alessandri 427309db69 Apply code styling fixes.
There is actually no need for such indentations.
2013-12-07 15:41:45 +01:00
Daniele Alessandri ee45de4f0e Rename base response interface to Predis\Response\ResponseInterface. 2013-12-07 15:22:42 +01:00
Daniele Alessandri 6ece8c40a0 Merge branch 'v0.9/response-status' 2013-12-07 15:16:20 +01:00
Daniele Alessandri 373d30b070 Use Predis\Response\Status to identify all kinds of status responses.
Status response objects are needed mostly to make it possible from the
client perspective to differentiate a status response with the payload
"OK" from a normale bulk reply containing "OK".

The biggest change is for commands returning +OK responses: these were
previously translated to TRUE (bool value), but they are now returned
as instances of Predis\Response\Status. Just to illustrate an example
of the possibilities with this change we will use SET since it is the
most widely used command returning +OK:

  $response = $client->set('foo', 'bar');

  echo $response;         // 'OK'
  $response == 'OK';      // TRUE
  isset($response->ok);   // TRUE
  $response == true;      // TRUE
  $response === true;     // FALSE
  $response instanceof Predis\Response\ObjectInterface;     // TRUE
  $response instanceof Predis\Response\Status;              // TRUE

For those checking responses returned by commands such as SET or PONG,
the breaking change basically lies in the usage of strict comparison:
doing $response === true will now evaluate to FALSE instead of TRUE.

By default Predis caches common status responses such as OK or QUEUED
to lower the memory usage when using pipelines or transactions.
2013-12-07 15:15:23 +01:00
Daniele Alessandri ac8d0c1f42 Fix example.
[ci skip]
2013-12-02 16:12:43 +01:00
Daniele Alessandri cf70d2f20e Minor code styling changes in Predis\Connection. 2013-12-02 16:05:05 +01:00
Daniele Alessandri ccf8822b4b Minor change in stream connection destructor. 2013-12-02 15:45:29 +01:00
Daniele Alessandri d27d3b0acb Cache value casters in static member variable.
This optimization is mostly useful since connection parameters can be
instantiated more than one time in a script when using clustering or
replication.
2013-12-02 14:34:02 +01:00
Daniele Alessandri 5b7504b069 Simplify connection factory class by removing dependency on profile.
A profile is not needed to create instances of basic initialization
commands such as AUTH (authentication) and SELECT (database selection)
since they do not need prefixing and other stuff.

If needed, developers can still extend the base connection factory to
make it use a server profile and configure the client to use it using
options.
2013-12-02 13:01:37 +01:00
Daniele Alessandri 6ef8e99822 Make sure raw commands IDs are normalized to uppercase. 2013-12-02 11:42:06 +01:00
Daniele Alessandri 4bf0ee4c6a Rename ConnectionInterface::writeCommand() to writeRequest().
This name is more consistent with its counterpart, readResponse().
2013-12-02 11:08:14 +01:00
Daniele Alessandri 59b9319bb8 [tests] Minor tweak for timeouts. 2013-12-02 10:46:44 +01:00
Daniele Alessandri bcf92a7548 [tests] Fix tests under PHP 5.3 due to another dumb mistake.
Seriously, I am startint to hate PHP 5.3...
2013-12-01 15:27:42 +01:00
Daniele Alessandri d2c001812f [tests] Rename test case classes. 2013-12-01 15:11:09 +01:00
Daniele Alessandri 3ae3414a0d [tests] Normalize casing of command identifiers in constraint.
We do not care much about the casing of command IDs in our constraint,
so it makes no difference for use if it is "SET" or "set".
2013-12-01 14:00:57 +01:00
Daniele Alessandri a00ffbf53f Rework examples for plain Redis commands. 2013-12-01 13:42:10 +01:00
Daniele Alessandri 583b924085 Add the ability for the client to send raw commands to Redis.
When sending raw commands their arguments are not filtered, responses
are not parsed and key prefixes are not applied. The client also does
not throw any exception on Redis errors regardless of its settings.

The first parameter takes the raw arguments of the command (included
its identifier) as defined by the Redis documentation while the second
optional parameter is always populated by reference to indicate when
Redis actually returned an error response.

  $client->raw(['PING']);                // "PONG"
  $client->raw(['SET','foo','bar']);     // "OK"
  $client->raw(['GET','foo'], $err);     // "bar", $err=FALSE
  $client->raw(['LPUSH','foo',1], $err); // "WRONGTYPE...", $err=TRUE

Internally, this method creates instances of Predis\Command\RawCommand
that get passed to the underlying connection instance for execution as
if they were usual commands defined by Predis.

Raw commands work in both cluster and replication scenarios since they
are recognized by their command ID, but key prefixing is not supported
since it is done by the profile instance when instantiating commands.
2013-12-01 13:42:03 +01:00
Daniele Alessandri 3c77d3b0c1 Update examples. 2013-12-01 11:28:56 +01:00
Daniele Alessandri e049db124c By convention all of the Redis command identifiers are uppercase. 2013-12-01 10:45:37 +01:00
Daniele Alessandri b2e0dc62fe [tests] Fix dumb mistake when running tests with older profiles. 2013-11-30 20:06:37 +01:00
Daniele Alessandri f7ff65e0fa Merge branch 'v0.9/test-suite-improvements' 2013-11-30 19:39:12 +01:00
Daniele Alessandri b253bdc41e [tests] Improve the basic framework of our test suite.
We now have a base test case class for Predis (namely PredisTestCase)
grouping various commonly used utility methods shared by all of the
tests in the suite, greatly improving reusability.
2013-11-30 19:38:27 +01:00
Daniele Alessandri 5d7f297110 Send ASKING command when redis-cluster returns a -ASK response.
We must always execute ASKING on the connection identified by the -ASK
response before executing the actual command because not doing so will
break the cluster specifications while redis-cluster is performing a
resharding operation.
2013-11-30 17:37:37 +01:00
Daniele Alessandri 7f690cb62e [tests] Add a PHPUnit constraint to verify commands.
Commands are verified by checking their IDs and optionally arguments.
Passing a command instance is only a shortcut to set the expected ID
and arguments, commands are never compared for identity but always for
equivalence.
2013-11-30 17:14:42 +01:00
Daniele Alessandri cb3cd050ab Update CHANGELOG.
Remove recently added lines as they are not entirely true, the client
currently does not apply any key prefixing for any command not created
by Redis profiles even though it is possible now, contrary to v0.8.

[ci skip]
2013-11-30 15:12:36 +01:00
Daniele Alessandri c4e0d9df92 Update CHANGELOG.
[ci skip]
2013-11-30 14:55:12 +01:00
Daniele Alessandri 41ea336175 [tests] Update tests for Predis\Command\Command. 2013-11-30 14:45:51 +01:00
Daniele Alessandri 5d40b85f10 Update CHANGELOG. 2013-11-30 14:42:02 +01:00
Daniele Alessandri b7ac108d43 Merge branch 'v0.9/commands' 2013-11-30 14:35:45 +01:00
Daniele Alessandri cf581a3b49 Add new command class useful to execute "raw" Redis commands.
By raw we mean that input arguments are not filtered and responses are
not parsed, which means arguments must follow the command signature as
defined by Redis and complex responses are left untouched.

When instantiating an instance of `Predis\Command\RawCommand` you must
pass at least the command ID. You can pass further arguments in the
array or you can just set them later with `RawCommand::setArguments()`
but you cannot modify the command ID once instantiated.

  $command = new Predis\Command\RawCommand(['SET', 'foo', 'bar']);
  $response = $client->executeCommand($command);

While higher level abstractions built upon `Predis\Client` should just
use commands created by the profile in use, inner parts of the library
might use raw commands to provide certain functionalities making sure
that input and output of commands are always consistent, independent
of the profile.
2013-11-30 14:30:33 +01:00
Daniele Alessandri bb4b8c3c35 Fix phpdoc. 2013-11-30 13:08:31 +01:00
Daniele Alessandri 09895f27bf Rename command class for scripting to Predis\Command\ScriptCommand.
We also changed our wording to indentify this kind of abstraction so
instead of using "scripted commands" (kind of broken English) we now
use "scriptable commands".
2013-11-30 12:43:21 +01:00
Daniele Alessandri 980edf2f7b Rename base command class to Predis\Command\Command. 2013-11-30 12:24:43 +01:00
Daniele Alessandri c8e20e428a Remove interface defining objects aware of command processing.
It was too broad in concept and not really that useful, so for now we
assume that only our base Predis\Profile\RedisProfile class can handle
command processing and we will decide later if we want to add a couple
of more methods to Predis\Profile\ProfileInterface.
2013-11-30 10:27:51 +01:00
Daniele Alessandri 7a56856d46 Make option "prefix" accept command processor instances. 2013-11-30 10:00:30 +01:00
Daniele Alessandri fc4e279b9a [tests] Fix tests on PHP 5.3.
Stupid PHP 5.3.
2013-11-29 23:39:50 +01:00
Daniele Alessandri 09b0750cb7 [tests] Improve tests of TTL. 2013-11-29 23:27:59 +01:00
Daniele Alessandri d52daacba9 [tests] Improve base command test case. 2013-11-29 23:27:56 +01:00
Daniele Alessandri 00247abc50 [tests] Add missing tests for SETNX.
For some obscure reason Predis/Command/StringSetPreserve had no tests.
2013-11-29 22:50:09 +01:00
Daniele Alessandri 862da9a3b2 [tests] Add "count" argument to SRANDMEMBER (since Redis >= 2.6). 2013-11-29 22:45:35 +01:00
Daniele Alessandri d6173bb33b Merge branch 'v0.9/external-prefixer' 2013-11-29 22:40:46 +01:00
Daniele Alessandri d0b431016d Move key prefixing logic from command classes to prefix processor.
While command classes define how the client should filter arguments or
parse responses, key prefixing depends on the actual command signature
as defined by Redis so it really is something that should be handled
separately as the norm.

Developers can define new handlers or override existing ones, but they
can still define the key prefixing logic inside their command classes
by implementing Predis\Command\PrefixableCommandInterface: the key
prefix processor will just use that by overriding any defined handler.
2013-11-29 22:36:32 +01:00
Daniele Alessandri 5856bde198 Fix phpdoc.
[ci skip]
2013-11-29 11:14:56 +01:00
Daniele Alessandri 4840736503 Apply some minor internal changes to concrete connection classes. 2013-11-23 11:08:38 +01:00
Daniele Alessandri 2d39408c0f Add a method to the pipeline to fetch the connection from the client.
In this method we can put the logic needed to prepare the connection
right before sending the queued commands to the server (e.g. switching
to the master server when connected in replication mode).
2013-11-22 15:41:50 +01:00
Daniele Alessandri 374101cfc3 Apply minor change. 2013-11-22 12:17:57 +01:00
Daniele Alessandri cec7c24236 Merge branch 'v0.9/server-profile' 2013-11-22 12:15:08 +01:00
Daniele Alessandri 2a5483df90 Reorganize the Predis\Profile namespace.
The profile factory code has been extrapolated into a the new class
Predis\Profile\Factory (final and with only static methods).
2013-11-22 12:01:29 +01:00
Daniele Alessandri 0a60a156f0 Merge branch 'v0.9/transaction-multiexec-state' 2013-11-17 16:20:29 +01:00
Daniele Alessandri 1e0ef2a64d Move check for WATCH and UNWATCH support. 2013-11-17 16:17:24 +01:00
Daniele Alessandri 30e74e36aa Update CHANGELOG. 2013-11-17 16:05:12 +01:00
Daniele Alessandri 1125809de9 Force exceptions on error responses for transaction control commands.
Commands such as MULTI, EXEC, DISCARD, WATCH and UNWATCH disregard the
the "exceptions" client option and always result in an exception being
thrown on error responses even when the client is configured to return
those errors ("exceptions" set to FALSE).
2013-11-17 15:58:26 +01:00
Daniele Alessandri 712e6420e9 Rewrite parts of Predis\Transaction\MultiExec to make them less ugly.
We also changed some options for this class, the accepted ones are:

  - "keys": string or array of strings for automatic WATCH.
  - "cas": sets the check-and-set mode.
  - "retry": number of attempts before giving up aborted transactions.
  - "exceptions": sets whether exceptions should be thrown on error
    responses (overrides the "exceptions" client option).

The "on_retry" option has been removed.
2013-11-17 15:57:43 +01:00
Daniele Alessandri 84e0f5af7a Extract the tracking of transaction states to a separate class.
The Predis\Transaction\MultiExecState class is actually quite dummy as
it does not work as a finite-state machine, but is used to track state
using flags. It basically replicates the same behaviour of when it was
part of the Predis\Transaction\MultiExec code and it will do for now.
2013-11-17 13:15:36 +01:00
Daniele Alessandri c047c4992a Merge branch 'v0.9/pipeline-refactoring' 2013-11-17 11:07:24 +01:00
Daniele Alessandri ce706a375c Merge branch 'v0.9/add-commands' 2013-11-17 11:06:22 +01:00
Daniele Alessandri 66f22899a1 Update CHANGELOG. 2013-11-17 11:04:03 +01:00
Daniele Alessandri 620adb2fe6 New command: PUBSUB (Redis 2.8). 2013-11-17 11:02:37 +01:00
Daniele Alessandri 1b5e2d0d0d New command: SENTINEL (Redis 2.6). 2013-11-17 11:02:33 +01:00
Daniele Alessandri 3d499e82a3 Add some supported options to Predis\Client::pipeline().
Only two options available for now, used to specify which kind of
pipeline object the client should use or return:

  - "atomic": returns a pipeline wrapped in a MULTI / EXEC transaction
    (class: Predis\Pipeline\Atomic).
  - "fire-and-forget": returns a pipeline that does not read back
    responses from the server (class: Predis\Pipeline\FireAndForget).

We might add more options in the future.
2013-11-16 21:54:17 +01:00
Daniele Alessandri 8068c87e47 Rewrite a good chunk of the classes in the Predis\Pipeline namespace.
First of all we completely removed the concept of pipeline executors.
Now pipelines can be easily customized by extending our default class
Predis\Pipeline\Pipeline.

Tests coverage for the Predis\Pipeline namespace is decent but can be
definitely improved while test cases can be beautified.
2013-11-16 21:23:49 +01:00
Daniele Alessandri c6f51e82bf Rename "Array" type-hint to to "array". 2013-11-16 17:01:58 +01:00
Daniele Alessandri 944da8c9b8 Rename Predis\Cluster\Hash\CRC16HashGenerator. 2013-11-16 16:41:00 +01:00
Daniele Alessandri f01ef33735 Merge branch 'v0.9/rename-transaction-class' 2013-11-16 16:35:07 +01:00
Daniele Alessandri aaac082324 Rename classes in Predis\Transaction. 2013-11-16 16:34:34 +01:00
Daniele Alessandri aa210aeb03 Merge branch 'v0.9/rename-cluster-classes' 2013-11-16 16:22:37 +01:00
Daniele Alessandri e6f1788e27 Rename interfaces and classes in the Predis\Cluster namespace.
A few methods were renamed accordingly for consistency
2013-11-16 16:21:27 +01:00
Daniele Alessandri c26b6763f9 Merge branch 'v0.9/rename-monitorcontext' 2013-11-16 15:43:16 +01:00
Daniele Alessandri 9d2cb975eb Rename classes in Predis\Monitor namespace. 2013-11-16 15:42:56 +01:00
Daniele Alessandri 2e6a76d83e Fix phpdocs. 2013-11-16 15:33:39 +01:00
Daniele Alessandri 046715a455 Merge branch 'v0.9/rename-pubsubcontext' 2013-11-16 15:28:54 +01:00
Daniele Alessandri c3a58dffdf Rename classes in the Predis\PubSub namespace. 2013-11-16 15:27:58 +01:00
Daniele Alessandri 7d60e995f8 Rename session handler class. 2013-11-16 15:03:05 +01:00
Daniele Alessandri f18d7103f5 [tests] Remove useless backslash in "use" directive. 2013-11-16 14:57:00 +01:00
Daniele Alessandri e42c72c043 Merge branch 'v0.9/rename-response-classes' 2013-11-16 14:04:25 +01:00
Daniele Alessandri 621c3d7fd3 Update CHANGELOG. 2013-11-16 14:03:17 +01:00
Daniele Alessandri b71c798f9b Rename classes in Predis\Response and Predis\Response\Iterator.
This change aims to make class names shorter with less redundant fully
qualified names.

Merge!
2013-11-16 14:01:11 +01:00
Daniele Alessandri 1022be6010 [tests] Fix tests. 2013-11-16 12:54:09 +01:00
Daniele Alessandri e41db42b01 Merge branch 'v0.9/response-namespace' 2013-11-16 12:50:45 +01:00
Daniele Alessandri ecd4c6281c Update CHANGELOG. 2013-11-16 12:48:37 +01:00
Daniele Alessandri 35ce43d526 Update CHANGELOG. 2013-11-16 12:44:56 +01:00
Daniele Alessandri 7f9d06bb83 Move the Predis\Iterator namespace into Predis\Response. 2013-11-16 12:07:35 +01:00
Daniele Alessandri a8edc02eb6 Create the Predis\Response namespace.
All of the response interface, classes and exceptions have been moved
into this namespace.
2013-11-16 11:59:33 +01:00
Daniele Alessandri 205ffbbd73 Update composer.json. 2013-11-16 11:27:47 +01:00
Daniele Alessandri b0f955b437 Fix phpdocs.
[ci skip]
2013-11-12 19:49:55 +01:00
Daniele Alessandri 8d15e5ec08 Do not pipeline initialization commands. 2013-11-12 18:16:54 +01:00
Daniele Alessandri 6fbc421b96 Fix URI parsing on multiple equal signs in pair value of query string. 2013-11-12 12:46:45 +01:00
Daniele Alessandri 298e7a14fa [tests] Add @medium since this could take a little bit more than 1sec. 2013-11-12 12:34:51 +01:00
Daniele Alessandri 22c2230d00 [tests] Rename just a couple of test methods. 2013-11-12 12:31:49 +01:00
Daniele Alessandri a1c7889584 Add option "aggregate" to customize multiple connections aggregation.
This option must return a callable object that is used to override how
the client aggregates connections when passing an array of parameters
to its constructor.

When specified, this option overrides both "cluster" and "replication"
as it allows to make use of your own code to aggregate multiple nodes.

This is, for example, how you can mimic the standard initialization of
a cluster that relies on client-side sharding:

  $parameters = ['tcp://127.0.0.1:6380', 'tcp://127.0.0.1:6381'];

  $options = [
    'aggregate' => function () {
      return function ($parameters, $options) {
          $connection = new Predis\Connection\PredisCluster();
          $options->connections->aggregate($connection, $parameters);

          return $connection;
      };
    },
  ];

  $client = new Predis\Client($parameters, $options);

When invoked by the client, the specified callable must always return
a Predis\Connection\ConnectionInterface instance or the client will
throw an UnexpectedValueException.
2013-11-12 12:31:45 +01:00
Daniele Alessandri 5e90e615b1 Minor optimizations for the parsing of URI parameters.
Using list() with the warning suppressor is slower than using isset()
to check the presence of the first two elements of the array returned
by explode(). This also allow us to skip incomplete query string pairs
when parsing the URI string.

We have also changed the exception being thrown on invalid URIs to a
more appropriate one.
2013-11-11 18:59:21 +01:00
Daniele Alessandri 321d2624ab Rename URI parsing method of Predis\Connection\ConnectionParameters. 2013-11-11 18:30:42 +01:00
Daniele Alessandri acd29ec076 Slightly change interface for connection factories. 2013-11-11 18:24:20 +01:00
Daniele Alessandri 3c6389f4dd Rework how connection parameters are handled.
These changes do not affect the actual functionalities of the client,
but make the code more explicit and less error-prone.
2013-11-11 18:17:09 +01:00
Daniele Alessandri 1d53f8a988 Minor code styling changes. 2013-11-11 15:59:21 +01:00
Daniele Alessandri dd679661dd Address #133 by reusing our own methods.
The main reason behind that code duplication was performance related
as we tried to reduce method calls when possible, even at the cost of
falling into the realm of early optimizations. Apparently we just lose
~400 req/sec on a 21000 req/sec basis ("SET foo bar") using PHP 5.5.3
(packaged by Ubuntu 13.10) on an Intel Q6600, so we will most likely
stick with this change for the sake of best practices.
2013-11-11 15:49:16 +01:00
Daniele Alessandri f36138c0b7 Minor internal change.
Check directly the private parameters array instead of passing through
method dispatching for the outer __isset() method.
2013-11-11 15:28:42 +01:00
Daniele Alessandri 31e08f0d5d Tweak phpdocs. 2013-11-11 12:29:43 +01:00
Daniele Alessandri cdb91284f1 Clean up ugly code bits. 2013-11-10 12:30:24 +01:00
Daniele Alessandri 38c7697881 Remove useless method. 2013-11-10 12:27:15 +01:00
Daniele Alessandri b45ba55f46 Switch to protected visibility for some members of Predis\Client.
The "profile" member is actually used for caching purposes as fetching
its value from the options instance would add noticeable overhead in a
part of the client where every bit of optimization matters, for this
we decided to keep it private.
2013-11-10 12:20:20 +01:00
Daniele Alessandri b50b90aa66 Rename method. 2013-11-10 12:17:58 +01:00
Daniele Alessandri 0128ecc623 Fix strict notice for undefined property during tests. 2013-11-09 20:37:30 +01:00
Daniele Alessandri bf991a24f3 Merge branch 'v0.9/protocol-processor-api' into integration 2013-11-09 20:02:21 +01:00
Daniele Alessandri bab0cd999c Rename Predis\Client::multiExec() to Predis\Client::transaction().
Method was deprecated since Predis v0.8.5.
2013-11-09 19:56:01 +01:00
Daniele Alessandri 30d81c942a Update CHANGELOG. 2013-11-09 19:32:38 +01:00
Daniele Alessandri f066356858 Slightly change the internal context factory method of Predis\Client. 2013-11-09 19:16:09 +01:00
Daniele Alessandri 7649533141 Remove some obsoleted or useless methods from Predis\Client. 2013-11-09 19:07:24 +01:00
Daniele Alessandri a4d0abc734 Minor tweaks to code.
Also removed a useless method, most likely a leftover from the past.
2013-11-09 19:02:01 +01:00
Daniele Alessandri b38f640ac9 Minor tweaks to phpdoc descriptions. 2013-11-09 18:57:35 +01:00
Daniele Alessandri d431ea6dba Change visibility of some members.
There's no actual need for these ones to be private.
2013-11-09 18:47:30 +01:00
Daniele Alessandri 715b1badcb Remove useless class constants. 2013-11-09 18:46:05 +01:00
Daniele Alessandri d79aadc38f Update CHANGELOG. 2013-11-09 18:44:22 +01:00
Daniele Alessandri 9136033eea Rationalize API renaming or moving stuff in Predis\Protocol namespace. 2013-11-09 18:36:28 +01:00
Daniele Alessandri 16d17af577 Rework the API for external protocol processors. 2013-11-09 17:10:07 +01:00
Daniele Alessandri 1a7b604c1b Tweak phpdocs and API of streamable multibulk iterators.
Despite not being a globally supported feature of Predis anymore, they
are still optionally supported by our default text protocol processors
and they can be used to build custom stuff for specific needs.
2013-11-09 15:49:11 +01:00
Daniele Alessandri 70a84e1d5a Merge branch 'v0.9/drop-multibulk-iterators' 2013-11-09 12:23:31 +01:00
Daniele Alessandri fb2d8a37c1 Drop support for streamable multibulk responses.
Supporting this feature has been problematic and leaded to some ugly
code to make abstractions such as pipelines and transactions aware of
these kind of response objects. Furthermore, it was not possible to
add them to all the connection classes due to implementation limits.

For such reasons Predis do not support them globally anymore, but the
actual classes are still shipped within the library so that they can
be used to build custom stuff at a level lower than client (that is,
unless we decide to remove them for good before going stable).
2013-11-09 12:07:36 +01:00
Daniele Alessandri 7c5aba08cd Make "2.8" the default Redis server profile. 2013-11-08 16:04:07 +01:00
Daniele Alessandri 1a769e3cc3 Fix different behaviour of filter_var() with NULL on PHP 5.3.
Seriously, they could not possibly screw bool validation up any more
than they already had with filter_var().
2013-11-08 15:31:14 +01:00
Daniele Alessandri 9a72b98c4a Remove previously deprecated Predis\Helpers class. 2013-11-08 12:13:37 +01:00
Daniele Alessandri 089b972def Merge branch 'v0.9/client-options' 2013-11-08 12:08:26 +01:00
Daniele Alessandri b1ebc8df2f Reimplement from scratch client configuration.
This commit is a complete rewrite of the classes previously contained
in the Predis\Option namespace aimed at lowering the initialization
overhead while bringing in more consistency. The overall idea is still
the same with a mini DI container, Predis\Configuration\Options, which
carries options with values that can be initialized lazily.

The first difference with our previous implementation is that now even
user-defined options can be initialized lazily, everything needed is
an object responding to the __invoke() magic method such as a closure.
Other kind of callable arguments (strings, arrays) will be treated as
plain values. The only drawback is that we cannot pass any instance of
classes implementing __invoke() as an option value, but considered the
limited scope of our use case we can say it's more of an acceptable
compromise. Callbacks used for lazy initialization will receive two
arguments upon invokation:

  - The current instance of Predis\Configuration\Option ($options)
  - A string containing the name of the option ($option)

This is an example in actual code:

  $options = new Predis\Configuration\Options([
    'exceptions' => true,
    'profile' => '2.8',
    'distributor' => function () {
      return new Predis\Cluster\Distribution\KetamaPureRing();
    },
    'cluster' => function ($options) {
      $distr    = $options->distributor;
      $strategy = new Predis\Cluster\PredisClusterHashStrategy($distr);
      $cluster  = new Predis\Connection\PredisCluster();

      return $cluster;
    },
    'connections' => function ($options, $option) {
      $factory = $options->getDefault($option);
      $factory->define('tcp', 'Predis\Connection\PhpiredisConnection');

      return $factory;
    },
  ]);

As you can see there's very little difference compared to before in
the actual usage as most changes are under the hood. Some options such
as "exceptions" and "replication" can now correctly parse bool values
from strings (so the string "false" is not evaluated as boolean true).

While options were initially conceived to configure the client and its
behavior, the concept has matured and it's perfectly fine to consider
the use of Predis\Configuration\Options to propagate configurations to
inner parts of the library.
2013-11-08 12:08:11 +01:00
Daniele Alessandri 153758019c Diverging from the v0.8 branch (current stable).
This commit marks the start of works for the next major release of
Predis which will bring various breaking changes needed to polish the
internal design making the library even more flexible to use or extend
and, more importantly, almost stable in terms of API.

The Redis commands API exposed by Predis\Client is not going to change
much if not at all which is a good news. The most immediate changes
affecting developers will involve the renaming of a few namespaces and
classes, the removal of some previously deprecated classes and methods
and some tweaks to the current abstractions.

Right now the plan is to have a fast paced development to release this
version as soon as possible, ideally a few weeks later than Redis 2.8,
then wait to see the final definition of redis-cluster so that we can
tweak our code if needed and finally hit the v1.0.0 milestone with as
few changes as possible. Furthermore, v1.x will most likely be the
last version of Predis supporting PHP 5.3 as we will start migrating
to PHP 5.4 (or even 5.5) with v2.x, which is not going to happen soon
anyway.
2013-11-08 11:17:50 +01:00
Daniele Alessandri 62f8730f1a Merge branch 'feature/list-iterator' into v0.8 2013-11-07 18:48:53 +01:00
Daniele Alessandri 9b8b362747 Implement PHP iterator for lists based on the LRANGE command.
This iterator tries to mimic the same behaviour of the cursor-based
iterators implemented upon the SCAN family of commands and offering
only limited guarantees on the returned elements, but uses LRANGE to
fetch items from a list incrementally.
2013-11-07 18:47:58 +01:00
Daniele Alessandri ee9e09aa07 Rename protected member. 2013-11-07 14:45:09 +01:00
Daniele Alessandri 66f98186f0 [tests] Do not check exception message for connection timeouts.
Given the IP address we use for this test (the standard IP assigned by
operating systems when unable to get one lease from a DHCP server), on
certain kernels or network stacks we can get different messages such
as "No route to host". Since we just need to make sure that our test
does not take more than 1 seconds abiding by the sub-second timeout,
we can just live with that.
2013-11-07 12:19:23 +01:00
Daniele Alessandri 463f2d655c Merge branch 'feature/scan-iterators' into v0.8 2013-11-07 12:10:43 +01:00
Daniele Alessandri b2db97d983 Tweak phpdocs for the abstract cursor-based iterator. 2013-11-07 12:10:04 +01:00
Daniele Alessandri 9da1648145 Mostly useless tweak for iterators example. 2013-11-07 12:10:04 +01:00
Daniele Alessandri 5ad00774e1 Rename for the last time all the iterator classes.
We are experimenting with a new approach at naming classes using less
redundant names by leveraging the containing namespace. The PHP "use"
directive is not limited to class names but can be used to import the
whole namespace, which means you can do something like this:

  use Predis\Collection\Iterator;
  // ...
  foreach (new Iterator\Keyspace($client) as $key) {
  	// ...
  }

Alternatively you can always rely on "use ... as ..." to import one of
the classes by giving it a more meaningful name in the context of the
root namespace:

  use Predis\Collection\Iterator\Keyspace as KeyspaceIterator;
  // ...
  foreach (new KeyspaceIterator($client) as $key) {
  	// ...
  }

In this specific case we chose to apply the -Key postfix to classes
iterating Redis keys to be more explicit about the fact that those
iterators does not work on local in-memory collections, but fetch
items from a key stored on a remote Redis server.
2013-11-07 12:09:59 +01:00
Daniele Alessandri ff004aeaaa Reenable skipped tests since bug in Redis has been fixed.
See commit antirez/redis@54a5a7dff8
2013-11-06 16:40:36 +01:00
Daniele Alessandri df2c9eb7ff Move Redis collections iterators in a different namespace.
The base iterator class is now known as RedisCollectionIterator and
we've also renamed a few methods to make their naming more generic.
2013-11-06 16:19:12 +01:00
Daniele Alessandri 4d8348158f [tests] Add more tests for SCAN-based iterators. 2013-11-04 18:01:29 +01:00
Daniele Alessandri 0ab0aa14fb [tests] Fix execution order of iterator methods.
We were testing iterators following a broken assumption about the
order in which the Zend engine executes the various methods during
the iteration.
2013-11-04 17:39:27 +01:00
Daniele Alessandri 85c978fdad Fix SCAN-based iterators following failing tests. 2013-11-04 16:53:56 +01:00
Daniele Alessandri b7f411a252 [ŧests] Add tests for new SCAN, SSCAN, ZSCAN and HSCAN iterators.
Right now we don't have integration tests since the returned values from
Redis may not always be predictable, but the current tests should suffice.
2013-11-04 16:53:24 +01:00
Daniele Alessandri 9866500ad6 Add example of iterators based on the various SCAN commands. 2013-11-03 15:05:05 +01:00
Daniele Alessandri 73ee5aabad Update CHANGELOG and README. 2013-11-03 14:21:31 +01:00
Daniele Alessandri e88938cdfd Implement PHP iterator based on the HSCAN command (Redis 2.8).
This iterator allows to perform full iterations over fields and values of a
hash by wrapping the incremental nature of HSCAN just like we did for SCAN:

  $client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
  $iterator = new Predis\Iterator\Scan\HashIterator($client, "hash_key");

  foreach ($iterator as $field => $value) {
      echo "$field => $value" . PHP_EOL;
  }

Being HSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.
2013-11-03 14:19:12 +01:00
Daniele Alessandri 93ae376618 Implement PHP iterator based on the ZSCAN command (Redis 2.8).
This iterator allows to perform full iterations over the members of a sorted
set by wrapping the incremental nature of ZSCAN just like we did for SCAN:

  $client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
  $iterator = new Predis\Iterator\Scan\SortedSetIterator($client, "zset_key");

  foreach ($iterator as $member => $rank) {
      echo "$rank => $member" . PHP_EOL;
  }

Being ZSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.

This iterator implementation returns the member as key and the rank as value
since the rank is a float value which would be truncated when transforming
the iteration to an array (e.g. using iterator_to_array()). Luckily PHP
preserves the insertion order for named arrays members still result sorted.
2013-11-03 14:19:07 +01:00
Daniele Alessandri 7028082b7f Implement PHP iterator based on the SSCAN command (Redis 2.8).
This iterator allows to perform full iterations over the members of a set
by wrapping the incremental nature of SSCAN just like we did for SCAN:

  $client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
  $iterator = new Predis\Iterator\Scan\SetIterator($client, "set_key");

  foreach ($iterator as $member) {
      echo $member . PHP_EOL;
  }

Being SSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.

Meh
2013-11-03 14:19:06 +01:00
Daniele Alessandri d09d8edc7d Extract base class for iterators based on the SCAN family of commands.
The iterators based on SCAN, SSCAN, ZSCAN and HSCAN will extend this abstract
class to share most of the logic which is common for all of the Redis commands
in the SCAN family.
2013-11-03 14:19:02 +01:00
Daniele Alessandri 70e42f8fca Implement PHP iterator based on the SCAN command (Redis 2.8).
This iterator allows to perform full iterations over the keyspace of a Redis
instance by wrapping the incremental nature of SCAN using an abstraction that
fits perfectly in userland code:

  $client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
  $iterator = new Predis\Iterator\Scan\KeyspaceIterator($client);

  foreach ($iterator as $key) {
      echo $key . PHP_EOL;
  }

Memory consumption during an iteration is limited because elements are fetched
incrementally, on the other hand SCAN gives limited guarantees about returned
elements since the underlying collection (the keyspace in this case) can change
during the whole iteration process. The most immediate drawback is that the same
element may be returned multiple times.

See http://redis.io/commands/scan to fully understand the inner workings,
and particularly the "Scan guarantees" paragraph.
2013-11-03 14:06:50 +01:00
Daniele Alessandri 695b6dd7b3 Update README. 2013-11-02 18:52:43 +01:00
Daniele Alessandri 6ce09a2a8b [tests] Handle failing test on OS X. 2013-11-02 18:50:24 +01:00
Daniele Alessandri bb03602326 Update CHANGELOG. 2013-11-02 18:19:32 +01:00
Daniele Alessandri 5c9adbacd7 [tests] Minor tweaks, no actual changes. 2013-11-02 18:19:32 +01:00
Daniele Alessandri 8533dbdb0b Deprecate Client::pubSub() in favor of Client::pubSubLoop().
Client::pubSub() still works like usual by returning a new pub/sub
context, but it is now considered an alias of Client::pubSubLoop().

This change is necessary in preparation for the next major version
of Predis where Client::pubSub() will be used for the new PUBSUB
command introduced in Redis 2.8.
2013-11-02 18:19:32 +01:00
Daniele Alessandri d78e1b6ab7 New command: HSCAN (Redis 2.8).
One test is currently marked as skipped because it makes
Redis crash when the specified MATCH pattern returns one
or more elements.

See http://redis.io/commands/scan for reference.
2013-11-02 18:19:32 +01:00
Daniele Alessandri d5aec78086 New command: ZSCAN (Redis 2.8).
One test is currently marked as skipped because it makes
Redis crash when the specified MATCH pattern returns one
or more elements.

See http://redis.io/commands/scan for reference.
2013-11-02 18:19:32 +01:00
Daniele Alessandri 0faae20737 New command: SSCAN (Redis 2.8).
See http://redis.io/commands/scan for reference.
2013-11-02 18:19:32 +01:00
Daniele Alessandri 4eb4960b63 New command: SCAN (Redis 2.8).
See http://redis.io/commands/scan for reference.
2013-11-02 18:19:32 +01:00
Daniele Alessandri 75c64b7f2f Add link to CONFIG REWRITE (Redis 2.8) in phpdoc for CONFIG command. 2013-11-02 18:19:32 +01:00
Daniele Alessandri d78780382a Promote Redis 2.8 to a standalone server profile.
We still need to populate this new server profile with the
recently added new commands for Redis 2.8.

The next development version has been set to Redis 3.0.
2013-11-02 18:19:32 +01:00
Daniele Alessandri 98aacd8d9a Back to development for the next patch release. 2013-11-02 18:19:31 +01:00
toretto 4824af1563 Added "Latest Stable Version" and "Total Downloads" Badges 2013-08-31 10:51:10 +02:00
Daniele Alessandri cb18d67b6a Update CHANGELOG and bump VERSION. 2013-07-27 11:13:54 +02:00
Daniele Alessandri 4576dc029f Add LICENSE and phpunit.xml.dist in package.ini for Pear.
This commit addresses issues #124 and #126. LICENSE will be installed
with the "doc" role while phpunit.xml.dist will be installed with the
"test" role.

[ci skip]
2013-06-17 11:16:07 +02:00
Daniele Alessandri aa458a1922 Merge pull request #123 from drealecs/doctype_fixes
some PHPDoc fixes in lib
2013-06-03 03:04:10 -07:00
Alexandru Patranescu 2d2930d24f some PHPDoc fixes in lib
and removed some unused imports also
2013-06-03 00:06:41 +03:00
Daniele Alessandri 7e0ec1a265 Update CHANGELOG.
[ci skip]
2013-05-31 11:52:47 +02:00
Daniele Alessandri 04e597ebba Merge remote-tracking branch 'origin/pr/116' into v0.8 2013-05-31 11:30:30 +02:00
Daniele Alessandri d681bff4ab Merge branch 'github/pr/114' into v0.8 2013-05-31 10:47:58 +02:00
Daniele Alessandri 3dea41aa66 Add tests for prefixed Predis\PubSub\DispatcherLoop. 2013-05-31 10:39:46 +02:00
Daniele Alessandri 69c66e157f Make callbacks properties protected in the DispatcherLoop class.
This makes easier to extend the class. The underlying pub/sub iterator
property is still private, but can be accessed via public getter method.
2013-05-31 10:21:21 +02:00
Daniele Alessandri dd50cfe47e Slightly rework original pull request. 2013-05-31 10:17:54 +02:00
Daniele Alessandri 8451146d38 Expose underlying client object from pub/sub iterators. 2013-05-31 10:17:08 +02:00
Thomas Orozco d45ce35923 Use a random IP when a host has several IPs.
Using gethostbyname, we will reuse the same (first) IP address for
each request. Here, we choose the IP we use randomly.

This is practical in a case where we have multiple redis read-only
slaves that can't invidually support the full application load, but are
accessible through a single hostname.
2013-05-11 14:08:51 -07:00
Eloi Poch 6cd124cc59 Fix DispatcherLoop error with client prefix keys
DispatcherLoop works properly if a client have configured a
prefix for the keys or not
2013-04-20 13:02:17 +02:00
Daniele Alessandri d6fa4a3292 Augment exception message with basic server details on connection error.
Providing a basic hint in the exception message about the server that caused
a connection exception could be useful especially with aggregated connections.

This is in response to issue #110.
2013-03-30 16:16:13 +01:00
Daniele Alessandri 5b771704d3 Handle DUMP and RESTORE with Predis\Connection\PredisCluster. 2013-03-30 14:38:49 +01:00
Daniele Alessandri 68d972a1b1 Merge remote-tracking branch 'origin/pr/111' into v0.8 2013-03-27 15:11:00 +01:00
marcosQuesada 4bf035918d setting medium timeout on slow tests 2013-03-23 00:57:36 +01:00
Daniele Alessandri 94c4e2ffee Fix handling of scripted commands with redis-cluster hash strategy.
A missing "use" directive was preventing the hash strategy to properly
use the specific methods of Predis\Command\ScriptedCommand, falling back
to analyzing the raw arguments array of the command.
2013-03-16 16:24:59 +01:00
Daniele Alessandri 6e2fd181f1 Make sure key prefixing is skipped when command has no arguments.
Actually this was already the case for certain commands, but some of them
was left unguarded for such cases. This commit also fixes #109.

The behaviour of silently skipping key prefixing when a command has no
arguments may change in the future so we added explicit tests as guards
for future changes. Predis\Command\Processor\KeyPrefixProcessor will
continue to skip key prefixing on empty arguments, regardless.
2013-03-16 16:00:33 +01:00
Daniele Alessandri 1c21fcc5b3 Fix strict warnings running command test generator script. 2013-03-16 13:23:46 +01:00
Daniele Alessandri 531261b0fc Add DUMP and RESTORE to the server profile for Redis 2.6.
Closes issue #108.
2013-03-16 13:21:24 +01:00
Daniele Alessandri 7434a9bd0e Add the WITHSCORES modifier only when option value is true.
Fixes issue #107.
2013-03-16 12:37:00 +01:00
Daniele Alessandri c4123ce7ce Update CHANGELOG. 2013-03-16 12:16:52 +01:00
Daniele Alessandri 536992e277 Merge remote-tracking branch 'nitper/cluster_hmset' into v0.8 2013-03-16 12:11:44 +01:00
Daniele Alessandri 5a735aa670 Back to development for the next patch release. 2013-03-16 12:11:37 +01:00
nitper 15f2776d77 update cluster tests 2013-03-11 23:08:10 +00:00
nitper dc1103582e allow HMSET in clusters 2013-03-11 22:50:03 +00:00
Daniele Alessandri 8c0498a893 Bump VERSION and update CHANGELOG. 2013-02-18 15:03:45 +01:00
Daniele Alessandri aba24d0f6f Remove a few more unnecessary strict comparisons. 2013-02-17 20:46:31 +01:00
Daniele Alessandri a1df4f20da Expose private method used to parse URI strings.
This is useful for 3rd party libraries such as PredisServiceProvider
so it makes sense to have it public and static.
2013-02-17 20:38:46 +01:00
Daniele Alessandri 116eaba75e Deprecate the whole Predis\Helpers class. 2013-02-17 15:21:01 +01:00
Daniele Alessandri de4bae3f9b Prevent E_NOTICE messages on __destruct() if $parameters is not set.
This can only happen when throwing on invalid connection parameters,
this is a quick fix that will do for now.
2013-02-17 15:21:01 +01:00
Daniele Alessandri b50a5975ac Use a nicer looking version for the same code. 2013-02-17 15:21:01 +01:00
Daniele Alessandri 1c1b4096f6 Remove a few more unnecessary strict comparisons. 2013-02-17 15:20:57 +01:00
Daniele Alessandri f8e4ba152f Use hexadecimal notation. 2013-02-17 12:27:45 +01:00
Daniele Alessandri 6b6b73f5f4 Add getArgument($index) in Predis\Command\CommandInterface.
This method should have been part of the interface since start since
it is used through the library. We also do not specify a default value
for the index argument since it does not make much sense.
2013-02-17 12:22:00 +01:00
Daniele Alessandri 729e40d6c0 Use 0 to indicate no arguments for KEYS[] in Lua scripted commands.
We previously used FALSE for that but in the end it does not make much
sense. Luckily for us this does not represent a breaking change since
existing code will keep to work, so we can safely push this change into
the next patch release.
2013-02-16 17:40:49 +01:00
Daniele Alessandri fbcfdc343e Do not implicitly set multibulk replies on composable connections.
This should be done externally on the underlying protocol instance.
2013-02-16 17:05:38 +01:00
Daniele Alessandri 8cbcb09c4c Remove a few unnecessary strict comparisons. 2013-02-16 17:05:12 +01:00
Daniele Alessandri 2781bd780f Fetch connection factory directly from client options. 2013-02-16 14:36:04 +01:00
Daniele Alessandri 9675626aac Add "tcp_nodelay" in the list of supported connection parameters.
[ci skip]
2013-02-16 12:14:05 +01:00
Daniele Alessandri f8829985f7 Tweak CHANGELOG.
[ci skip]
2013-02-16 11:59:43 +01:00
Daniele Alessandri e2e809c9d4 Fix test to handle different hashes generated on 64bits builds of PHP.
Just noticed it on Travis CI as they recently switched to 64bits PHP builds,
also great to see that the library seems to work fine anyway.
2013-02-16 11:46:42 +01:00
Daniele Alessandri ef0067e1a4 Use slightly faster version of the same code.
Yet again, micro-optimizations here.
2013-02-16 11:32:29 +01:00
Daniele Alessandri da343046e5 No need for strict comparison here.
Should be also slightly faster (at least on a micro-optimization scale).
2013-02-16 11:14:55 +01:00
Daniele Alessandri 76d6681f68 Fix unserialization of Predis/Connection/PhpiredisStreamConnection. 2013-02-16 11:14:55 +01:00
Daniele Alessandri 8d01be388d Support TCP_NODELAY for stream-based connections on PHP >= 5.4.0.
This cannot be implemented for previous versions of PHP because we
need socket_import_stream() to extract the underlying socket resource
from the stream in order to be able to set the TCP_NODELAY flag.
2013-02-16 11:14:50 +01:00
Daniele Alessandri c38376dcc4 Accepts callable as first argument of Predis\Client::__construct().
Users can then use callables to wrap the creation and initialization
of the underlying connection with custom strategies:
2013-02-15 11:36:19 +01:00
Daniele Alessandri c354d02105 Aggregated connection for redis-cluster now uses 16384 hash slots.
This commit reflects the recent change from the redis unstable branch
in which the number of hash slots was increased from 4096 to 16384.

See https://github.com/antirez/redis/commit/ebd666d for reference.
2013-02-14 21:54:23 +01:00
Daniele Alessandri d6685a424a Update FAQ. 2013-02-09 10:11:16 +01:00
Daniele Alessandri 05ef62ff97 Tweak README. 2013-02-09 10:06:30 +01:00
Daniele Alessandri b76e876b73 No need for "iterable_multibulk" as a default connection parameter.
Furthermore, connections that do not support certain parameters should
check and throw whether they are set, independently from their value.
2013-02-09 09:56:07 +01:00
Daniele Alessandri ebd895a67d Update link to phpiredis. 2013-02-09 09:49:57 +01:00
Daniele Alessandri 923e7ed5fd Add Predis\Connection\PhpiredisStreamConnection.
This class works just like Predis\Connection\PhpiredisConnection but
it does not require the socket extensions since it relies on PHP's
native streams thus allowing the use of persistent connections.
2013-02-09 09:46:48 +01:00
Daniele Alessandri 9e0fe7bdc7 Back to development for the next patch release.
Forgot to do that prior to merge, my bad.

[ci skip]
2013-02-08 14:54:53 +01:00
Daniele Alessandri 5d774dc581 Merge branch 'gh/pr/102' into v0.8 2013-02-08 12:37:43 +01:00
Daniele Alessandri dffbb8b042 [tests] Fix version check to work on Redis < 2.6.0.
INFO does not have the concept of sections prior to 2.6.0 while our
test suite can be run against 2.4.0 (provided that phpunit.xml uses
the correct server profile), so we need to make sure that the check
does not break with prior version of Redis even if this is unlikely
to happen at this point.

Also changed a bit the naming of variables since things are already
pretty much explicit in this context.
2013-02-08 12:33:07 +01:00
Raphael Stolt 06d5475129 Added PHPUnit utility method markTestSkippedOnRedisVersionBelow and applied it where necessary 2013-02-07 22:46:25 +01:00
Raphael Stolt 1536455fea Added CLIENT SET/GETNAME command 2013-02-07 20:21:29 +01:00
Daniele Alessandri aa1b070f9b Bump VERSION and update CHANGELOG. 2013-02-03 13:59:55 +01:00
Daniele Alessandri 3e125c964c Implement Predis\Session\SessionHandler.
This class makes it easy to use Predis to store PHP sessions on Redis.

NOTE: requires PHP >= 5.4.0 or a polyfill for PHP's SessionHandlerInterface.
2013-02-02 15:14:06 +01:00
Daniele Alessandri e9fdc47d3f Minor fix in readme.
[ci skip]
2013-02-02 10:48:22 +01:00
Daniele Alessandri d3930ea298 Update markdown files to use relative links.
See https://help.github.com/articles/relative-links-in-readmes for details.

[ci skip]
2013-02-02 10:44:54 +01:00
Daniele Alessandri 0efcbb7992 Add a way to get the default value of an option from options.
It is not possible to get the default value of a client option using
either its name or instance:

  $options = array(
    'profile' => function ($options, $option) {
      // instance of Predis\Option\OptionInterface
      $profile = $options->getDefault($option);

      // string representing an option handled by $options,
      // returns NULL if the specified name is not handled.
      $profile = $options->getDefault('profile');

      return $profile;
    },
  );

This addition makes it less awkward to get the default value of an
option, especially when not in the context of a callable option
initializer.
2013-02-02 10:30:53 +01:00
Daniele Alessandri f2af247c63 Push minor changes in the standard executor internals. 2013-01-29 12:38:19 +01:00
Daniele Alessandri a5cf6d72cd Fix standard pipeline executor not parsing raw replies.
This bug was actually introduced right before pushing the stable release
of v0.8.0 in which we moved the responsibility of parsing raw replies
with command parser to consumer classes.

This commit closes #101.
2013-01-29 12:13:01 +01:00
Daniele Alessandri 7173f0c80c Get back to development. 2013-01-29 11:55:47 +01:00
Daniele Alessandri 495e3c6f8a Bump VERSION and update CHANGELOG.
[ci skip]
2013-01-19 11:18:58 +01:00
Daniele Alessandri 3465bc7c1f Add PHP 5.5 to the CI build matrix and switch to branch blacklisting. 2013-01-19 11:16:20 +01:00
Daniele Alessandri 8bf896f81f Update CHANGELOG. 2013-01-19 09:56:51 +01:00
Daniele Alessandri 0085bc08ae Fix CHANGELOG. 2013-01-19 09:46:58 +01:00
Daniele Alessandri f7232b9ddc Highlight PHP code in FAQ. 2013-01-19 09:44:14 +01:00
Daniele Alessandri 95cc528904 Remove <?php tags from README.
It seems like GitHub can now highlight PHP syntax without those ones.
2013-01-19 09:44:09 +01:00
Daniele Alessandri 4a16cb9417 Update .gitignore.
[ci skip]
2013-01-13 13:54:09 +01:00
Daniele Alessandri 94758d5f58 Update CHANGELOG.
[ci skip]
2013-01-13 13:53:22 +01:00
Daniele Alessandri acc0f04bdb Add missing param to phpdoc entry.
[ci skip]
2013-01-13 13:48:50 +01:00
Daniele Alessandri 09de7be7cb Add optional callable to drive extraction of node hash in distributor.
This is mainly in response to the longstanding issue #36 in which my
proposed solution was fine in terms of functionalities, but eventually
never made into the repository since it was far from being clean enough
for my taste.

Now developers can optionally pass a callable object when creating the
hashring instance to decide how the distributor should extract the hash
from a node (really a connection instance) to populate the ring:

  use Predis\Cluster\Distribution\HashRing;
  use Predis\Connection\PredisCluster;

  $servers = array(
    'tcp://10.0.0.1?alias=node01',
    'tcp://10.0.0.2?alias=node02',
  );

  $options = array(
    'nodehash' => function ($connection) {
      return $connection->getParameters()->alias;
    },
    'cluster' => function ($options) {
      $replicas = HashRing::DEFAULT_REPLICAS;
      $hashring = new HashRing($replicas, $options->nodehash);
      $cluster  = new PredisCluster($hashring);

      return $cluster;
    },
  );

  $client = new Predis\Client($servers, $options);

Both HashRing and KetamaPureRing in the Predis\Cluster\Distribution
namespace support this new approach.
2013-01-13 13:10:01 +01:00
Daniele Alessandri 70b279bbdc Bump year in LICENSE.
On a related note, happy new year!

[ci skip]
2013-01-01 13:58:18 +01:00
Daniele Alessandri f8cbbc5b8f Update URL for phpiredis.
Ownership of the repository has been transferred. Thanks again to
@seppo0010, the original author of phpiredis, for his work on the
extension!

[ci skip]
2012-12-28 20:51:34 +01:00
Daniele Alessandri 83720075f3 Make it possible to cast key prefix processor instance to string.
Mostly useful with string interpolation when getting the current prefix
associated to a client instance.
2012-12-27 10:50:25 +01:00
Daniele Alessandri 9901233fa1 Instantiate the current class when subclassing Client.
Previously the getClientFor() method in a subclass of Predis\Client
returned an instance of Predis\Client instead of a new instance of
the subclass. The new behaviour is more correct.
2012-12-24 14:50:07 +01:00
Daniele Alessandri dcb4093046 Update CHANGELOG. 2012-12-15 17:46:00 +01:00
Daniele Alessandri 1e8af648cb [tests] Add missing tests for Predis\Option\ClientReplication. 2012-12-15 17:22:10 +01:00
Daniele Alessandri ff5e3515c3 Implement callable initializer for "connections" client option. 2012-12-15 17:12:37 +01:00
Daniele Alessandri 59813cd74e Pass option handler instance to callable initializers.
This is just a convention implemented to client options supporting
callable initializers such as "profile", "cluster" and "replication".

This is useful to get a fully-initialized default value and perform
additional operations before returning it. An example with "profile":

  $options = array(
    'commands' => array(
      'test1' => 'Predis\Command\ConnectionEcho',
      'test2' => 'Predis\Command\ConnectionEcho',
    ),
    'profile'  => function ($options, $option) {
      $profile = $option->getDefault($options);

      if (is_array($options->commands)) {
        foreach ($options->commands as $id => $cmd) {
          $profile->defineCommand($id, $cmd);
        }
      }

      return $profile;
    },
  );
2012-12-15 16:47:32 +01:00
Daniele Alessandri bfd96b15dc Fix response parsing with scripted commands after -NOSCRIPT.
This commit fixes issue #94.
2012-12-12 14:28:06 +01:00
Daniele Alessandri 51b466267d Fix missing use directives.
This miss caused a PHP error when Redis did not return a +QUEUED
reply inside a MULTI / EXEC command.
2012-11-21 22:57:23 +01:00
Daniele Alessandri 78f3596566 Merge branch 'tests/update-redis-2.8' into v0.8 2012-11-21 22:13:42 +01:00
Daniele Alessandri ac01c1a17f [tests] TTL and PTTL return -2 on non existing keys in Redis >= 2.8. 2012-11-21 22:09:05 +01:00
Daniele Alessandri 46920c9c77 [tests] Fix expected exception message on wrong key type.
Redis >= 2.8 returns -WRONGTYPE errors instead of -ERR when executing
operations on wrong key type (such as trying to LPUSH on a string key).

Luckily for us, phpunit's @expectedExceptionMessage annotation actually
does not perform an exact match but works on a substring so we just omit
the initial part of the exception message to make the test work.
2012-11-21 21:49:49 +01:00
Daniele Alessandri b26d6103a6 Avoid channels reordering issues when testing UNSUBSCRIBE.
When using UNSUBSCRIBE without a list of channels (which actually means
"unsubscribe from all the subscribed channels") Redis 2.6 does not
guarantee that channels are returned following the same order of
subscription.
2012-11-13 16:44:55 +01:00
Daniele Alessandri a4760d65cd Bump Redis version used in tests on Travis CI.
It seems like Travis CI switched silently to Redis 2.6, which means
that we can enable the full test suite of Predis.
2012-11-13 16:13:07 +01:00
Daniele Alessandri 49aa6f0aca Update performance numbers in the related FAQ section.
We use newer version of PHP, phpiredis, phpredis, Redis and Ubuntu.

[ci skip]
2012-11-08 13:06:24 +01:00
Daniele Alessandri 292f9939b2 Tweak CONTRIBUTING instructions.
[ci skip]
2012-11-03 16:02:43 +01:00
Daniele Alessandri daa36a980d Make Predis\Connection\PhpiredisConnection::write() protected.
We should actually make use of more protected methods in this
class instead of the private ones, this is most likely going
to be addressed in future commits.

See also issue #86 on GitHub for the reason behind this change.
2012-11-03 15:21:52 +01:00
Daniele Alessandri 0b09d2c359 Back to development for the next patch release. 2012-11-03 15:16:01 +01:00
Daniele Alessandri 0a622aee31 Bump VERSION and update CHANGELOG.
Guess what time is it? Yeah, once again... it is release time!
2012-10-23 01:46:05 +02:00
Daniele Alessandri 040dfebd9c Minimum required version of PHP is 5.3.2. 2012-10-23 01:35:22 +02:00
Daniele Alessandri 0e4604a9bb Tweak README. 2012-10-23 01:34:48 +02:00
Daniele Alessandri deb64c295a Add notes about coding standards in CONTRIBUTING.
[ci skip]
2012-10-12 22:43:45 +02:00
Daniele Alessandri aac06a4cd8 Move contributing section from README to CONTRIBUTING.
[ci skip]
2012-10-12 22:32:21 +02:00
Daniele Alessandri dfb5cf2c1b Remove TODO.
We are going to open a new issue on GitHub for a decent
documentation of the library.

[ci skip]
2012-10-12 21:57:50 +02:00
Daniele Alessandri a1024bba53 Merge FAQ files into a single markdown document.
[ci skip]
2012-10-12 21:51:54 +02:00
Daniele Alessandri f357cafb14 Update CHANGELOG.
[ci skip]
2012-10-12 21:39:05 +02:00
Daniele Alessandri 2b4cf80d90 Merge remote-tracking branch 'origin/pr/84' 2012-09-18 18:05:11 +02:00
Ondrej -onovy- Novy 6cd1f03834 Fixed typos. 2012-09-18 17:43:29 +02:00
Daniele Alessandri 732d7f96d1 Extract a strategy class from the replication connection. 2012-09-12 13:09:52 +02:00
Daniele Alessandri b4e1ab106c Update README.
[ci skip]
2012-09-10 14:17:00 +02:00
Daniele Alessandri 5a2c61c02b Update CHANGELOG.
[ci skip]
2012-09-04 18:32:16 +02:00
Daniele Alessandri 1b9e10bdd8 Move command response parsing to the client class.
Connection classes should just handle, convert and return simple Redis
types while parsing and transforming structured replies should be done
by consumers (see Predis\Client or Predis\Transaction\MultiExecContext).

This actually makes more sense considering that parsing a complex response
with the associated command parser may require different actions. As an
example, the result of EXEC is a multibulk that holds the actual responses,
so we really need to parse each one of its elements and we should also
make sure that iterable multibulks are consumed. We already did that
previously, but it was weird knowing that command parsers were applied
by the connection class.

This also moves some duplicated logic away from each connection class
implementation which is a nice bonus.
2012-09-04 14:53:05 +02:00
Daniele Alessandri 37e2b546b0 Fix MULTI / EXEC pipeline executor when using iterable multibulks. 2012-09-04 13:19:26 +02:00
Daniele Alessandri f163e1221b Describe scripted commands (EVAL / EVALSHA) in the README.
[ci skip]
2012-09-04 13:19:18 +02:00
Daniele Alessandri 1bb2ab95ef Use the proper service name.
[ci skip]
2012-09-03 19:52:25 +02:00
Daniele Alessandri ea18afc820 Update the configuration file for Travis CI.
Travis is upgrading their base image and will disable most of
the services at boot (Redis is one of these).
2012-09-03 14:39:11 +02:00
Daniele Alessandri baa91da35b Merge remote-tracking branch 'origin/pr/79' 2012-09-03 14:37:46 +02:00
Pascal Borreli 6d85a81da4 Fixed typo 2012-09-03 11:50:26 +00:00
Daniele Alessandri f913e81b9f Add a reference to Predis\Async in the README.
I think we can indeed start promoting Predis\Async now that it has
reached a fairly stable state (in terms of API and functionalites)
despite still being considered experimental.

[ci skip]
2012-09-03 12:27:45 +02:00
Daniele Alessandri 003b3d180d Add missing test for Predis\Client::getClientFor(). 2012-08-24 12:13:37 +02:00
Daniele Alessandri a6e1ac11d0 Implement separate Predis\Client::getConnectionById().
This method is not part of Predis\ClientInterface because it is being
considered mostly an helper / utility method.
2012-08-24 12:07:56 +02:00
Daniele Alessandri be46ab813c Remove useless default NULL value in method arguments. 2012-08-24 11:55:19 +02:00
Daniele Alessandri 6918de6e4b Restore 0x notation for CRC16 hash generator. 2012-08-24 11:51:00 +02:00
Daniele Alessandri cfa97dd9f5 Fix cs. 2012-08-24 11:49:43 +02:00
Daniele Alessandri 1e8f790ee4 Remove leftover method. 2012-08-24 11:48:42 +02:00
Daniele Alessandri c655affe5f Add Predis\Command\CommandInterface::setRawArguments(). 2012-08-24 11:47:44 +02:00
Daniele Alessandri 457fd6076d CS fixes.
[ci skip]
2012-08-22 11:54:49 +02:00
Daniele Alessandri 282287765b Fix phpdoc comment.
[ci skip]
2012-08-22 11:53:16 +02:00
Daniele Alessandri 00d6160549 Enable code coverage report on Travis CI. 2012-08-22 11:46:31 +02:00
Daniele Alessandri 576163724c Add an example for multibulk reply iterators.
[ci skip]
2012-08-21 18:10:49 +02:00
Daniele Alessandri 9df9dbdedc Promote multibulk response iterators as Predis response objects.
Multibulk response iterators will not be passed anymore to the response
parser method of the command that generated the response. Pipeline and
transaction abstractions still consume interators returned as response
items.
2012-08-21 17:15:14 +02:00
Daniele Alessandri 8d7f5099c4 Add tests for Predis\Connection\RedisCluster (redis-cluster). 2012-08-21 15:24:06 +02:00
Daniele Alessandri e8daf45269 Improve Predis\Pipeline\MultiExecExecutor. 2012-08-19 15:00:45 +02:00
Daniele Alessandri 8567b05459 Specify the server profile in constructor of the connection factory.
When no server profile is specified, the connection factory will not push
any initialization command to the newly created connection object.

This change is mainly useful when using redis-cluster and also makes it
possible to easily inject commands such as "SCRIPT LOAD" at initialization
time by grouping everything into one common place simply by extending the
connection factory class.
2012-08-19 13:57:58 +02:00
Daniele Alessandri 6e76ea6c7e Add tests for classes in the Predis\Protocol\Text namespace.
This was the only namespace containing classes with no tests.
2012-08-02 21:42:11 +02:00
Daniele Alessandri e774a301c4 Add tests for Predis\Connection\ComposableStreamConnection. 2012-08-02 17:25:13 +02:00
Daniele Alessandri 2b85824d74 Apply minor fixes to README.
[ci skip]
2012-08-02 16:15:31 +02:00
Daniele Alessandri 81422b9992 Partially rewrite README.
[ci skip]
2012-08-02 16:10:58 +02:00
Daniele Alessandri c230b6e831 Update TODO.
[ci skip]
2012-08-02 16:10:47 +02:00
Daniele Alessandri 69d4c013f7 Minor change (mostly micro-optimization). 2012-08-02 12:42:53 +02:00
Daniele Alessandri 1ac9cc9c71 Support EVAL and EVALSHA with redis-cluster.
We extract the keys from commands using the second argument of EVAL /
EVALSHA which specifies the number of arguments that must be treated
as keys (used to populate the KEYS table in the Lua script) and then
we check if there is only one key since redis-cluster right now does
not support multi-keys requests.

Our scripted command abstraction is also supported.
2012-08-02 12:08:56 +02:00
Daniele Alessandri b2f59a0c63 Support EVAL and EVALSHA with client-side sharding (Predis cluster).
We extract the keys from commands using the second argument of EVAL /
EVALSHA which specifies the number of arguments that must be treated
as keys (used to populate the KEYS table in the Lua script) and then
we check if all the keys generate the same hash using the usual method.

Our scripted command abstraction is also supported.

It comes without saying that accessing or setting keys from within the
Lua script is something that might not work as expected, so you should
be careful when using EVAL and EVALSHA in the context of client-side
sharding.
2012-08-02 11:38:20 +02:00
Daniele Alessandri 93971bcb45 Merge branch 'command-hash-strategy'
Conflicts:
	lib/Predis/Connection/RedisCluster.php
2012-07-30 20:29:13 +02:00
Daniele Alessandri e54bc31212 Create Predis\Cluster namespace and move related classes / interfaces. 2012-07-30 20:10:14 +02:00
Daniele Alessandri b9eddae96f Fix and optimize node guessing algorithm. 2012-07-30 16:40:53 +02:00
Daniele Alessandri 7683f97ff2 Move the hash generator inside the command hash strategy class.
This should make things a tiny bit faster (we are speaking about micro
optimizations anyway) but more  importantly it results in a better
encapsulation.
2012-07-30 15:42:45 +02:00
Daniele Alessandri f4f9d02551 Improve the slot-guessing algorithm.
This change makes it almost useless to pre-assign slots using connection
parameters, but the functionality will be kept for special cases.
2012-07-30 12:55:41 +02:00
Daniele Alessandri bacdb7ff62 Remove useless "use" directives. 2012-07-29 22:30:31 +02:00
Daniele Alessandri e0c6ad58be Optimize lazy initialization of the slots map.
This is twice faster than before but still kind of slow compared to the
initialization of a cluster with no slots pre-assigned to connections.
2012-07-29 22:07:00 +02:00
Daniele Alessandri febd99421f Pre-associate connections to slot ranges using connection parameters.
This makes it possible to easily assign a connection to a slot range
using the key "slots" in connection parameters like in the following
example:

    $parameters = array(
        'tcp://127.0.0.1:6379?slots=0-1364',
        'tcp://127.0.0.1:6380?slots=1365-2729',
        'tcp://127.0.0.1:6381?slots=2730-4095',
    );

    $options = array('cluster' => 'redis');
    $client = new Predis\Client($parameters, $options);

It is possible to get the full list of slot ranges for each node of
the cluster using redis-cli connected to one of the nodes:

    ./redis-cli -h 127.0.0.1 -p 6379 CLUSTER NODES

The last column in the resulting output contains the slots assigned
to each instance participating to the redis cluster.
2012-07-29 19:38:58 +02:00
Daniele Alessandri 8559c2cb30 Make it possible to pre-associate slots to a connection.
This is useful to avoid guessing the correct server instance at runtime
thus reducing the overhead of a guess-and-try approach since relying on
-ASK or -MOVED responses returned by a node is a costly operation.

For now, you can pre-associate slots using the "cluster" client option:

    $parameters = array(
        'tcp://127.0.0.1:6379',
        'tcp://127.0.0.1:6380',
        'tcp://127.0.0.1:6381',
    );

    $options = array(
        'cluster' => function ($options) {
            $cluster = new Predis\Connection\RedisCluster();

            $cluster->setSlots(0,    1364, '127.0.0.1:6379');
            $cluster->setSlots(1365, 2729, '127.0.0.1:6380');
            $cluster->setSlots(2730, 4095, '127.0.0.1:6381');

            return $cluster;
        },
    );

    $client = new Predis\Client($parameters, $options);

In the future we will make the slots configuration easier by fetching
the configuration from a node using the command "CLUSTER NODES" or by
pre-computing the slices of slots associated to a node when adding it
to the cluster connection object.
2012-07-29 14:14:11 +02:00
Daniele Alessandri 2ba54a0e1c Use specific command hash strategy for redis-cluster.
This is needed because redis-cluster does not support the same commands
or operations that can be performed with our client-side managed predis
cluster.

For example redis-cluster does not support key tagging (that is, parts
of a key enclosed by {...} to hash only that specific part of a key)
and multiple-key operations suchs as MGET, MSET, SDIFF, SUNION or SINTER.
Some multiple-key operations can be performed anyway if the command has
only one key (e.g. "MGET foo" and "MSET foo bar" will not fail).
2012-07-29 13:48:16 +02:00
Daniele Alessandri 024a31d571 Fix wrong binary notation.
Cannot use 0b yet since it is PHP 5.4 only.
2012-07-29 13:33:06 +02:00
Daniele Alessandri d0572b0efc Rename command hash strategy cass used by Predis cluster. 2012-07-29 12:07:48 +02:00
Daniele Alessandri 0f80cb55bb Add suggested extensions to composer.json.
[ci skip]
2012-07-27 16:58:51 +02:00
Daniele Alessandri 55a3fd65a2 More code styling changes. 2012-07-27 12:23:25 +02:00
Daniele Alessandri 6c732c737b Order "use" directives by namespace depth and name.
This is not really useful per se, but at least we use a fixed rule.
2012-07-26 23:04:20 +02:00
Daniele Alessandri 559853bdd5 Move some classes and interfaces in other namespaces. 2012-07-26 22:37:31 +02:00
Daniele Alessandri 28e1e7ad25 Reword some exception messages. 2012-07-26 16:31:09 +02:00
Daniele Alessandri 98112fdb39 Use instance methods to cast values for connection parameters. 2012-07-26 15:49:42 +02:00
Daniele Alessandri 0e8d978348 Minor code styling changes in client class.
[ci skip]
2012-07-26 15:18:09 +02:00
Daniele Alessandri 469f3cc68b Do not accept string or Predis\Profile\ServerProfileInstance in constructor.
To specify a server profile you can just set the "prefix" option in the
client options array passed to the constructor of Predis\Client.
2012-07-26 14:36:01 +02:00
Daniele Alessandri 36f8210864 Rename variable and field. 2012-07-26 12:18:28 +02:00
Daniele Alessandri 81be513eaa Change signature of Predis\Pipeline\PipelineContext constructor.
Now the second argument is a Predis\Pipeline\PipelineExecutorInterface.
2012-07-26 11:33:24 +02:00
Daniele Alessandri 4b73afc316 Add missing tests for Predis\Command\Hash\CommandHashStrategy. 2012-07-25 22:41:14 +02:00
Daniele Alessandri fd6a14d80b Make it possible to set/unset command handlers in CommandHashStrategy. 2012-07-25 22:22:55 +02:00
Daniele Alessandri f2d92f1e29 Expose the command hash strategy from the predis cluster class.
This will be useful to add, remove or change the handler used to
extract, validate and hash the keys of each command instance.
2012-07-25 21:25:50 +02:00
Daniele Alessandri c3cafaa9a6 Remove useless helpers. 2012-07-25 21:18:58 +02:00
Daniele Alessandri 89d6c0e9b6 Extract common PubSub handling logic into a separate abstract class. 2012-07-25 21:07:04 +02:00
Daniele Alessandri 9f51263136 Fix internal flags for MULTI / EXEC and PUB/SUB contexts.
Do not ask me why I was using 0x (the prefix for hexadecimal notation)
when what we really need here is 0b (the prefix for binary notation).
Really, everything was working by sheer coincidence.

Since 0b has been added in PHP 5.4, we rely on plain decimal numbers
to define our constants for now.
2012-07-21 13:48:32 +02:00
Daniele Alessandri a75e52cf5a Update CHANGELOG.
[ci skip]
2012-06-01 12:14:50 +02:00
Irakli Nadareishvili b865cee1f8 Make autoloader act nicer to autoloaders that may be running in parallel. 2012-05-27 21:09:38 +02:00
Daniele Alessandri 1f0be85a3d Add initial support for Redis cluster (Redis v3.0).
This implementation is capable of handling "ASK" and "MOVED" replies
returned by Redis when one of the nodes asks the client for temporary
or permanent redirects of a slot to a different node.

Performances look almost on par with our client-side sharding solution
and everything looks already relatively stable.

Tests are still missing.
2012-05-13 11:13:33 +02:00
Daniele Alessandri 2578e154d4 New commands: BITOP, BITCOUNT (Redis v2.6-dev). 2012-05-17 17:17:35 +02:00
Daniele Alessandri 81da6d2553 TIME can be considered a read-only command in MASTER / SLAVE. 2012-05-17 16:48:08 +02:00
Daniele Alessandri 188eaf035b Fix comment in package.ini.
[ci skip]
2012-05-17 09:53:45 +02:00
Daniele Alessandri 6638776d85 [test] Add tests for pipeline executors. 2012-05-17 09:43:48 +02:00
Daniele Alessandri 511fe0bbab Rewrite the logic used to handle Redis commands with clustering.
The reason for this change is to support the upcoming redis-cluster since
it has different behaviors compared to the client-side cluster implementation
provided by Predis. For example redis-cluster will not support key tags or
certain operations currently available with our client-side implementation.
2012-05-16 16:50:37 +02:00
Daniele Alessandri 56a3e327fc Add a pipeline executor that internally uses MULTI / EXEC.
The actual pipeline is wrapped between MULTI and EXEC to ensure that all the
commands are correctly sent and executed on the server. The whole pipeline is
discarded should it fail at a certain point during execution.

We do not use our Predis\Transaction\MultiExecContext abstraction internally
but rely on raw commands since this new executor does not really need full
support for Redis transactions.
2012-05-15 15:59:23 +02:00
Daniele Alessandri 63cf5048a7 Slightly optimize internals of MULTI / EXEC transactions.
We start using SplQueue to enqueue the commands executed inside a MULTI /
EXEC context so that we can dequeue them for parsing their replies later.

This change does not affect performances but makes the code more clean.
2012-05-15 15:03:42 +02:00
Daniele Alessandri 177d7e1c6a Fix CHANGELOG. 2012-05-15 12:44:49 +02:00
Daniele Alessandri 8a84f8b6cf Optimize command pipelines.
Using SplQueue instead of a plain PHP array to queue command instance in
the pipeline is faster and makes the underlying implementation definitely
more clean.

This change is not going to be backported to Predis v0.7 due to changes
in Predis\Pipeline\PipelineContextInterface.
2012-05-15 12:42:26 +02:00
Daniele Alessandri 09f15a9cb9 Fix README. 2012-05-15 10:38:53 +02:00
Daniele Alessandri 2b4885abc3 Update README.
[ci skip]
2012-04-30 19:56:08 +02:00
Daniele Alessandri 649e71c0ab Clean up leftovers. 2012-04-30 17:07:19 +02:00
Daniele Alessandri 14ac381aad Fix phpdoc. 2012-04-30 17:06:42 +02:00
Daniele Alessandri 78360ea27b Set raw arguments when switching from scripted command to EVAL. 2012-04-28 18:04:54 +02:00
Daniele Alessandri 214b7d2dc9 Remove almost useless method. 2012-04-28 09:23:41 +02:00
Daniele Alessandri 2d0b30dac5 Client handles -NOSCRIPT falling back to EVAL for scripted commands.
Now Predis\Command\ScriptedCommand uses EVALSHA instead of EVAL internally
so that performances should be better since the client do not resend the
Lua script body on each call.

Plain EVALSHA commands are not affected and will return or throw the error.
2012-04-28 08:56:11 +02:00
Daniele Alessandri 75afe831b0 Fix Predis\Command\ServerEvalSHA::getScriptHash().
"Predis\Command\ServerEvalSHA::getScriptHash()" was calculating the hash
while it just needs to return the first argument of the command.
2012-04-28 01:30:21 +02:00
Daniele Alessandri c36e6fd900 Pass also the command that generated the server error. 2012-04-27 23:59:51 +02:00
Daniele Alessandri 743ccc39ae Remove the "safe" pipeline option.
Just let users specify the appropriate pipeline executor.
2012-04-27 23:36:12 +02:00
Daniele Alessandri 41c29bed4e Change how Redis errors such as -ERR replies generates exceptions.
The "throw_errors" connection parameter has been removed and replaced by the
new "exceptions" client option since exceptions on -ERR replies returned by
Redis are not generated by connection classes anymore but are thrown by the
client class and other abstractions such as pipeline contexts.

This change does not affect much people using the Predis\Client class (aside
from the different configuration) but gives much more flexibility to those
building their own pieces of code around the internal classes of Predis.
2012-04-27 23:29:41 +02:00
Daniele Alessandri 90f37f8698 Do not assume that the position of a MultiBulkResponse iterator is 0. 2012-04-27 16:13:15 +02:00
Daniele Alessandri dc889be2a2 Switch to master inside executor when pipelining in replication mode.
The actual code to switch to master has been implemented only in the
standard and the fire-and-forget executor classes since it does not
make sense to have it in special executors used exclusively when in
client-side clustering mode.
2012-04-25 13:02:33 +02:00
Daniele Alessandri ca7bd8149f Scripting abstraction can use negatives to calculate number of keys.
With a negative number Predis will count from the end of the arguments list
to calculate the actual number of keys that will be interpreted as elements
for `KEYS` by the underlying `EVAL` command.
2012-04-25 11:35:06 +02:00
Daniele Alessandri 9426d78b90 Fix example for custom distribution strategy.
See ISSUE #63 for details.
2012-04-13 11:37:03 +02:00
Daniele Alessandri 6b6c91cd15 Update CHANGELOG. 2012-04-01 10:15:31 +02:00
Daniele Alessandri b511911ddb Update README.
[ci skip]
2012-03-31 12:00:10 +02:00
Daniele Alessandri eb450ae0b4 Make 2.6 the default server profile for the test suite too.
We leave 2.4 for Travis CI since their CI environment uses Redis 2.4.

[ci skip]
2012-03-31 11:49:46 +02:00
Daniele Alessandri ca033d15a9 Add a couple of paragraphs in the FAQ. 2012-03-31 11:45:32 +02:00
Daniele Alessandri 9443da1948 Update TODO. 2012-03-31 11:42:25 +02:00
Daniele Alessandri 298dc87613 Update CHANGELOG. 2012-03-31 11:41:43 +02:00
Daniele Alessandri 92697aa075 Make 2.6 the default server profile. 2012-03-31 11:39:42 +02:00
Daniele Alessandri 7c393cbc09 Apparently the next major version or Redis will be 2.8. 2012-03-31 11:36:35 +02:00
Daniele Alessandri 5b6e4dc3dd Make it possible to prepend the autoloader. 2012-03-19 11:31:55 +01:00
Daniele Alessandri b37d072b68 Make Predis\Autoloader faster. 2012-03-18 18:01:01 +01:00
Daniele Alessandri 608c48146f Fix helper method for invalid options in connection classes.
This fix is needed since connection parameters do not respond to __toString()
anymore after recent changes.
2012-03-18 15:23:25 +01:00
Daniele Alessandri bcba9e1009 Change how we check for required extensions in connection classes. 2012-03-18 15:22:24 +01:00
Daniele Alessandri 64a84d9020 Add notes about the parameters supported by each connection class. 2012-03-18 15:07:18 +01:00
Daniele Alessandri a3b4c2244a Remove some overkill stuff from Predis\ConnectionParameters.
It was basically some crazy and almost useless stuff I'd say.
2012-03-18 14:53:21 +01:00
Daniele Alessandri 4805a048ed Add missing tests for Predis\Profile\ServerProfile::defineCommand(). 2012-03-18 13:00:53 +01:00
Daniele Alessandri c394458b80 Remove an almost useless method from Predis\Profile\ServerProfile. 2012-03-18 13:00:28 +01:00
Daniele Alessandri 51d0b58cd3 Add new interfaces used to abstract the main client class and contexts.
Now developers can pass a client object or an executable context (see
Predis\Transaction\MultiExecContext or Predis\Pipeline\PipelineContext)
interchangeably as parameters to their methods using the new interface
Predis\BasicCliantInterface.

These new interfaces will also allow us to easily create new client
classes aside from the standard Predis\Client one.
2012-03-18 11:05:33 +01:00
Daniele Alessandri 890ace8565 Rename certain connection parameters usig shorter names.
- `connection_async` is now `async_connect`
  - `connection_timeout` is now `timeout`
  - `connection_persistent` is now `persistent`
2012-03-16 19:33:17 +01:00
Daniele Alessandri 8ba432e8f7 Move list of renamed namespaces/interfaces/classes to a separate file. 2012-03-16 19:20:15 +01:00
Daniele Alessandri d61bb3af07 Update CHANGELOG. 2012-03-11 17:50:48 +01:00
Daniele Alessandri da381fffa9 Promote 2.6 as an independent server profile for Redis 2.6.
The development server profile now targets Redis 3.0.
2012-03-11 17:49:18 +01:00
Daniele Alessandri 7b01bc0644 Fix MONITOR and Predis\MonitorContext with Redis 2.6.
Starting with 2.6, Redis uses a slightly different format for the payload
returned by MONITOR for each command. Predis can now adapt to this difference
and returns a new `client` field in the payload object. This new field is
always defined but is set to NULL when connected to Redis < 2.6.

Please note that Redis 2.6 now does not echo the `MONITOR` command as the
first payload when opening a new MONITOR context.
2012-03-11 17:39:57 +01:00
Daniele Alessandri 7893fd1faa New command: TIME (Redis v2.6-dev). 2012-03-11 17:34:06 +01:00
Daniele Alessandri 785670dcf7 Enable integration tests for Redis commands on Travis CI.
This was not possible before since our test suite requires Redis >= 2.4 but
their environment was running Redis 2.2 until a month ago or so.
2012-02-25 10:58:00 +01:00
Daniele Alessandri ec723fd4a9 Remove the ability to execute a command on all the nodes of a cluster.
The reason for this change is that not every cluster implementation can support
this behaviour, think of Redis cluster for example. We moved the implementation
of this method in Predis\Connection\PredisCluster since it can still be useful.
2012-02-07 15:40:19 +01:00
Daniele Alessandri b67af29eb6 Make cluster and replication classes extend from a common interface. 2012-02-07 11:42:34 +01:00
Daniele Alessandri dc14c29676 Rename certain namespaces, interfaces and classes.
Now we follow a Symfony2-like naming convention for namespaces, interfaces
and classes sticking with one clear rule.

- Renamed namespaces:

  - Predis\Network
  - Predis\Profiles
  - Predis\Iterators
  - Predis\Options
  - Predis\Commands
  - Predis\Commands\Processors

- Renamed interfaces:

  - Predis\IReplyObject
  - Predis\IRedisServerError
  - Predis\IConnectionFactory
  - Predis\IConnectionParameters
  - Predis\Options\IOption
  - Predis\Options\IClientOptions
  - Predis\Profile\IServerProfile
  - Predis\Pipeline\IPipelineExecutor
  - Predis\Distribution\INodeKeyGenerator
  - Predis\Distribution\IDistributionStrategy
  - Predis\Protocol\IProtocolProcessor
  - Predis\Protocol\IResponseReader
  - Predis\Protocol\IResponseHandler
  - Predis\Protocol\ICommandSerializer
  - Predis\Protocol\IComposableProtocolProcessor
  - Predis\Network\IConnection
  - Predis\Network\IConnectionSingle
  - Predis\Network\IConnectionComposable
  - Predis\Network\IConnectionCluster
  - Predis\Network\IConnectionReplication
  - Predis\Commands\ICommand
  - Predis\Commands\IPrefixable
  - Predis\Command\Processor\ICommandProcessor
  - Predis\Command\Processor\ICommandProcessorChain
  - Predis\Command\Processor\IProcessingSupport

- Renamed Classes:

  - Predis\Commands\Command
  - Predis\Network\ConnectionBase

- Classes moved to different namespaces:

  - Predis\MonitorContext

Meh
2012-01-31 18:19:18 +01:00
Daniele Alessandri ce625ca902 Start development of Predis v0.8. 2012-01-15 12:04:17 +01:00
Daniele Alessandri 46d293a716 Fix phpdocs.
[ci skip]
2012-01-14 23:35:39 +01:00
Daniele Alessandri fcd41a4787 Fix CHANGELOG. 2012-01-14 23:33:39 +01:00
Daniele Alessandri 8dc9450f39 Bump year in LICENSE.
[ci skip]
2012-01-14 15:29:12 +01:00
Daniele Alessandri 6ad522f492 Update CHANGELOG. 2012-01-14 15:11:27 +01:00
Daniele Alessandri 317fb6c398 Make Predis\Network\MasterSlaveReplication serializable.
Since PHP cannot serialize closures we switched to a private method to check
if a SORT command is a read-only operation, but closures are still supported
even if they will make the connection unserializable.
2012-01-14 14:53:52 +01:00
Daniele Alessandri 93163bdfb3 Make it possible to serialize and unserialize connection instances. 2012-01-14 14:53:47 +01:00
Daniele Alessandri 626520b836 Add specific server profile alias for Redis 2.6. 2012-01-14 13:01:38 +01:00
Daniele Alessandri aaea628c55 Back to development for the next patch release. 2012-01-14 12:51:01 +01:00
Daniele Alessandri 135fd5004b Bump VERSION and update CHANGELOG. 2011-12-27 16:19:23 +01:00
Daniele Alessandri c25a815317 Update README. 2011-12-27 15:57:12 +01:00
Daniele Alessandri 39a9fc2ddd Add a new example for complex replication configuration. 2011-12-27 12:34:44 +01:00
Daniele Alessandri f5bca54bba Fix CHANGELOG. 2011-12-27 10:40:29 +01:00
Daniele Alessandri 364aa180f9 Use Predis\NotSupportedException for unsupported connection parameters. 2011-12-27 10:38:06 +01:00
Daniele Alessandri 4da506cd9e Track changes in Onion. 2011-12-24 19:03:13 +01:00
Daniele Alessandri ef5034dc72 Update CHANGELOG.
[ci skip]
2011-12-24 12:17:03 +01:00
Daniele Alessandri 994f045a4a Add a method to execute instances of Redis commands in a transaction. 2011-12-24 12:08:34 +01:00
Daniele Alessandri 8cd8d4e580 Fix broken scripted commands when all arguments are considered keys. 2011-12-21 23:14:46 +01:00
Daniele Alessandri 22f1aafae8 Fix example of replication. 2011-12-21 21:41:51 +01:00
Daniele Alessandri c47b009b69 Update documentation for master / slave replication. 2011-12-21 21:33:30 +01:00
Daniele Alessandri 2cff6f0886 Merge branch 'replication' into v0.7
See ISSUE #21 for history and details about transparent master / slave
replication support in Predis.
2011-12-21 21:25:56 +01:00
Daniele Alessandri 63cb150fc2 Switch to the master server right before the execution of a pipeline.
This is actually a temporary solution since we should be using a dedicated
pipeline executor to handle the master/slave replication connection.

Ideally we should stick with a slave if no write operations are present in
the buffer, but forcing a switch to the master connection is the easiest
solution for now and users can still create a new client instance from one
of the slaves when they are sure that their pipelines contain read-only
operations.
2011-12-21 21:15:46 +01:00
Daniele Alessandri 466c666547 Add example for master / slave replication. 2011-12-21 21:01:48 +01:00
Daniele Alessandri 8d5c794efe [tests] Add more tests for Predis\Network\MasterSlaveReplication. 2011-12-21 18:34:53 +01:00
Daniele Alessandri e3fba5d4b7 [tests] Add more tests for Predis\Network\MasterSlaveReplication. 2011-12-21 16:50:03 +01:00
Daniele Alessandri a8400f2ed8 Rename default replication class to Predis\Network\MasterSlaveReplication. 2011-12-21 16:50:03 +01:00
Daniele Alessandri 44629a33db [tests] Add tests for Predis\Network\PredisReplication. 2011-12-21 16:50:01 +01:00
Daniele Alessandri d38f164d3f Minor fixes in documentation. 2011-12-21 11:26:26 +01:00
Daniele Alessandri 9bc5685959 Make the "profile" option accept a callable object as initializer.
This can be useful to set up the profile with additional commands,
e.g. when injecting new "virtual" commands based upon the EVAL and
the Predis\Commands\ScriptedCommand class.
2011-12-21 10:56:10 +01:00
Daniele Alessandri 565690a5b1 Disallow certain commands when in replication mode.
Some of these commands do not actually pose any threat, but their replies can
be misleading since users do not know on which server they are connected to.
We prefer to make things explicit so users can get a new client object out of
a specific connection in the replication pool to issue these commands.
2011-12-20 12:10:06 +01:00
Daniele Alessandri bdbbe18e6c Add the ability to get a connection by alias from aggregated connections.
Previously it was possible to create a new instance of Predis\Client using
the alias of a single connection in a cluster of connections. Now we added
the ability to do this also when using master/slave replication.
2011-12-18 15:07:21 +01:00
Daniele Alessandri 78027f0498 Use our own channel to distribute Predis via PEAR instead of PearHub.
The new PEAR channel is self-hosted using Pirum.
2011-12-18 13:28:45 +01:00
Daniele Alessandri 104cd1eae7 Use Onion to build PEAR packages of Predis.
Since Pearhub is currently broken (unfortunately the project does not seem to
be actively mantained anymore) but we still want to have PEAR packages for our
library, we need to automate the creation of a package.xml definition file to
build the actual packages that will be uploaded on a self-hosted PEAR channel.

Onion, while still in its alpha stage right now, works perfectly fine for our
needs and its own package.ini file looks simple enough to edit and maintain.

See http://c9s.github.com/Onion for more details about Onion and thank @c9s
for making it available.
2011-12-18 12:50:10 +01:00
Daniele Alessandri 5148ce16c6 Add the ability to mark specific commands or scripts for EVAL as read-only.
As suggested by @Seldaek in ISSUE #21, it would be desiderable to have the
ability to mark certain scripts for EVAL (and EVALSHA) as read-only to avoid
switching to the master server when this is not really needed.

When marking a script as read-only, only its SHA1 hash is saved to use less
memory and to make this work transparently for both EVAL and EVALSHA.
2011-12-17 10:58:37 +01:00
Daniele Alessandri 4b9ab0bcce Revert to development version for the next patch release.
Forgot to do this early. [ci skip]
2011-12-16 22:04:21 +01:00
Daniele Alessandri 39ed8e3e8f Fix wrong usage of single-quotes for a string expecting interpolation. 2011-12-16 20:36:01 +01:00
Daniele Alessandri 6f4347010d Add new "replication" client option for master / slave replication.
When the "replication" option is specified and evaluates to true, the array of
connection parameters passed to the client constructor os be used to initialize
a new instance of Predis\Network\IConnectionReplication. This option can also
accept a callable object used as an initializer or the fully-qualified name of
a class.
2011-12-16 19:30:07 +01:00
Daniele Alessandri c43278eceb Implement support for master / slave replication configurations.
We used a new kind of virtual connection that, just like with cluster, groups
multiple connection objects and handles the logic needed to switch among them
depending on the kind of operation performed by commands..

Our default implementation starts by picking up a random slave and switches to
the master as soon as a command performing a write operation against a key is
detected. The master server will then be used for all the subsequent requests
unless a manual switch to a different connection object is performed.

Redis transactions are always performed on the master server, which means that
the switch to master is done as soon as the client issues a WATCH, MULTI or
any other command related to transactions.

See also https://github.com/nrk/predis/issues/21 for more details.
2011-12-16 16:28:36 +01:00
Daniele Alessandri 5561ce6bd3 Bump VERSION and update CHANGELOG.
Guess what time is it? Yes it is release time!
2011-12-11 17:24:01 +01:00
Daniele Alessandri 6730661b4a [tests] Use a custom phpunit.xml file for TravisCI.
TravisCI environmenti run Redis 2.2 but we need Redis 2.4 to run the
integration tests in the test suite. For now we have simply disabled
the `connected` group of tests using a custom phpunit.xml file, we will
see later if it is worth building Redis on the fly with a `before_script`
directive in .travis.yml or just wait for a a new version of Redis to
be deployed on their VM images.
2011-12-11 17:15:23 +01:00
Daniele Alessandri 4e0c09a3cf Fix E_STRICT error messages. 2011-12-11 16:57:47 +01:00
Daniele Alessandri 71aad42534 Update README and CHANGELOG. 2011-12-11 16:43:42 +01:00
Daniele Alessandri 25b7d72fc9 Make it possible to remove connections from a cluster. 2011-12-11 14:06:32 +01:00
Daniele Alessandri 0f88225104 [tests] Rename the realm-network-webdis group to realm-webdis. 2011-12-11 13:33:37 +01:00
Daniele Alessandri 8be921cb66 Minor changes to README. 2011-12-11 13:20:09 +01:00
Daniele Alessandri e12d80b67f Minor fixes to CHANGELOG. 2011-12-11 13:11:56 +01:00
Daniele Alessandri 8984af1201 Minor changes in comments. 2011-12-11 12:50:27 +01:00
Daniele Alessandri dc9bd4e3a3 Add notice in the example of servers-side scripting with Lua. 2011-12-11 12:41:38 +01:00
Daniele Alessandri 2c4073ecab Prepare CHANGELOG. 2011-12-11 12:36:48 +01:00
Daniele Alessandri 1d6d0f3555 Rename IOption::validate() to IOption::filter(). 2011-12-11 11:07:29 +01:00
Daniele Alessandri efdc16476d Remove explicit versioning from composer.json and add minor changes. 2011-12-11 11:07:29 +01:00
Daniele Alessandri 469d5127aa Update READMEs. 2011-12-11 11:07:23 +01:00
Daniele Alessandri 9dcabc3264 Make it possible to use any type of callable to execute a transaction. 2011-12-11 09:34:41 +01:00
Daniele Alessandri 6e13a8af44 [tests] Add tests for OOB commands inside a pipeline context. 2011-12-11 09:33:00 +01:00
Daniele Alessandri 58e61ae1ca Support for redis-cluster has been postponed to Predis v0.8.
The reason is pretty simple: redis-cluster will not be available in a stable
release of Redis anytime soon, so there is no reason to wait anymore to get
it supported in Predis v0.7.
2011-12-10 15:37:43 +01:00
Daniele Alessandri ab1aeb3c01 Remove BETA from repository. 2011-12-10 15:35:45 +01:00
Daniele Alessandri 1e8446ef63 Update README. 2011-12-10 15:32:15 +01:00
Daniele Alessandri 371ac91777 [tests] Rewrite the whole test suite to allow more granular testing.
Fix also a few bugs found while rewriting the test suite.

In order to be able to run integration tests, the test suite requires
a version of Redis >= 2.4.0.

The units have been splitted into several different groups using
PHPUnit @group annotation to allow developers to enable, disable
and combine certain types of tests. The available groups are:

  - disconnected: can run without a Redis server online
  - connected: active connection to a Redis server is required
  - commands: test dedicated to a specific Redis command
  - slow: performs operations that can slow down execution;

A list of the available groups can be obtained by running

  phpunit --list-groups

Groups of tests can be disabled or enabled via the XML configuration
file or the standard command-line test runner. Please note that due
to a bug in PHPUnit, older versions ignore the --group option when
the group is excluded in the XML configuration file. Please refer to
http://github.com/sebastianbergmann/phpunit/issues/320 for details

Integration tests in the @connected group check if the command being
tested is defined in the selected server profile (see the value of
the TEST_SERVER_VERSION constant in phpunit.xml). If the command is
not defined in the target server profile, the integration test is
automatically marked as skipped.

We also provide an helper script in the bin directory that can be
used to automatically generate a file with the scheleton of a test
case for a Redis command by specifying the name of the class in the
Predis\Commands namespace. For example, to generate a test case for
SET (represented by the Predis\Commands\StringSet class):

  ./bin/generate-command-test.php --class=StringSet

The realm of a command is automatically inferred from the name of the
class, but it can be set using the --realm option.
2011-12-10 15:26:00 +01:00
Daniele Alessandri dd20e8557f Pass the client options to the internal cluster initializer method.
This change is useless right now, but when Predis will support Redis cluster
we will need to have access the connection factory object since it will be
required by our future RedisCluster class.
2011-12-02 15:12:47 +01:00
Daniele Alessandri fae8a79cf2 Fix docs after rename of the executable files in bin/. 2011-12-02 10:15:21 +01:00
Daniele Alessandri da25d6b6ff Fix wrong method visibility. 2011-12-01 23:25:31 +01:00
Daniele Alessandri cad5d16eae Handle key prefixing in a completely different way.
When we will have PHP 5.4 going mainstream and Predis will drop support for
PHP 5.3, we will be able to rely in traits to semplify code and reuse more.
2011-12-01 22:52:11 +01:00
Daniele Alessandri a910807666 Make it possible to use any kind of callable for PUB/SUB callbacks. 2011-12-01 21:21:22 +01:00
Daniele Alessandri d81346641f Make it possible to get the client instance used by a pipeline object. 2011-12-01 20:42:37 +01:00
Daniele Alessandri 1b3478ec2e Rename files in the bin/ directory. 2011-12-01 19:05:12 +01:00
Daniele Alessandri 9ab18ff2b4 Fix fields serialization of the connection parameters class.
This was broken by a recent commit.
2011-12-01 18:52:05 +01:00
Daniele Alessandri 2babb8744a Minor code formatting changes. 2011-12-01 16:53:35 +01:00
Daniele Alessandri d9b95d0bc7 Remove useless backslash in the FQN of server profiles. 2011-12-01 16:33:14 +01:00
Daniele Alessandri d79ff39882 Add missing parameters in the phpdocs of PipelineContext. 2011-12-01 15:36:12 +01:00
Daniele Alessandri 559c5097cd Add the ability to discard the commands queued in a pipeline object. 2011-12-01 15:34:45 +01:00
Daniele Alessandri 367ca6e31e Fix mistype in the ServerEval class. 2011-12-01 14:50:34 +01:00
Daniele Alessandri 4a8c678561 Change how the key prefix processor is initialized.
When the argument of 'profile' is an instance of Predis\Profiles\IServerProfile
the value of the 'prefix' option is ignored, which means that it is up to the
user to initialize the appropriate prefix processor.
2011-12-01 14:42:58 +01:00
Daniele Alessandri a5bf0eb41a Partially rewrite the client options bits and remove some madness.
The concept is now similar to a little dependency-injection system.
2011-12-01 12:26:07 +01:00
Daniele Alessandri 1ae30d62db Returns the SHA1 hash of a Lua script from instances of ServerEval. 2011-12-01 08:49:42 +01:00
Daniele Alessandri 64119bb4a0 Do not use different methods to initialize socket for the PhpiredisConnection. 2011-12-01 08:43:34 +01:00
Daniele Alessandri 1d635c370f Change the visibility of certain methods in the client class. 2011-11-29 17:56:58 +01:00
Daniele Alessandri 1260c91f63 Pass the server profile to a connection initializer callback. 2011-11-29 17:17:08 +01:00
Daniele Alessandri 728afe7fcb Redesign how Predis\ConnectionFactory works and make more sense out of it. 2011-11-29 16:32:37 +01:00
Daniele Alessandri 058e11257b Add phpunit.xml to the list of files ignored by git.
The only configuration file for PHPUnit that we want to track using git is
phpunit.xml.dist since phpunit.xml is intended for user customizations of
the test suite.
2011-11-28 10:26:55 +01:00
Daniele Alessandri 31bd53b1ed Update README. 2011-11-28 10:21:19 +01:00
Daniele Alessandri a894f470bd Add an "autoload.php" utility script for autoloading in examples and tests. 2011-11-28 10:19:11 +01:00
Daniele Alessandri b7c715a03f Rename helper method used to fetch the key tag from a key.
The name "getKeyHashablePart" was too generic for this method after all.
2011-11-28 10:10:28 +01:00
Daniele Alessandri 4882e23319 Move Publish/Subscribe related classes to the Predis\PubSub namespace. 2011-11-28 10:01:21 +01:00
Daniele Alessandri 7bdc2e6195 Rename a few protected/private field names. 2011-11-25 14:17:18 +01:00
Daniele Alessandri 0fee0c6d97 Remove the underscore prefix for names of private/protected fields. 2011-11-25 14:17:11 +01:00
Daniele Alessandri 5d42b41c22 [test] Run the test suite in strict mode and use output colors. 2011-11-18 21:04:07 +01:00
Daniele Alessandri 2c1f349925 [test] Use phpunit to specify the parameters of the server used by the suite.
This is especially handy because users can now easily override them without
modifying the source code of the test suite and just by creating a phpunit.xml
file that is automatically picked up by phpunit over the phpunit.xml.dist file
shipped within the repository.
2011-11-18 20:54:58 +01:00
Daniele Alessandri d784838447 [test] Sleep one second to give BGSAVE the time to complete. 2011-11-18 20:43:48 +01:00
Daniele Alessandri 654907857d Update TODO. 2011-11-18 16:38:19 +01:00
Daniele Alessandri 5d04cf540d New commands: INCRBYFLOAT, HINCRBYFLOAT (Redis v2.6-dev). 2011-11-18 16:10:39 +01:00
Daniele Alessandri 51b998720e New commands: PSETEX, PEXPIRE, PEXPIREAT, PTTL (Redis v2.6-dev). 2011-11-18 15:58:36 +01:00
Daniele Alessandri 4e0709ad3d New command: SCRIPT (Redis v2.6-dev).
See http://redis.io/commands/script.
2011-11-18 13:55:03 +01:00
Daniele Alessandri f75974b5d8 New command: SLOWLOG (Redis 2.2).
See http://redis.io/commands/slowlog.
2011-11-18 12:42:14 +01:00
Daniele Alessandri 5680cd40b5 Support the different replies of CONFIG GET|SET|RESETSTAT. 2011-11-18 12:42:09 +01:00
Daniele Alessandri 43c9900804 Run CI only on the specified branches.
[ci skip]
2011-11-16 21:55:08 +01:00
Daniele Alessandri 5d5001c177 Rename markdown files using the .md extension. 2011-11-13 23:09:09 +01:00
Daniele Alessandri 3d4957b06d Merge pull request #50 from snc/travis-ci
Add support for Travis CI.
2011-11-13 13:54:36 -08:00
H. Westphal 734eba3165 Added travis-ci configuration. 2011-11-13 21:17:32 +01:00
H. Westphal 22cb11d057 Fixed typo. 2011-11-13 21:03:22 +01:00
Daniele Alessandri 20f9c0c155 Update composer.json with the new directive for autoloading. 2011-11-05 14:33:16 +01:00
Daniele Alessandri 29f26b0f9b [phpdoc] Apply a few fixes to the documentation. 2011-10-22 11:41:58 +02:00
Daniele Alessandri 2f23fb03f0 Apply minor changes to the rest of the examples. 2011-10-22 11:07:25 +02:00
Daniele Alessandri d160cd9175 Update the server-side scripting example to use the current Redis unstable. 2011-10-22 10:55:58 +02:00
Daniele Alessandri ce75acf81f Merge pull request #47 from GunioRobot/clean 2011-10-21 08:04:12 -07:00
Gun.io Whitespace Robot b9ca78ac43 Remove whitespace [Gun.io WhitespaceBot] 2011-10-21 10:50:42 -04:00
Daniele Alessandri 4e6ed3f26d [phpdoc] Add API documentation.
This is a starting point to add a documentation of the whole set of APIs and
classes of Predis. The next step will be to actually improve and extend it.
2011-10-21 12:54:24 +02:00
Daniele Alessandri 1f2104ef7f Strip the license header from files when generating the monolithic Predis file. 2011-10-18 17:35:49 +02:00
Daniele Alessandri 9608a97469 Add a license header to PHP files. 2011-10-18 16:41:46 +02:00
Daniele Alessandri b4d5b19b30 Fix a few oversights. 2011-10-18 16:19:12 +02:00
Daniele Alessandri 20d872a306 Apply some coding style changes. 2011-10-18 15:51:55 +02:00
Daniele Alessandri 4251664095 Change the way we enable/disable the safety catch to run the test suite.
Now we check for the presence of the file "test/enable.tests" to enable the
test suite instead of relying on the value of a constant defined in PHP. In
this way we can prevent commiting an enabled test suite by mistake since the
above mentioned file is not tracked by Git (see .gitignore)..
2011-10-15 10:58:02 +02:00
Daniele Alessandri b5affe739c Promote 2.4 as the default Redis server profile. 2011-10-15 10:31:38 +02:00
Daniele Alessandri f19c6335d1 Fix parsing of replies to INFO for Redis 2.4.
The new string format for INFO replies has been postponed to a future version
of Redis, so we just moved the INFO class that handles them to the development
server profile.
2011-10-15 10:21:34 +02:00
Daniele Alessandri e070f83dc5 Test suite: move tests for case-insensitive handling of commands names. 2011-10-02 23:29:03 +02:00
Daniele Alessandri c107d937fa Apply minor code styling change, nothing that really matters. 2011-10-02 23:19:08 +02:00
Daniele Alessandri 68dba4cb12 Ensure that commands are registered in server profiles using lowercase aliases. 2011-10-02 23:16:04 +02:00
Daniele Alessandri f1072f8344 Update composer.json. 2011-10-02 12:18:06 +02:00
Daniele Alessandri 5e41657363 Use the new Predis\Autoloader class for tests and examples. 2011-10-02 12:07:52 +02:00
Daniele Alessandri 04b8a8f75c Update comment to reflect old changes. 2011-10-02 11:55:23 +02:00
Daniele Alessandri f7d9c4bac7 Merge pull request #43 from juriansluiman/feature-uppercase
Now Predis follows the same standard behaviour of PHP (method names are treated
case-insensitively) when invoking methods related to Redis commands, (i.e.
$client->info() or $client->INFO() makes no difference).
2011-10-02 02:40:00 -07:00
Jurian Sluiman 49355b0881 Provide better name for test method
testMagicUppercase()? I don't know where I got that one from...
Just changed the method name to something more describring the
actual test.
2011-09-28 18:05:46 +02:00
Jurian Sluiman c33d053531 Add support for mixed case commands
Commands in Redis are most time written in uppercase, Predis supports
only lowercase commands. This change converts all commands into lower-
case, so MiXeDcAsE and UPPERCASE commands can be created as well.
2011-09-28 17:47:56 +02:00
Jurian Sluiman 0d28395aa0 Remove additional test
CreateCommand and supportsCommand are the only two methods which need
to be changes, so test for only those two methods.
2011-09-28 17:34:21 +02:00
Daniele Alessandri 7ebbe25171 Merge pull request #41 from thumbtack/autoloader
Add an autoloader class for Predis.
2011-09-27 23:18:20 -07:00
Eric Naeseth 1296717c2d Update README.
Signed-off-by: Eric Naeseth <eric@thumbtack.com>
2011-09-27 17:43:51 -07:00
Eric Naeseth 94a2ddeca9 Add an autoloader for Predis classes.
This makes it easier to use Predis in scripts and projects that do
not already include as PSR-0 autoloader.

Signed-off-by: Eric Naeseth <eric@thumbtack.com>
2011-09-27 17:42:06 -07:00
Jurian Sluiman 07584f859c Add methods to test for uppercase and lowercase commands
At this moment predis is only capable of lowercase commands, the test
adds the requirement to provide both lowercase, uppercase (and even
mixed case) commands.
2011-09-26 20:33:45 +02:00
Daniele Alessandri 45a5dd49a7 Merge branch 'multiexec_rewrite' 2011-08-24 16:21:08 +02:00
Daniele Alessandri bd8a44101c Change some exception messages thrown by the transaction class. 2011-08-24 11:59:47 +02:00
Daniele Alessandri 71e7cb1399 Make some methods/fields of the transaction class protected instead of private. 2011-08-24 11:49:31 +02:00
Daniele Alessandri f085d2f97d Use a protected method to get all the flags of a transaction. 2011-08-24 11:46:07 +02:00
Daniele Alessandri 647cd53235 Use 'env' in the shebang instead of looking for php in /usr/bin. 2011-08-23 15:34:25 +02:00
Daniele Alessandri 8fdf935605 Make it possible to exclude certain classes when generating a single file.
The script that is used to create a single file out of the whole repository can
now accept a list of classes (their full FQN is needed) that must be excluded
when generating the file. The list can be passed directly in the command line
(multiple -e parameters) or in text file that contains a class name on each
line (single -E parameter).

The script does also a basic check to ensure that the user is not excluding a
class that is referenced by other subclasses.
2011-08-23 15:13:40 +02:00
Daniele Alessandri 7742fd5a22 Fix the bitmask used to check the state of subscriptions in a PubSub context.
The old code was not really broken, but this one is more appropriate.
2011-08-21 15:24:06 +02:00
Daniele Alessandri 7241fe6419 Make the code that process EXEC replies more easy on the eyes. 2011-08-21 15:18:39 +02:00
Daniele Alessandri d01e738d59 Move the code that executes a transaction block to a separate method. 2011-08-21 15:15:39 +02:00
Daniele Alessandri 0bdcf299c2 Implement a few minor changes. 2011-08-21 14:58:39 +02:00
Daniele Alessandri 03d408ddad Use a single integer to store and check the current state of a transaction. 2011-08-21 14:31:04 +02:00
Daniele Alessandri 3733e790eb Reuse code. 2011-08-21 11:55:08 +02:00
Daniele Alessandri a9e34cabb1 Add a composer.json for Composer.
Composer is a package manager for PHP currently under development. You can find
details about Composer at the following URL http://github.com/composer/composer
2011-08-21 10:12:54 +02:00
Daniele Alessandri b30f495345 Change how the hash of a node is retrieved in the hashring-based distributor.
Now classes that extend Predis\Distribution\HashRing can override how the hash
of a node is retrieved in order to implement different kind of distribution
strategies while reusing the base algorithm.
2011-08-20 18:07:42 +02:00
Daniele Alessandri c6fa5232bc Unset multiple fields with just one unset(). 2011-08-20 18:00:58 +02:00
Daniele Alessandri 2b62b75557 Jot down planned improvements for the single-file builder script. 2011-08-20 16:36:11 +02:00
Daniele Alessandri 6151d6d53e Improve actual "namespace" and "use" directives detection (fix ISSUE #35). 2011-08-20 16:30:33 +02:00
Daniele Alessandri db51f6e0d0 Remove spurious carriage returns and trailing spaces. 2011-08-20 16:27:59 +02:00
Daniele Alessandri 62744fbb02 Merge branch 'webdis_connection' 2011-06-29 12:05:24 +02:00
Daniele Alessandri 05b111d6d2 Update comment. 2011-06-29 12:05:00 +02:00
Daniele Alessandri fc51f23ca7 Return cURL errors on HTTP response codes >= 400.
By default the cURL extension does not trigger any error when fetching a
response with an HTTP code >= 400. Changing this behaviour is also useful to
intercept the 403 error generated when executing Redis commands disallowed
on Webdis by using ACLs.
2011-06-08 23:07:23 +02:00
Daniele Alessandri b85bc00880 Add support for the 'connection_timeout' parameter with WebdisConnection. 2011-06-08 22:40:35 +02:00
Daniele Alessandri 86256f2819 Minor reorganization, nothing worth mentioning. 2011-06-08 21:56:11 +02:00
Daniele Alessandri bc040fae6f Change handling of unsupported methods in Predis\Network\WebdisConnection. 2011-06-08 21:53:54 +02:00
Daniele Alessandri e7d2717ee1 Switch from pecl_http to the cURL extension to make requests against Webdis.
The cURL extension is easily found already packaged for various Linux
distributions, it provides everything needed and it seems to have a lower
overhead compared to pecl_http.
2011-06-08 21:43:23 +02:00
Daniele Alessandri 0de4af07dd Fix wrong serialization for commands that do not have arguments. 2011-06-06 12:49:38 +02:00
Daniele Alessandri ff7812282e Slightly change how HTTP options are initialized and handled. 2011-06-06 12:18:37 +02:00
Daniele Alessandri e5a85dfce8 Add support for HTTP basic access authentication.
With Webdis it is possible to define some access control rules to allow or
disallow certain commands and one of the possible configurations is based on
plain old HTTP authentication.
2011-06-05 22:24:03 +02:00
Daniele Alessandri 4b3ba03a3e Disallow certain commands that are disabled or do not make sense with Webdis. 2011-06-05 21:43:55 +02:00
Daniele Alessandri 776501b31a Use a faster approach to serialize the POST data for HTTP requests to Webdis. 2011-06-05 21:01:15 +02:00
Daniele Alessandri 2c8d256bdc Reimport Predis\Network\WebdisConnection with updates.
I could have rebased the previous branch with master, but since it was only a
single file and its history was basically meaningless I preferred to start
from scratch.
2011-06-05 18:46:16 +02:00
Daniele Alessandri 0195a7488a Fix a bug in Predis\Network\StreamConnection::writeBytes().
When PHP's fwrite() ends up writing only a part of $buffer over the network,
this method attempts to automatically write the rest of $buffer. Due to this
bug, the data being already sent to the server was not discarded from $buffer.
Usually fwrite() writes the whole $buffer in one go, but anyway this bug would
not have passed unnoticed since it results in malformed requests and Redis
would have surely returned a -ERR reply.
2011-06-05 17:05:04 +02:00
Daniele Alessandri a8e063e855 Minor updates to README. 2011-06-05 10:19:02 +02:00
Daniele Alessandri 2cdcd297f0 Rename Predis\Client::pubSubContext() to Predis\Client::pubSub(). 2011-06-04 18:47:59 +02:00
Daniele Alessandri 65c0336d2f Use the shared initializer to initialize Pub/Sub and accept callbacks.
When a callback is specified, the client does not return a new instance
of Predis\PubSubContext but it invokes that callback on each message
received. The context can be aborted simply by returning FALSE from the
callback.
2011-06-04 18:41:38 +02:00
Daniele Alessandri 8c207f71bd Removing leftovers. 2011-06-04 17:12:24 +02:00
Daniele Alessandri 42f4663050 Move Predis\ConnectionException to Predis\Network\ConnectionException. 2011-06-04 16:00:35 +02:00
Daniele Alessandri 3801928e0d Move Predis\ProtocolException to Predis\Protocol\ProtocolException. 2011-06-04 15:53:31 +02:00
Daniele Alessandri d59556cae1 Rename the Predis\Protocols namespace to Predis\Protocol. 2011-06-04 15:45:01 +02:00
Daniele Alessandri 667ce97213 Remove a useless return statement. 2011-06-04 15:27:36 +02:00
Daniele Alessandri 101fffbabe Do not check for the existence of a UNIX domain socket file in userland.
Now Predis throws an instance of Predis\ConnectionException when trying to
connect to an instance of Redis on a non-existent UNIX domain socket file.
2011-06-04 15:19:06 +02:00
Daniele Alessandri b35dcd515b Change the code layout of private/protected fields. 2011-06-02 23:49:46 +02:00
Daniele Alessandri df0943120e Add a fire-and-forget executor for pipelines. 2011-06-02 23:44:49 +02:00
Daniele Alessandri b72b12c5cd Fix wrong exception being thrown on invalid instance types passed to 'executor'. 2011-06-02 23:41:12 +02:00
Daniele Alessandri 3f2814c254 Change the code layout of private/protected fields. 2011-06-02 18:53:53 +02:00
Daniele Alessandri 1bd4a25e36 Remove code comments in the exception classes. Descriptions will be added again later with proper documentation. 2011-06-02 18:43:52 +02:00
Daniele Alessandri 24aaa2ac23 Nothing relevant, just reorganizing some private members. 2011-06-02 17:52:22 +02:00
Daniele Alessandri ba4ebb3799 Make the specialized pipeline and transaction initializer methods of Predis\Client protected. 2011-06-02 17:37:33 +02:00
Daniele Alessandri 087b8b0b2b Pass a transaction instance as the first argument of Predis\Transaction\AbortedMultiExecException. 2011-06-02 17:34:06 +02:00
Daniele Alessandri b3910466c9 Clean up a bit the private transaction initializer method of Predis\Client. 2011-06-02 17:25:04 +02:00
Daniele Alessandri 6ad73c782a Move classes related to MULTI/EXEC abstraction to the Predis\Transaction namespace. 2011-06-02 17:20:18 +02:00
Daniele Alessandri fee3866f54 Make it possible to pipeline instances of Predis\Command\ICommand directly. 2011-06-02 16:53:16 +02:00
Daniele Alessandri dfad0d3d24 Rename private variables. 2011-06-02 16:44:52 +02:00
Daniele Alessandri 1ba1408d39 Move the handling of pipeline options inside the pipeline class. 2011-06-02 16:41:17 +02:00
Daniele Alessandri e048ac2d51 Move the PipelineContext class in the Predis\Pipeline namespace. 2011-06-02 16:03:33 +02:00
Daniele Alessandri fb3088b4d3 Redis 2.4 has now its server profile (but it's not the default one yet). The development profile is now Redis 2.6. 2011-05-31 22:01:15 +02:00
Daniele Alessandri 962037321a Make ZADD and ZREM variadic commands for Redis 2.4. 2011-05-31 21:28:37 +02:00
Daniele Alessandri 42521f2558 Do not use new classes for variadic RPUSH, LPUSH, SADD, SREM and HDEL in the 2.4 profile. 2011-05-31 21:26:04 +02:00
Daniele Alessandri 2012963ed0 Add the Predis\IReplyObject interface (used to mark returned objects that must skip reply parsing). 2011-05-21 11:04:15 +02:00
Daniele Alessandri deeb58644a Fix missing change that should have been part of commit cc2349c. 2011-05-21 10:50:42 +02:00
Daniele Alessandri 9f05f50899 Why not using markdown when the FAQ is actually a markdown file? 2011-05-19 12:46:55 +02:00
Daniele Alessandri fd97cd1bad Update the FAQ with details on the missing support for transparent (de)serialization of values. 2011-05-19 12:44:47 +02:00
Daniele Alessandri cc2349c785 Change how error messages for server-side errors are handled. 2011-05-14 10:34:22 +02:00
Daniele Alessandri 8efe76ad60 Make Predis\Commands\ServerEvalSHA inherited from Predis\Commands\ServerEval. 2011-05-13 21:36:25 +02:00
Daniele Alessandri 2010774b68 New command: EVALSHA (Redis v2.4-dev). 2011-05-13 21:23:02 +02:00
Daniele Alessandri 909b06e805 Add support for transparent key prefixing to EVAL and the Predis\Commands\ScriptedCommand class. 2011-05-13 20:22:06 +02:00
Daniele Alessandri 13ac03e134 Merge branch 'redis_scripting' 2011-05-13 20:06:34 +02:00
Daniele Alessandri 092b822033 Add an example for server-side scripting with Lua using Predis abstractions. 2011-05-13 20:06:06 +02:00
Daniele Alessandri 0e0cd865e7 Change the default value for the number of arguments used to populate KEYS. 2011-05-13 19:55:24 +02:00
Daniele Alessandri 228a2ceb2e Update TODO. 2011-05-13 12:58:42 +02:00
Daniele Alessandri b688beaff7 Update FAQ for performance numbers. 2011-05-13 12:58:16 +02:00
Daniele Alessandri 51e0d61833 Update README. 2011-05-13 08:54:28 +02:00
Daniele Alessandri 6e6a28a9f0 Reduce method calls by one when creating a new connection in Predis\Client. 2011-05-07 11:33:33 +02:00
Daniele Alessandri 486225111d Allow developers to define connections with Predis\ConnectionFactory using callable objects. 2011-05-07 10:54:22 +02:00
Daniele Alessandri cd8b3535ef Simplify Predis\ConnectionFactory. 2011-05-07 10:49:32 +02:00
Daniele Alessandri 984fd06c77 Fix check for unsupported parameters in Predis\Network\PhpiredisConnection. 2011-05-07 09:29:50 +02:00
Daniele Alessandri b087b9814d Remove a useless method from the cluster option class. 2011-05-06 16:32:39 +02:00
Daniele Alessandri 4d1dcdb280 Change type check order for client options. 2011-05-06 15:39:22 +02:00
Daniele Alessandri 893618c985 Initialize client options in a lazy way. 2011-05-06 15:20:40 +02:00
Daniele Alessandri 0255261cd5 Whoops, forgot to add Predis\Options\ClientCluster to the repository. 2011-05-05 18:43:08 +02:00
Daniele Alessandri 5f0799ab65 Predis\Commands\Command::filterArguments() is protected. 2011-05-05 17:30:05 +02:00
Daniele Alessandri e97e13bde5 Add the 'prefix' client option. The client will automatically prepend the specified prefix string to each key. 2011-05-05 17:16:14 +02:00
Daniele Alessandri 46db0409a1 Merge branch 'command_processor' 2011-05-05 16:31:55 +02:00
Daniele Alessandri cb363b52f6 Update examples. 2011-05-05 16:24:46 +02:00
Daniele Alessandri 724543a4e6 Rename Predis\Network\ConnectionCluster to Predis\Network\PredisCluster. 2011-05-05 15:55:24 +02:00
Daniele Alessandri 150795f999 Remove the key_distribution option and allow user-defined callbacks to initialize a cluster connection. 2011-05-05 15:06:00 +02:00
Daniele Alessandri 9b4a915a52 Dynamically check for the presence of the WITHSCORE modifier with the ZRANGE family of commands. 2011-05-04 22:44:37 +02:00
Daniele Alessandri b47a3f9ab8 Implement Predis\Commands\Command::setRawArguments(). 2011-05-04 18:52:26 +02:00
Daniele Alessandri 5a80876c64 Handle key prefixing in a more consistent way, and make it a first-class citizen in Predis. 2011-05-04 18:06:40 +02:00
Daniele Alessandri b5ebf48318 Make command processors accept only instances of Predis\Commands\ICommand. 2011-05-04 13:06:57 +02:00
Daniele Alessandri 09b5d7ac61 Change Predis\Commands\Preprocessors to Predis\Command\Processors. 2011-05-04 11:23:31 +02:00
Daniele Alessandri 812d37b2d4 Fix typo. 2011-05-04 00:13:53 +02:00
Daniele Alessandri 859ee35c68 Expose two methods to retrieve the standard prefixing strategies used for commands accepting single or multiple keys. 2011-05-03 21:59:43 +02:00
Daniele Alessandri ca22208ce8 Define a default value for the number of values used to populate KEYS. 2011-05-03 18:00:30 +02:00
Daniele Alessandri a386263d84 Add an helper method to get the actual keys from the whole argument list. 2011-05-03 17:37:39 +02:00
Daniele Alessandri 2bdfed5071 Add an abstraction for a virtual command that leverages Redis scripting with the new EVAL command. 2011-05-03 15:14:51 +02:00
Daniele Alessandri bd027341be New command: EVAL (Redis v2.4-dev). 2011-05-03 15:07:56 +02:00
Daniele Alessandri 4fc87fa161 Update README. 2011-05-03 14:31:35 +02:00
Daniele Alessandri be1f0914b1 Update README's markdown code to show nice colors on GitHub. 2011-04-26 08:26:22 +02:00
Daniele Alessandri 804a5d95fb Merged pull request #28 from udat/110425-fixes.
A few fixes
2011-04-25 15:02:28 -07:00
Artur Kotyrba 650d6a07e0 Fixed method and class name 2011-04-25 23:39:05 +02:00
Artur Kotyrba d4694da487 Added missing use statements 2011-04-25 23:37:00 +02:00
Artur Kotyrba 7e4b367a1d Removed unused argument for constructor of SafeExecutor and SafeClusterExecutor 2011-04-25 23:36:30 +02:00
Daniele Alessandri 19b703588b Add an example for Predis\DispatcherLoop. 2011-04-25 14:39:29 +02:00
Daniele Alessandri b5a1ba9795 Minor code and formatting changes for the example files. 2011-04-25 14:22:34 +02:00
Daniele Alessandri 21372bef6d Add an example for Predis\MonitorContext. 2011-04-25 14:17:24 +02:00
Daniele Alessandri e507198cc3 Do not populate the 'arguments' property if commands received with MONITOR do not carry an argument list. 2011-04-25 14:16:12 +02:00
Daniele Alessandri 88a9f509b4 Fix database handling in Predis\MonitorContext. 2011-04-25 14:14:01 +02:00
Daniele Alessandri b2575bd667 Reorganize some Redis commands classes. 2011-04-25 12:39:21 +02:00
Daniele Alessandri 86edc50ac4 Rename Predis\ConnectionParameters::setByUser(). 2011-04-25 09:49:38 +02:00
Daniele Alessandri dac0104267 Move the reducer function in Predis\Commands\Command::__toString() to a protected method. 2011-04-25 09:48:39 +02:00
Daniele Alessandri f7a3388865 Adjust formatting of Predis\Profiles\ServerVersionNext. 2011-04-25 09:42:07 +02:00
Daniele Alessandri 7b4da3cd78 Use variadic SUBSCRIBE in the PubSub example. 2011-04-24 14:11:34 +02:00
Daniele Alessandri 6dd3565c67 Reuse code. 2011-04-24 14:10:53 +02:00
Daniele Alessandri 3ca4645231 Implement Predis\DispatcherLoop on top of Predis\PubSubContext. 2011-04-24 13:57:19 +02:00
Daniele Alessandri c07c610a0d Implement Predis\MonitorContext as an abstraction for the MONITOR command. 2011-04-24 13:16:16 +02:00
Daniele Alessandri 880d2d24b9 Add the ability to get a connection out of a cluster using a key. 2011-04-24 11:13:33 +02:00
Daniele Alessandri 4ef8948b5e Move the key-tag extractor method to Predis\Helpers. 2011-04-24 11:04:17 +02:00
Daniele Alessandri b396eb3c48 Remove code from the test for SLAVEOF. 2011-04-24 10:03:23 +02:00
Daniele Alessandri b4a90df812 Reuse code. 2011-04-24 09:59:01 +02:00
Daniele Alessandri dd3faa3d53 New command: CLIENT (Redis v2.4-dev). 2011-04-24 09:32:47 +02:00
Daniele Alessandri 819f3ca6ed Implement variadic SREM in the development profile (Redis v2.4). 2011-04-24 09:06:23 +02:00
Daniele Alessandri 8787930977 Implement variadic HDEL in the development profile (Redis v2.4). 2011-04-19 20:49:30 +02:00
Daniele Alessandri a8705b9535 Implement variadic SADD in the development profile (Redis v2.4). 2011-04-19 20:42:50 +02:00
Daniele Alessandri 66f6610c72 Implement variadic RPUSH and LPUSH in the development profile (Redis v2.4). 2011-04-19 20:35:48 +02:00
Daniele Alessandri 9bc50e321e The stable version of Redis will be 2.4. 2011-04-19 20:04:37 +02:00
Daniele Alessandri 4af1b7744c Implement an option to specify which cluster class to use. 2011-04-12 15:42:37 +02:00
Daniele Alessandri cbc7929f6e Move the logic of the connection factory option to a dedicated class. 2011-04-12 14:45:28 +02:00
Daniele Alessandri 1a175da7ca Predis\ConnectionParameters::__isset() should check if a parameters has been set and its value is not null. 2011-04-12 13:01:22 +02:00
Daniele Alessandri f6eab6ec3a Just a minor code styling change. 2011-04-11 23:43:49 +02:00
Daniele Alessandri 07d9717f8a Fix wrong import with the 'use' directive. 2011-04-11 23:23:55 +02:00
Daniele Alessandri 3f3c235363 Make Predis\Distribution\IDistributionStrategy extend the new Predis\Distribution\INodeKeyGenerator interface. 2011-04-11 23:20:10 +02:00
Daniele Alessandri a348e32144 Improve Predis\Client::getConnection() internals. 2011-04-11 18:53:02 +02:00
Daniele Alessandri 55899e7741 Check for null client options in the filter method. 2011-04-11 18:21:05 +02:00
Daniele Alessandri d1157a506d Remove useless code. 2011-04-11 18:21:01 +02:00
Daniele Alessandri bea8a3239d Remove default null value from Predis\Client::initializeConnection(). 2011-04-11 17:01:26 +02:00
Daniele Alessandri 839ce08487 Mostly aesthetic changes for Predis\PubSubContext. 2011-04-11 16:19:22 +02:00
Daniele Alessandri 944a478272 Remove Predis\Commands\Command::setArguments(). 2011-04-09 09:35:28 +02:00
Daniele Alessandri 83bab78bd1 Rename the newConnection() method to create() in Predis\ConnectionFactory. 2011-04-08 16:55:08 +02:00
Daniele Alessandri b22cb6f76d Rename Predis\IConnectionSchemes to Predis\IConnectionFactory. 2011-04-08 16:40:25 +02:00
Daniele Alessandri 5527fc34e7 Split the FAQ file. 2011-04-08 15:23:23 +02:00
Daniele Alessandri 7979d9ab64 Update TODO. 2011-04-08 11:23:02 +02:00
Daniele Alessandri 0396320951 Merge branch 'command_preprocessors' 2011-04-08 11:22:24 +02:00
Daniele Alessandri 20ce6e523a Add an example to show how to leverage key prefixes. 2011-04-08 11:16:06 +02:00
Daniele Alessandri 44d4c77918 Merge branch 'protocols' 2011-04-07 10:34:46 +02:00
Daniele Alessandri 65fc4f7d55 Rename to Predis\Protocols\IComposableProtocolProcessor. 2011-04-07 10:34:30 +02:00
Daniele Alessandri 6e2bba3ddb Move the definition of the OBJECT commad to the server profile for Redis 2.2. 2011-04-06 18:51:52 +02:00
Daniele Alessandri 2a47dc8275 Update TODO. 2011-04-06 18:32:52 +02:00
Daniele Alessandri 9340b3ddce Partially rewrite the shared abstraction initializer method of Predis\Client. 2011-04-06 18:31:53 +02:00
Daniele Alessandri db95350c37 Reorganize the Predis\Protocols namespace. 2011-04-06 17:52:39 +02:00
Daniele Alessandri 80f1cedf79 Add the OBJECT command to the dev server profile. 2011-04-06 12:49:54 +02:00
Daniele Alessandri 33f6419700 Invoke preprocessors after checking if a command is defined by the current profile. 2011-04-05 21:38:49 +02:00
Daniele Alessandri 771a0ee179 Pass method names to preprocessors by value. 2011-04-05 21:34:05 +02:00
Daniele Alessandri 1d9b53d443 Rename class to Predis\Commands\Preprocessors\KeyPrefixPreprocessor. 2011-04-05 20:46:40 +02:00
Daniele Alessandri 86df741937 Rename Predis\Utils to Predis\Helpers. 2011-04-05 16:37:36 +02:00
Daniele Alessandri 4ea8489110 Differentiate communication exceptions between connection and protocol exceptions. 2011-04-05 15:59:21 +02:00
Daniele Alessandri ae96b0f39f Actually implement preprocessor removal from a preprocessor chain. 2011-04-05 13:07:11 +02:00
Daniele Alessandri 1ee7926673 Check values passed to PreprocessorChain::offsetSet(). 2011-04-05 12:37:11 +02:00
Daniele Alessandri b5d748156e Implement a class to chain multiple command preprocessors. 2011-04-05 12:31:00 +02:00
Daniele Alessandri 5e05febf33 Implement a namespacing preprocessor to prefix Redis keys transparently. 2011-04-05 11:57:37 +02:00
Daniele Alessandri 07b4238ce7 Add an abstraction to optionally preprocess command arguments. 2011-04-05 11:56:36 +02:00
Daniele Alessandri c0d9b53ff7 Fix mistakes in the FAQ. 2011-04-04 17:17:33 +02:00
Daniele Alessandri 9954bd5a12 Share more code between connection classes. 2011-04-04 17:17:14 +02:00
Daniele Alessandri 4b25c41f78 Update FAQ. 2011-04-04 15:57:37 +02:00
Daniele Alessandri ac471eeff3 Rename and simplify Predis\Profiles\ServerProfile::registerProfile(). 2011-04-04 15:31:01 +02:00
Daniele Alessandri da2cd3ee7e Simplify Predis\Profiles\ServerProfile::defineCommand(). 2011-04-04 15:03:14 +02:00
Daniele Alessandri bfa9cc7469 Fix FAQ (3300 is actually 3200, just a typo). 2011-04-04 12:17:20 +02:00
Daniele Alessandri 87a1f43487 More updates for the performance numbers in the FAQ. 2011-04-04 12:14:19 +02:00
Daniele Alessandri 556f7b0ec2 Update the average numbers reported in the FAQ after the recent optimizations. 2011-04-04 12:05:35 +02:00
Daniele Alessandri 7146a32f6d Fix the phpiredis-based connection class. 2011-04-04 11:57:47 +02:00
Daniele Alessandri 595692d50f Minor fixes and adjustments to pipeline executors. 2011-04-04 11:42:52 +02:00
Daniele Alessandri c2a61a3113 Rename Predis\CommandPipeline to Predis\PipelineContext. 2011-04-04 11:31:26 +02:00
Daniele Alessandri 27d56a7ac9 Methods for defining commands at runtime should not be enforced in the Predis\Profiles\IServerProfile interface. 2011-04-04 11:23:38 +02:00
Daniele Alessandri 4c84eb181b Minor changes for Predis\Network\StreamConnection. 2011-04-04 11:20:12 +02:00
Daniele Alessandri 503cc86f7d Move method to the base Predis\Network\ConnectionBase class. 2011-04-04 10:37:53 +02:00
Daniele Alessandri 8300b1d63c Fix parameter validation and use a slightly optimized approach. 2011-04-03 13:42:42 +02:00
Daniele Alessandri 62b4e52eef Update TODO. 2011-04-03 12:20:01 +02:00
Daniele Alessandri 8a2f53059a Make Predis\ConnectionParameters::__construct() faster. 2011-04-03 11:36:28 +02:00
Daniele Alessandri c2097b4242 Add .gitignore file. 2011-04-03 11:10:12 +02:00
Daniele Alessandri 6f51521f81 Rename test file. 2011-04-03 10:55:27 +02:00
Daniele Alessandri 609db5159e Remove Predis\ComposableConnectionParameters (superseeded by Predis\ConnectionParameters). 2011-04-03 10:47:37 +02:00
Daniele Alessandri 5ab210fd9d Allow users to undefine a default parameter. 2011-04-03 10:45:47 +02:00
Daniele Alessandri 6fe57bae3f Implement support for using Predis\Options\IOption with Predis\ConnectionParameters. 2011-04-03 10:38:02 +02:00
Daniele Alessandri 9c0012837a Return the path of the file as the identifier for connections based on UNIX domain sockets. 2011-04-03 10:12:28 +02:00
Daniele Alessandri 741495037e Make Predis\ConnectionParameters extensible. 2011-04-03 09:59:54 +02:00
Daniele Alessandri 9d5dc120dc Implement serialization/deserialization for Predis\ConnectionParameters. 2011-04-03 09:32:07 +02:00
Daniele Alessandri 74f6f9ab85 Small refactoring of the internals of Predis\ConnectionParameters. 2011-04-03 09:26:53 +02:00
Daniele Alessandri 0d6ffaf0f0 Minor fixes to the connection parameters classes. 2011-04-01 00:35:02 +02:00
Daniele Alessandri 9389f217c8 Reimplement Predis\ConnectionParameters and move the old implementation to Predis\ComposableConnectionParameters. 2011-03-31 19:13:27 +02:00
Daniele Alessandri 3f720ad867 Add the new Predis\IConnectionParameters interface. 2011-03-31 15:12:52 +02:00
Daniele Alessandri 17f51420ce Improve speed for options validation. 2011-03-31 14:29:06 +02:00
Daniele Alessandri 3d9ddeef98 Opt for a smaller and slightly more efficient solution. 2011-03-31 00:17:11 +02:00
Daniele Alessandri 85c1a7a852 Fix ISSUE #27. 2011-03-30 23:24:45 +02:00
Daniele Alessandri 094a5bcc90 Fix wrong command class for KEYS in the v2.2 server profile. 2011-03-29 00:14:54 +02:00
Daniele Alessandri f637872421 Keeping the server profiles classes independent leads to faster initialization times. 2011-03-28 23:56:31 +02:00
Daniele Alessandri de1a183315 Do some micro-optimizations to reduce the overhead of creating client instances. 2011-03-28 23:25:37 +02:00
Daniele Alessandri ab45b7a461 Fix wrong value :-) 2011-03-28 18:22:54 +02:00
Daniele Alessandri 2ed31eeb16 Update the average performance reported in the FAQ after some internal improvements. 2011-03-28 12:47:46 +02:00
Daniele Alessandri 3b70d1e020 Change code formatting for the classes in the Predis\Commands namespace. 2011-03-27 19:46:02 +02:00
Daniele Alessandri 2201dd1df2 Merge branch 'command_hashing' 2011-03-27 18:50:55 +02:00
Daniele Alessandri 658782f531 Add a script to generate a Phar archive of Predis from the repository. 2011-03-27 15:01:51 +02:00
Daniele Alessandri c4064e5801 Some commands accepting multiple keys can be hashed if all the keys return the same hash (key tags).
List of the commands affected by this change (based on Redis 2.2):
    MSET, MGET, DEL, BLPOP, BRPOP, RPOPLPUSH, BRPOPLPUSH, SINTER, SINTERSTORE,
    SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, ZINTERSTORE, ZUNIONSTORE.
2011-03-27 12:12:51 +02:00
Daniele Alessandri d6a445f1ec Fix SINTERSTORE and SUNIONSTORE to accept an array for the list of source keys. 2011-03-27 09:38:30 +02:00
Daniele Alessandri 0f751cabcb Upgrade to PHPUnit 3.5. 2011-03-27 09:15:38 +02:00
Daniele Alessandri b007b753f5 Fix SUBSCRIBE and PSUBSCRIBE so that they can accept a list of channels for subscription. 2011-03-26 22:45:52 +01:00
Daniele Alessandri b84c84007f Remove Predis\ICommand::canBeHashed() as a public method required for command classes and reuse it internally to Predis\Command. 2011-03-24 00:43:02 +01:00
Daniele Alessandri 4e0e1908cd Minor speed optimizations. 2011-03-23 23:27:05 +01:00
Daniele Alessandri 930a1096e1 Refactor the key hashing logic for Redis commands. 2011-03-23 22:58:49 +01:00
Daniele Alessandri cdfd0b9f5c Fix more problems of Predis\MultiExecContext on certain cases. 2011-03-20 15:27:59 +01:00
Daniele Alessandri cb1f27a403 Update TODO. 2011-03-20 12:08:34 +01:00
Daniele Alessandri e4c45455fe Fix a couple of corner cases for Predis\MultiExecContext. 2011-03-20 10:47:57 +01:00
Daniele Alessandri ceca866158 Remove Predis\Network\IConnectionSingle::setProtocolOption() for now. 2011-03-20 10:47:30 +01:00
Daniele Alessandri 665e428366 Give up on some core reusing practices in favor of execution speed and memory usage. 2011-03-20 10:07:40 +01:00
Daniele Alessandri 31e068796f Update FAQ. 2011-03-18 23:19:25 +01:00
Daniele Alessandri e84844e33c Reimplement Predis\Options\CustomOption to implement directly the Predis\Options\IOption interface. 2011-03-18 22:25:45 +01:00
Daniele Alessandri 21ac9b06f5 Do not validate default option values, assume that default values are correct. 2011-03-18 22:01:50 +01:00
Daniele Alessandri e5ff0ab992 Remove the 'on_connection_initialized' client option (useless in the vast majority of cases). 2011-03-18 21:47:52 +01:00
Daniele Alessandri 743feb0634 Optimize Predis\ClientOptions. 2011-03-18 21:38:37 +01:00
Daniele Alessandri afd78b49a6 Update README and samples. 2011-03-18 15:45:27 +01:00
Daniele Alessandri 94d0805cf6 Apply minor change. 2011-03-18 15:13:52 +01:00
Daniele Alessandri 15af329aa3 Add a new option to specify different connection schemes handlers on a client-instance level. 2011-03-18 15:04:06 +01:00
Daniele Alessandri a10a8e3c9b Clean up code before fast-forwarding the master branch. 2011-03-12 15:56:22 +01:00
Daniele Alessandri 3181f6c592 Remove useless code. 2011-03-12 15:26:39 +01:00
Daniele Alessandri b11ab53bb1 Implement new various changes. 2011-03-11 19:07:46 +01:00
Daniele Alessandri 82759cd6ec Change how parameters are handled internally. 2011-03-10 16:30:00 +01:00
Daniele Alessandri b5a89a0f50 Add a VERSION constant to Predis\Client. 2011-03-08 11:03:32 +01:00
Daniele Alessandri 2853214ddc Update FAQ. 2011-03-08 10:57:06 +01:00
Daniele Alessandri e5e7933aef Add missing file extension. 2011-03-07 19:01:39 +01:00
Daniele Alessandri a81f76d376 Add a FAQ file (it will also be used in the wiki). 2011-03-07 18:59:54 +01:00
Daniele Alessandri 9b17352d9c Transit from UNSTABLE to BETA. 2011-03-07 11:23:26 +01:00
Daniele Alessandri 14d4492ad6 Slight change, nothing serious here. 2011-03-07 11:12:20 +01:00
Daniele Alessandri 995de40734 Fix Predis\Network\PhpiredisConnection. 2011-03-06 16:20:37 +01:00
Daniele Alessandri 190b687789 Change how network resources are handled internally and also exposed to subclasses. 2011-03-06 14:45:59 +01:00
Daniele Alessandri e94fbc3287 Adjust the tests for SUBSTR/GETRANGE since the return value for empty string slices has been fixed in Redis 2.2.2. 2011-03-06 12:45:23 +01:00
Daniele Alessandri 826db07900 Force the test suite to use the 2.2 server profile for now. 2011-03-06 12:39:18 +01:00
Daniele Alessandri be4d01c071 Remove a useless method declaration. 2011-03-06 12:32:43 +01:00
Daniele Alessandri 74b6d05b48 Move the database info parsing bits for the reply to INFO in a separate function. 2011-03-06 12:24:51 +01:00
Daniele Alessandri 58eb4e2477 Make the reply parser for INFO < 2.4 somewhat backwards compatible when used against Redis >= 2.4. 2011-03-06 12:22:22 +01:00
Daniele Alessandri 3186da49b4 Parse allocation_stats if present in the INFO reply. 2011-03-06 12:14:19 +01:00
Daniele Alessandri 3f8b639e2b Change StreamConnection in order to disable read/write timeouts when the value of 'read_write_timeout' is also equal to 0. 2011-03-06 11:03:53 +01:00
Daniele Alessandri 6ce35c97e9 Update README. 2011-03-06 10:08:35 +01:00
Daniele Alessandri b03e6c4f02 Make CommandPipeline::recordCommand() overridable by subclasses. 2011-03-06 10:05:46 +01:00
Daniele Alessandri 7bef3abf91 Change the code for the initialization of the phpiredis reader resource. 2011-03-06 09:55:22 +01:00
Daniele Alessandri 3b4ef4f33e Update README. 2011-03-05 18:42:52 +01:00
Daniele Alessandri f668560a5a Implement ConnectionParameters::__toString(). 2011-03-05 16:36:34 +01:00
Daniele Alessandri 6c9b246b2b Implement a new command class for INFO to parse the new reply format for this command in Redis > 2.2. 2011-03-05 15:47:54 +01:00
Daniele Alessandri 878b338e87 Fix comment. 2011-03-05 12:27:02 +01:00
Daniele Alessandri 38e76cbbc8 Allow passing an array for the list of source keys to be used in ZUNIONSTORE/ZINTERSTORE. 2011-03-05 11:56:10 +01:00
Daniele Alessandri f8844ef8b8 Rename IServerProfile::registerCommand() to IServerProfile::defineCommand(). 2011-03-05 10:52:38 +01:00
Daniele Alessandri 3681c1e622 Clustered connections should use IConnectionSingle::executeCommand() to execute commands internally. 2011-03-05 10:52:31 +01:00
Daniele Alessandri 99c8acfc8c Clean up leftovers. 2011-03-04 19:38:47 +01:00
Daniele Alessandri 30bc53ee75 Rename method ICommand::getCommandId() to ICommand::getId(). 2011-03-04 19:37:10 +01:00
Daniele Alessandri 0d5fb3319d Move Predis\Command and Predis\ICommand to the Predis\Commands namespace. 2011-03-04 19:21:41 +01:00
Daniele Alessandri c3ce210150 Remove a useless 'use' directive. 2011-03-04 18:56:20 +01:00
Daniele Alessandri 8b749386df Implement Predis\Command::__toString(). 2011-03-04 17:17:49 +01:00
Daniele Alessandri 6abac4590d Rename protocol interfaces. 2011-03-04 17:00:23 +01:00
Daniele Alessandri a627b91be1 Fix some more namespacing issues. 2011-03-04 16:18:27 +01:00
Daniele Alessandri 5077996940 Add the ability to create new connections using uri strings, array of parameters or instances of Predis\ConnectionParameters. 2011-03-04 16:06:38 +01:00
Daniele Alessandri db807e7a91 Do not fail on undefined client options properties. 2011-03-04 15:42:45 +01:00
Daniele Alessandri 3021cbd76b Fix wrong name for private field. 2011-03-04 15:12:02 +01:00
Daniele Alessandri 2c4a9e92a6 Add the ability to define custom handlers for client options and connection parameters. 2011-03-04 15:10:43 +01:00
Daniele Alessandri d077aa67db Remove since it generates overhead for nothing really useful. 2011-03-04 13:05:28 +01:00
Daniele Alessandri 0af002b3b9 Update README. 2011-03-04 12:50:12 +01:00
Daniele Alessandri a3218721c1 Merge branch 'phpiredis_new_api' 2011-03-04 12:04:51 +01:00
Daniele Alessandri 21c959a451 Fix namespacing issues with Predis\ClientException. 2011-03-04 11:58:07 +01:00
Daniele Alessandri ba9c3ed3db Fix README. 2011-03-02 17:58:06 +01:00
Daniele Alessandri eba7f84335 Fix the validation of default values for Predis\Options\Option class. 2011-03-02 17:44:10 +01:00
Daniele Alessandri 1e1a904d1a Update the client features test suite (still needs more test coverage of the whole API). 2011-03-02 17:40:27 +01:00
Daniele Alessandri 33ffca23a0 Check if the socket extension is loaded. 2011-03-02 15:16:49 +01:00
Daniele Alessandri 6fada0c35c Add some notes. 2011-03-02 15:00:52 +01:00
Daniele Alessandri 99129fbf91 Implement a new Predis\Network\PhpiredisConnection class that internally uses phpiredis. 2011-03-02 12:28:42 +01:00
Daniele Alessandri 5431af0c4b Update examples to the new connection API design. 2011-03-02 10:11:58 +01:00
Daniele Alessandri 89c311d0de Complete redesign of the network connection API, it should make much more sense now. 2011-03-02 10:02:29 +01:00
Daniele Alessandri fda4f32f06 Rename server profile classes to comply with how underscores are interpreted in the PSR-0 standard. 2011-02-27 13:37:03 +01:00
Daniele Alessandri 9fcdc73499 Fix a couple of namespacing issues with client exceptions in connection classes (ISSUE #24). 2011-02-26 23:19:13 +01:00
Daniele Alessandri ba4dc10936 Update README. 2011-02-26 23:06:25 +01:00
Daniele Alessandri aec3fcf3e8 Add a script to recreate a single PHP file from the repository. 2011-02-26 22:52:40 +01:00
Daniele Alessandri 1746948d61 Fix README (this is the last time). 2011-02-25 14:54:28 +01:00
Daniele Alessandri d05007b5db Fix README (again). 2011-02-25 14:51:16 +01:00
Daniele Alessandri fa08ff1b18 Fix README. 2011-02-25 14:49:53 +01:00
Daniele Alessandri 9e0f0078ea Rename test file. 2011-02-25 14:47:10 +01:00
Daniele Alessandri 4ad4b9cf77 Remove direct requires of parts of PHPUnit. 2011-02-25 12:45:11 +01:00
Daniele Alessandri d2b0326087 Fix requiring path of bootstrap.php in external processes spawned by tests. 2011-02-25 12:39:05 +01:00
Daniele Alessandri 9f58d8a663 Register an autoloader function for examples. 2011-02-25 12:09:45 +01:00
Daniele Alessandri c6b8336346 Update README and remove references to the PHP 5.2 backport for the current version. 2011-02-25 12:06:54 +01:00
Jordi Boggiano ac1e6e1846 Fix tests for latest changes, added phpunit.xml.dist file and autoloader in test/bootstrap.php 2011-02-21 14:18:04 +01:00
Jordi Boggiano 30f908cd85 Convert monolithic one-file-lib to a proper PSR-0 file tree 2011-02-21 14:17:57 +01:00
Daniele Alessandri 2a78142b28 Remove comment, code will remain as-is for performance reasons. 2011-02-16 11:24:08 +01:00
Daniele Alessandri 978d7087d5 Minor formatting change. 2011-02-16 11:22:09 +01:00
Daniele Alessandri 97439a7e08 Update UNSTABLE. 2011-02-16 11:14:41 +01:00
Daniele Alessandri 5a25cf33be Fix after incomplete rename of private fields. 2011-02-15 22:42:18 +01:00
Daniele Alessandri 237f3e3d7e Rename the 'throw_on_error' client option to 'throw_errors'. 2011-02-15 18:24:38 +01:00
Daniele Alessandri 784b33358d Check for null values when setting a protocol processor instance for a connection. 2011-02-15 18:05:02 +01:00
Daniele Alessandri 2b2ca8e8dc Remove trailing spaces in code. 2011-02-15 12:46:19 +01:00
Daniele Alessandri af03916369 Rename a couple of private fields. 2011-02-15 12:30:43 +01:00
Daniele Alessandri 8e4ef21b41 Update CHANGELOG. 2011-02-12 21:57:42 +01:00
Daniele Alessandri 65c530a13b Add test guard for empty bulk replies. 2011-02-12 21:22:47 +01:00
Daniele Alessandri dcafee61a8 Fix wrong method signature. 2011-02-12 21:07:27 +01:00
Jordi Boggiano c1587ccf54 Fixed bug reading zero-length values from a bulk response 2011-02-12 19:16:16 +01:00
Daniele Alessandri 44839a7a6f Minor fix in a comment. 2011-02-12 17:25:48 +01:00
Daniele Alessandri 9d6ffcc5f2 Update TODO. 2011-02-12 17:24:40 +01:00
Daniele Alessandri 679c7ffdd5 Trade a tiny bit of speed for more code reuse. 2011-02-12 16:58:31 +01:00
Daniele Alessandri 09a7a18ac0 Adapt the client features test suite to the new structure of the library. 2011-02-12 16:17:30 +01:00
Daniele Alessandri 03cff6a813 Fix wrong class lookup. 2011-02-12 16:17:00 +01:00
Daniele Alessandri f6bd5757af Repeat with me: do not blindly copy and paste. 2011-02-12 15:34:47 +01:00
Daniele Alessandri 8a145bc6c9 More reliable network writes in Predis\Protocols\TextProtocol. 2011-02-12 15:18:52 +01:00
Daniele Alessandri fc3ee47140 Definitely remove support for Redis 1.0. 2011-02-12 15:05:56 +01:00
Daniele Alessandri ddb3180700 Switch the default text protocol processor to the new and faster one. 2011-02-12 15:05:24 +01:00
Daniele Alessandri f7bef784af Add inline (p)subscribe via options on Predis\PubSubContext initialization. 2011-02-12 14:24:12 +01:00
Daniele Alessandri c5d353b754 Update CHANGELOG. 2011-02-12 14:22:51 +01:00
Daniele Alessandri fb2bc5c8e9 Bump year in LICENSE file. 2011-01-26 16:26:33 +01:00
Daniele Alessandri 68f77444b6 Use only one check for replies that should not be passed to a reply parser. 2011-01-14 17:08:45 +01:00
Daniele Alessandri b6d93b5b34 Promote the profile for Redis 2.2 as stable and use it as the default one for the client. 2011-01-13 12:30:06 +01:00
Daniele Alessandri 4e6ed1fd5b Do not use is_numeric() when it is not really needed (it is relatively slow). 2011-01-13 10:50:40 +01:00
Daniele Alessandri fc9deb68be Remove usage of constants in the protocol handlers. 2011-01-13 10:32:20 +01:00
Daniele Alessandri b47adffd4f Do not perform useless read operations in the bulk reply handler. 2011-01-13 10:28:39 +01:00
Daniele Alessandri 3d80ff489a Less lines of code please. 2011-01-12 22:49:19 +01:00
Daniele Alessandri 4705b27302 Add the 'on_retry' callback as an option for Predis\MultiExecContext. 2011-01-12 22:46:58 +01:00
Daniele Alessandri 9877e0c380 Fix once and for all the implementation of Predis\Protocols\FastTextProtocol. 2011-01-12 22:27:45 +01:00
Daniele Alessandri 92e2455189 Remove unused variables. 2011-01-12 18:39:27 +01:00
Daniele Alessandri e1d8ee5d9b Remove useless reference passing. 2011-01-12 18:38:15 +01:00
Daniele Alessandri 74145ce45c Fix server errors handling in Predis\Protocols\FastTextProtocol. 2011-01-12 18:31:54 +01:00
Daniele Alessandri 898b038f48 Do not make useless calls to fread. 2011-01-12 18:17:35 +01:00
Daniele Alessandri aacf2bc65d Make reads from the socket stream more reliable in Predis\Protocols\FastTextProtocol. 2011-01-12 18:07:09 +01:00
Daniele Alessandri 11c490e978 Minor adjustments. 2011-01-11 22:16:30 +01:00
Daniele Alessandri db2469341f Remove useless stuff. 2011-01-11 16:36:19 +01:00
Daniele Alessandri c1108c6e92 Add an optional and faster protocol processor. 2011-01-10 12:59:04 +01:00
Daniele Alessandri c9567c8606 Add an optional 'on_connection_initialized' callback to client options. 2011-01-10 12:20:52 +01:00
Daniele Alessandri 014adfe75d Remove the method Predis\Network\TcpConnection::rawCommand(). 2011-01-09 21:24:09 +01:00
Daniele Alessandri 2853ba7cef Add the ability to set a different protocol processor on connection instances. 2011-01-09 15:55:55 +01:00
Daniele Alessandri 539a4bbdcd Remove the Predis\ConnectionManager class.
The functionalities provided by that class have been merged into Predis\Client.
2011-01-09 15:42:36 +01:00
Daniele Alessandri bf3776b47a Improve initialization code of Predis\Client instances. 2011-01-09 15:05:28 +01:00
Daniele Alessandri fe0a940f18 Add the new Predis\Protocols\IRedisProtocolExtended interface. 2011-01-09 14:53:20 +01:00
Daniele Alessandri c5169694ef Remove Predis\Client::setConnection(). 2011-01-09 14:41:32 +01:00
Daniele Alessandri a992d9d0b8 Better checks for arguments passed to Predis\ConnectionParameters. 2011-01-09 14:36:48 +01:00
Daniele Alessandri c94cf5ef32 Better checks for arguments passed to Predis\Network\UnixDomainSocketConnection. 2011-01-09 14:36:10 +01:00
Daniele Alessandri 5d37ea1258 Remove useless override. 2011-01-09 14:24:13 +01:00
Daniele Alessandri 8392f465cc Cache the generated connection ID. 2011-01-09 13:43:45 +01:00
Daniele Alessandri b3e7cfe408 Make multiple explicit calls to Predis\Client::connect() possible. 2011-01-09 12:08:05 +01:00
Daniele Alessandri b013bce140 Add missing method in the Predis\Network\IConnectionCluster interface. 2011-01-09 12:01:06 +01:00
Daniele Alessandri f1488534b6 Reduce lines of code. 2011-01-09 11:58:45 +01:00
Daniele Alessandri d1282261b8 Simplify the internals of Predis\Client when initializing a connection.
Note that the options set for a Predis\Network\IConnectionSingle instance
passed to the client are not automatically overridden anymore.
2011-01-09 11:49:40 +01:00
Daniele Alessandri f1223c1a90 Simplify the signature of Predis\Client::pushInitCommands(). 2011-01-09 10:59:54 +01:00
Daniele Alessandri bcfb568d1a Add new Predis\Client::getOptions() method. 2011-01-09 10:53:52 +01:00
Daniele Alessandri 48a47aa503 Add the Predis\Profiles\IServerProfile interface. 2011-01-09 10:46:54 +01:00
Daniele Alessandri 8eb59c8852 Add missing methods to Predis\Protocols\IRedisProtocol. 2011-01-08 20:09:23 +01:00
Daniele Alessandri cd9995b972 Add missing 'use' directives. 2011-01-08 18:18:02 +01:00
Daniele Alessandri 131e4c9d03 Rewrite Predis\ConnectionParams to leverage the Predis\Options namespace. 2011-01-08 18:17:57 +01:00
Daniele Alessandri cd828ab18a Add the new Predis\Options namespace and optimize Predis\ClientOptions. 2011-01-08 17:37:53 +01:00
Daniele Alessandri 33b71a085c Remove a useless method. 2011-01-08 01:57:47 +01:00
Daniele Alessandri 48762ec876 Fix argument name mismatch. 2011-01-08 01:42:39 +01:00
Daniele Alessandri 3b2681f2c8 Move some classes in new namespaces and refactor some code. 2011-01-08 00:45:46 +01:00
Daniele Alessandri 62b8569dc8 More changes but nothing set in stone yet.
The commands test suite passes all the assertions (woot!).
2011-01-07 20:35:39 +01:00
Daniele Alessandri f4309893bc Start a major rewrite of the internals of the library.
The public API of Predis\Client will be compatible with older releases, but
many of the core internal classes are going to change.
2011-01-07 17:50:54 +01:00
Daniele Alessandri c247d6201a Update README. 2011-01-06 11:48:41 +01:00
Daniele Alessandri df268a1143 Merge branch 'pullreq_18' 2011-01-06 00:27:45 +01:00
Daniele Alessandri d04c6d2670 Remove garbage. 2011-01-06 00:25:46 +01:00
Artur Kotyrba 8a76c8c849 Remove unused private method. 2011-01-05 23:03:53 +01:00
Daniele Alessandri a7ae86689d Test suite: client initialization using an instance of Predis\IConnectionCluster. 2011-01-05 23:03:34 +01:00
Daniele Alessandri 6de7222857 Revert changes to the test suite in 6a7fc49. 2011-01-05 22:55:15 +01:00
Artur Kotyrba fb30e22c30 Added possibility to use custom connection cluster classes in Predis\Client constructor.
Added three methods (used by \Predis\Client) to IConnectionSingle interface.
2011-01-05 22:05:21 +01:00
Daniele Alessandri 2bb763dbf6 Minor code style change. 2011-01-05 12:50:33 +01:00
Daniele Alessandri afff56d2ec Look for a closing curly brace in a string only after the index of the opening one when using key tags. 2011-01-05 12:49:08 +01:00
Daniele Alessandri d717d906e8 Optimize when a pair of curly brackets for key tagging is missing. 2011-01-05 12:44:37 +01:00
Daniele Alessandri 51352bcbb3 Create a new class to handle the old response type of KEYS (Redis v1.2). 2011-01-04 21:01:29 +01:00
Daniele Alessandri 2b809325e0 Use a faster method to detect errors when reading a line from the server. 2011-01-04 11:08:55 +01:00
Daniele Alessandri 306ed28c5d Reuse code a bit. 2011-01-04 10:55:39 +01:00
Daniele Alessandri d94ad9942f Use a local cache for handlers while iterating chunks of a multi-bulk reply. 2011-01-04 10:34:56 +01:00
Daniele Alessandri dcbd943505 Reduce overhead by directly managing reply handlers for multibulk replies. 2011-01-04 10:31:34 +01:00
Daniele Alessandri b74e2c22f7 Rewrite the bulk reply handler (more compact and faster code). 2011-01-02 22:22:07 +01:00
Daniele Alessandri 48728d2672 More strict check of the length argument for a network read. 2011-01-02 22:05:27 +01:00
Daniele Alessandri e134e21b78 Remove a useless check for the payload length. 2011-01-02 21:55:28 +01:00
Daniele Alessandri f0f1647773 Use an explicit index to add values to the multi-bulk reply array. 2011-01-02 21:51:53 +01:00
Daniele Alessandri d270205a8c Nothing fancy, and hardly an optimization. 2011-01-02 21:50:14 +01:00
Daniele Alessandri a1db042d17 Avoid allocating an iterator to traverse the arguments list of a command. 2011-01-02 21:42:54 +01:00
Daniele Alessandri e645ed7d3f Preallocate an empty array for empty command arguments. 2011-01-02 21:35:43 +01:00
Daniele Alessandri 9ae69e6c51 Update CHANGELOG. 2011-01-01 19:01:34 +01:00
Daniele Alessandri 3a46f8a7c5 Update README to reflect public API changes. 2011-01-01 15:05:00 +01:00
Daniele Alessandri b202e6cae7 Make Predis\Client::setProfile() private. 2011-01-01 14:59:38 +01:00
Daniele Alessandri 5ca82fb56b Code style changes only. 2011-01-01 13:06:43 +01:00
Daniele Alessandri 1530c7c0d6 Cannot execute with a transaction block after using fluent interface style with Predis\MultiExecBlock. 2011-01-01 11:49:05 +01:00
Daniele Alessandri 11b2f3aca3 Improve fluent-interface style for transactions with CAS. 2011-01-01 11:35:48 +01:00
Daniele Alessandri 6b82b412fb Cannot use the 'retry' option for transactions without providing a function block. 2011-01-01 11:32:23 +01:00
Daniele Alessandri 858d7372ca Add an example for MULTI/EXEC transactions using CAS. 2010-12-31 19:41:31 +01:00
Daniele Alessandri 99042f6b9c Do not fail with empty transactions when using CAS. 2010-12-31 19:40:59 +01:00
Daniele Alessandri 725d5abe4a Update README. 2010-12-31 19:01:01 +01:00
Daniele Alessandri 46b56437a4 Fix and optimize WATCH with CAS. 2010-12-31 18:55:04 +01:00
Daniele Alessandri 4a497eea79 Add support for optional automatic retries upon aborted transactions. 2010-12-31 18:53:13 +01:00
Daniele Alessandri cf21a43211 Support DISCARD with CAS. 2010-12-31 16:17:31 +01:00
Daniele Alessandri 70487bbfb3 Add support for check-and-set (CAS) for transactions with Predis\MultiExecBlock. 2010-12-31 16:17:24 +01:00
Daniele Alessandri 922beeceea Test suite: tiny fix in a test for LINSERT (again, this time for real). 2010-12-31 16:16:54 +01:00
Daniele Alessandri 02d7400d1f Test suite: tiny fix in a test for LINSERT. 2010-12-21 18:36:43 +01:00
Daniele Alessandri 3a2e977ee0 Test suite: temporary fix for testSetExpire(). 2010-12-18 17:44:06 +01:00
Daniele Alessandri eac195eaea Remove unused class. 2010-12-18 17:43:41 +01:00
Daniele Alessandri daf88645f2 New command: BRPOPLPUSH (Redis v2.2-dev).
Conflicts:

	lib/Predis.php
2010-12-18 17:40:30 +01:00
Daniele Alessandri ecc7499b47 Test suite: move up testStrlen(). 2010-12-18 17:39:17 +01:00
Daniele Alessandri 64cb73fbb9 New command: GETBIT (Redis v2.2-dev).
Conflicts:

	lib/Predis.php
2010-12-18 17:38:49 +01:00
Daniele Alessandri 0b9bca8ce1 New command: SETBIT (Redis v2.2-dev).
Conflicts:

	lib/Predis.php
2010-12-18 17:36:48 +01:00
Daniele Alessandri e1924551b1 New command: SETRANGE (Redis v2.2-dev).
Conflicts:

	lib/Predis.php
2010-12-18 17:33:15 +01:00
Daniele Alessandri 171a28fe26 New command: GETRANGE (Redis v2.2-dev - replaces SUBSTR). 2010-12-18 17:29:32 +01:00
Daniele Alessandri ca5cd2f42a Update CHANGELOG. 2010-11-28 21:16:57 +01:00
Daniele Alessandri 1e4661cfc8 Overridden methods for UNWATCH and DISCARD in Predis\MultiExecBlock must return $this to not break method chaining. 2010-11-28 19:19:20 +01:00
Daniele Alessandri e146fa9e65 Fix a bunch of broken tests. 2010-11-28 17:17:39 +01:00
Daniele Alessandri 21b3fdb3e1 New command: PERSIST (Redis v2.2-dev). 2010-11-28 16:35:25 +01:00
Daniele Alessandri cd9dbb763e Update CHANGELOG. 2010-11-28 14:07:03 +01:00
Daniele Alessandri fffa7acd83 Add support for UNIX domain sockets. 2010-11-28 13:58:09 +01:00
Daniele Alessandri f419d15f82 New command: ZREVRANGEBYSCORE (Redis v2.2-dev). 2010-11-27 12:55:39 +01:00
Daniele Alessandri 7b1713398d Make WATCH accept an array of keys that must be watched. 2010-09-25 17:52:04 +02:00
Daniele Alessandri bbc94863d1 Update CHANGELOG. 2010-09-25 16:25:14 +02:00
Daniele Alessandri 9e58ad7648 Test suite: move the trigger guard for the test suite in the common included file. 2010-09-25 16:15:45 +02:00
Daniele Alessandri 1d45649f86 Test suite: add test for WATCH in Predis\MultiExecBlock. 2010-09-25 16:15:13 +02:00
Daniele Alessandri 29f18254bb Fix improper handling of a few corner cases for Predis\MultiExecBlock and send DISCARD to the server on uncaught exceptions inside a callable block. 2010-09-25 15:06:03 +02:00
Daniele Alessandri 4c8f31f532 Fix bad handling of empty MULTI/EXEC contexts (MULTI should not even be sent to the server). 2010-09-25 14:26:50 +02:00
Daniele Alessandri 96e7a58f9f Test suite: add missing tests for Predis\MultiExecBlock. 2010-09-25 14:23:22 +02:00
Daniele Alessandri c131d2f7b6 Fix an infinite recursion loop when calling Predis\Client::multiExec() (ISSUE #14). 2010-09-24 23:02:08 +02:00
Daniele Alessandri fc8f363fe5 New commands: RPUSHX, LPUSHX (Redis v2.2-dev). 2010-09-21 17:33:24 +02:00
Daniele Alessandri 49a140e3af New command: LINSERT (Redis v2.2-dev). 2010-09-21 17:22:26 +02:00
Daniele Alessandri 73b4760fc4 New command: STRLEN (Redis v2.2-dev). 2010-09-21 16:56:52 +02:00
Daniele Alessandri 8f601b8420 Slight micro-optimization. 2010-09-21 15:55:02 +02:00
Daniele Alessandri 4a6bab995e Update CHANGELOG. 2010-09-18 19:09:54 +02:00
Daniele Alessandri b3ea36f3fa Add a new example. 2010-09-18 18:54:57 +02:00
Daniele Alessandri 8769567c7e Remove Predis\Client::rawCommand() due to interface inconsistencies. 2010-09-18 18:31:05 +02:00
Daniele Alessandri 5124fd1d43 Push initialization commands already created instances of Predis\IConnectionSingle. 2010-09-18 18:26:23 +02:00
Daniele Alessandri 2eec3929fb Get the connection out of a cluster only once inside Predis\Client::getClientFor(). 2010-09-18 17:05:54 +02:00
Daniele Alessandri aa0ea048ae Accept instances of Predis\IConnection or Predis\ConnectionParameters as parameters for the constructor of Predis\Client. 2010-09-18 14:56:53 +02:00
Daniele Alessandri f67082072d Perform (p)unsubscribtion only if (p)subscribed to a channel when the destructor for Predis\PubSubContext is invoked. 2010-09-17 22:23:29 +02:00
Daniele Alessandri ac5f34b0ad Make arguments handling more solid for the SORT command. 2010-09-17 22:10:05 +02:00
Daniele Alessandri 78f11f1a0f Remove useless code duplication. 2010-09-17 21:55:25 +02:00
Daniele Alessandri 9468891faf Fix checks on the value for the STORE argument (ISSUE #13). 2010-09-17 11:36:17 +02:00
Daniele Alessandri 9b849d49c0 Remove some ugly code. And by ugly, I mean really ugly. 2010-08-15 19:15:58 +02:00
Daniele Alessandri ff2129bddf Update CHANGELOG. 2010-08-15 18:38:41 +02:00
Daniele Alessandri b40c2fd214 Remove the static method Predis\Client::create(). 2010-08-15 17:58:45 +02:00
Daniele Alessandri 3487cc219c Remove the method Predis\Client::pipelineSafe(). 2010-08-15 17:52:08 +02:00
Daniele Alessandri 4aca9852fe Update CHANGELOG. 2010-08-15 17:29:08 +02:00
Daniele Alessandri 104bfa3332 Move some common code for connections in the Predis\Connection class. 2010-08-15 16:26:37 +02:00
Daniele Alessandri 68397fe958 Rename Predis\Connection to Predis\ConnectionFactory and disallow the creation of instances for this class. 2010-08-15 15:57:24 +02:00
Daniele Alessandri 8428f9916a More code clean-ups. 2010-08-15 15:08:35 +02:00
Daniele Alessandri 2aec7bfeda Leverage the 'use' statement to make the code a bit shorter and cleaner. 2010-08-15 14:52:47 +02:00
Daniele Alessandri 870a7b9e78 Update CHANGELOG. 2010-08-15 12:08:36 +02:00
Daniele Alessandri b4b06acfe7 Add the Predis\ICommand interface. 2010-08-15 11:43:03 +02:00
Daniele Alessandri fbd5059fb2 Do not use magic methods to serialize the command buffer: rename Predis\Command::__invoke() to Predis\Command::serialize(). 2010-08-15 11:34:24 +02:00
Daniele Alessandri c5f6ca1d90 Test suite: update client tests. 2010-08-15 11:25:56 +02:00
Daniele Alessandri 6ea96e82f9 Make Predis\Command::serializeRequest() a protected method. 2010-08-15 11:20:39 +02:00
Daniele Alessandri e7b8b50dda Merge the serialization of Predis\MultiBulkCommand into Predis\Command since it is the preferred way to send commands to Redis servers >= 1.2. 2010-08-15 11:16:30 +02:00
Daniele Alessandri a1f202527f Do not implicitly extract arguments for multi-bulk commands when the first (and only) element of the arguments array is an array itself. 2010-08-15 11:02:48 +02:00
Daniele Alessandri 01b59a546c Update CHANGELOG. 2010-07-30 19:38:51 +02:00
Daniele Alessandri 565a647a3d Drop support for long method names for commands and move support for Redis v1.0 into a separate file under the new addons subdirectory. 2010-07-30 19:19:23 +02:00
Daniele Alessandri 9c494c6052 Update CHANGELOG. 2010-07-11 17:13:59 +02:00
Daniele Alessandri 46f5408490 Update CHANGELOG. 2010-07-11 17:13:49 +02:00
Daniele Alessandri 1520e2c48b Test suite: add a test for the LIMIT modifier of ZRANGEBYSCORE configured via associative array. 2010-07-11 17:07:56 +02:00
Daniele Alessandri 618708b853 Fix handling of the WEIGHT modifier for ZUNIONSTORE and ZINTERSTORE with more than two weights specified. 2010-07-11 16:40:27 +02:00
Daniele Alessandri ad48369a6b Update CHANGELOG. 2010-07-11 16:40:18 +02:00
Daniele Alessandri 802e77da26 Update CHANGELOG. 2010-07-11 15:32:33 +02:00
Daniele Alessandri 4dc1099103 Update CHANGELOG. 2010-07-07 20:17:44 +02:00
Daniele Alessandri f1df8b163c Add tests for the new options handling for the ZRANGE commands family. 2010-07-07 20:17:32 +02:00
Daniele Alessandri 12298d599b Add support for the LIMIT modifier in ZRANGEBYSCORE. 2010-07-07 20:17:22 +02:00
Daniele Alessandri d2cd1b70b8 ZRANGE, ZREVRANGE and ZRANGEBYSCORE accepts an array instance for optional modifiers. 2010-07-07 20:17:14 +02:00
Daniele Alessandri 7d447f8493 More appropriate type-check to detect clustered connections. 2010-07-02 22:38:16 +02:00
Daniele Alessandri 9f21f5a635 Code formatting. 2010-07-02 22:29:47 +02:00
Daniele Alessandri e3ae04437c First stub of the Predis\Compatibility class. Things will most probably change later. 2010-07-02 22:19:57 +02:00
Daniele Alessandri 2af73f4fa1 Deprecate long method names for Redis commands and move them into new server profiles available in the Predis_Compatibility.php file. 2010-07-02 21:52:56 +02:00
Daniele Alessandri a4df829b19 Deprecate Predis\InlineCommand and Predis\BulkCommand. Those classes are made available through the Predis_Compatibility.php file. 2010-07-02 20:58:15 +02:00
Daniele Alessandri 22807e8163 Bump version number. 2010-07-02 20:55:04 +02:00
Daniele Alessandri 1bb04baf78 Merge branch 'version-0.6'
Conflicts:
	lib/Predis.php
2010-07-02 20:51:18 +02:00
Daniele Alessandri 5defb14698 Merge branch 'connections' 2010-06-24 17:23:01 +02:00
Daniele Alessandri 66a0458018 Leverage the global connection creator facility to alias the 'redis' scheme to the 'tcp' scheme. 2010-06-10 20:37:34 +02:00
Daniele Alessandri 2543bb30cc Map URI schemes to connection classes. 2010-06-10 19:47:40 +02:00
Daniele Alessandri 1fd715e7a5 Prepare to return the appropriate instance of Predis\IConnectionSingle based on the URI scheme. 2010-06-10 11:47:09 +02:00
Daniele Alessandri e191d0a7ce Add required methods to Predis\IConnectionSingle and Predis\IConnectionCluster interfaces. 2010-06-10 11:26:12 +02:00
Daniele Alessandri a2c9cb38a5 Accept the 'scheme' argument for Predis\ConnectionParameters. The 'redis' scheme is now an alias of 'tcp' for compatibility with older versions of Predis. 2010-06-10 11:19:14 +02:00
Daniele Alessandri 72c41a25cb Rename Predis\Connection to Predis\TcpConnection. 2010-06-10 10:40:09 +02:00
Daniele Alessandri b5a6c4e5c3 The Connection class now implements the new IConnectionSingle interface. Guess what is about to happen... 2010-06-09 20:56:25 +02:00
1136 changed files with 113378 additions and 6827 deletions
+6
View File
@@ -0,0 +1,6 @@
[codespell]
skip=./.git
check-hidden=
check-filenames=
builtin=clear,rare,informal,usage,code,names
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget,ro,DOF,dof
+1
View File
@@ -0,0 +1 @@
coverage_clover: build/logs/clover-*.xml
+27
View File
@@ -0,0 +1,27 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
block_comment_start = /*
block_comment = *
block_comment_end = */
[*.php]
max_line_length = 150
[*.{md,yml,yaml,neon,sh}]
indent_size = 2
[VERSION]
insert_final_newline = false
[tests/**.php]
max_line_length = unset
[{src/ClientInterface.php,src/ClientContextInterface.php}]
max_line_length = unset
+20
View File
@@ -0,0 +1,20 @@
* text=auto
/.github export-ignore
/bin export-ignore
/examples export-ignore
/tests export-ignore
/.codespellrc export-ignore linguist-language=INI
/.coveralls.yml export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.php-cs-fixer.dist.php export-ignore
/CHANGELOG.md export-ignore linguist-documentation
/CONTRIBUTING.md export-ignore linguist-documentation
/FAQ.md export-ignore linguist-documentation
/VERSION export-ignore
/phpunit.relay.xml export-ignore
/phpunit.xml.dist export-ignore
/phpstan.dist.neon export-ignore
/phpstan-tests.dist.neon export-ignore
+14
View File
@@ -0,0 +1,14 @@
# 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
+6
View File
@@ -0,0 +1,6 @@
The Predis code of conduct is derived from the Ruby code of conduct. Any violations of the code of conduct may be reported to [Till Krüss](https://till.im):
- Participants will be tolerant of opposing views.
- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
- When interpreting the words and actions of others, participants should always assume good intentions.
- Behavior that can be reasonably considered harassment will not be tolerated.
+2
View File
@@ -0,0 +1,2 @@
github: tillkruss
custom: "https://www.paypal.me/tillkruss"
+31
View File
@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Run command '...'
2. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Versions (please complete the following information):**
- Predis: [e.g. 1.1.2]
- PHP [e.g. 8.0.0]
- Redis Server [e.g. 6.0.0]
- OS [e.g. Ubuntu 20.10]
**Code sample**
If applicable, a small snippet of code that reproduces the issue.
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+73
View File
@@ -0,0 +1,73 @@
---
services:
redis-official:
image: ${REDIS_IMAGE_NAME:-redis:7.4}
container_name: redis-standalone
healthcheck:
test: [ "CMD", "redis-cli", "PING" ]
interval: 10s
timeout: 5s
retries: 3
ports:
- "6379:6379"
profiles:
- all
- official
- standalone
redis-clients:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
container_name: redis-standalone
environment:
- TLS_ENABLED=yes
- REDIS_CLUSTER=no
- PORT=6379
- TLS_PORT=6666
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
ports:
- 6379:6379
- 6666:6666 # TLS port
volumes:
- "./dockers/standalone:/redis/work"
profiles:
- all
- clients
- standalone
redis-cluster:
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
container_name: redis-cluster
environment:
- REDIS_CLUSTER=yes
- NODES=6
- REPLICAS=1
- TLS_ENABLED=yes
- PORT=16379
- TLS_PORT=27379
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
ports:
- "6372-6377:16379-16384"
volumes:
- "./dockers/cluster:/redis/work"
profiles:
- all
- clients
- cluster
redis-stack:
image: ${REDIS_STACK_IMAGE_NAME:-redislabs/client-libs-test:rs-7.4.0-v2}
container_name: redis-stack
ports:
- "6479:6379"
environment:
- REDIS_CLUSTER=no
- PORT=6379
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --save ""}
volumes:
- "./dockers/redis-stack:/redis/work"
profiles:
- all
- clients
- stack
+49
View File
@@ -0,0 +1,49 @@
name-template: 'v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
change-template: '- $TITLE (#$NUMBER)'
autolabeler:
- label: 'maintenance'
files:
- '*.md'
- '.github/*'
- label: 'bug'
branch:
- '/bug-.+'
- label: 'maintenance'
branch:
- '/maintenance-.+'
- label: 'feature'
branch:
- '/feature-.+'
categories:
- title: 'Breaking Changes'
labels:
- 'breakingchange'
- title: 'Experimental Features'
labels:
- 'experimental'
- title: 'New Features'
labels:
- 'feature'
- 'enhancement'
- title: 'Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- 'BUG'
- title: 'Maintenance'
label: 'maintenance'
exclude-labels:
- 'skip-changelog'
template: |
$CHANGES
## Contributors
We'd like to thank all the contributors who worked on this release!
$CONTRIBUTORS
+9
View File
@@ -0,0 +1,9 @@
# Workflows
## Delete runs by workflow name
```bash
gh run list --workflow 'redis-server-tests.yml' --limit 1000 --json databaseId \
| jq '.[].databaseId' \
| xargs -I % gh api --silent -X DELETE /repos/predis/predis/actions/runs/%
```
+196
View File
@@ -0,0 +1,196 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow
name: Linters
on:
push:
branches:
- main
- v2.**
pull_request: null
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
byte_level:
name: Byte-level
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Check file permissions
run: test "$(find . -type f -not -path './.git/*' -executable)" = "./bin/create-command-test"
- name: "Find non-printable ASCII characters"
run: |
! LC_ALL=C.UTF-8 find . -type f -name '*.php' -print0 \
| xargs --null -- grep --perl-regexp --with-filename --line-number '[^ -~ü]'
syntax_errors:
name: Syntax errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"
coverage: none
tools: parallel-lint
- name: Checkout repository
uses: actions/checkout@v3
- name: Check source code for syntax errors
run: composer exec -- parallel-lint bin/ examples/ src/ tests/
static_analysis:
name: Static Analysis
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
- name: Validate Composer configuration
run: composer validate --no-interaction --strict
- name: Install dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest
- name: Check PSR-4 mapping
run: composer dump-autoload --no-interaction --optimize --strict-psr
- name: Perform static analysis
run: composer run phpstan
- name: Perform static analysis on tests
run: composer run phpstan -- --configuration=phpstan-tests.dist.neon
coding_standards:
name: Coding Standards
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
- name: Check EditorConfig configuration
run: test -f .editorconfig
- name: Check adherence to EditorConfig
uses: greut/eclint-action@v0
- name: Install dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest
- name: Check coding style
run: composer exec -- php-cs-fixer fix --diff --dry-run --allow-risky=yes --using-cache=no
- name: Search for TODO-s and FIXME-s
run: |
! git grep --extended-regexp --ignore-case '\b(TODO|FIXME)\b' -- ':/' ':!tests/*' ':!*/linters\.yml'
exported_files:
name: Exported files
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Check exported files
run: |
EXPECTED="LICENSE,README.md,autoload.php,composer.json"
CURRENT="$(
git archive HEAD \
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" \
| paste --serial --delimiters=","
)"
echo "CURRENT =${CURRENT}"
echo "EXPECTED=${EXPECTED}"
test "${CURRENT}" = "${EXPECTED}"
spelling:
name: Spelling
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-codespell
- name: Install codespell
run: pip install --user 'codespell>=2.2'
- name: Search for misspellings
run: $(python -m site --user-base)/bin/codespell
changelog:
name: Changelog
runs-on: ubuntu-latest
timeout-minutes: 5
if: >-
github.event_name == 'pull_request' &&
!contains(github.event.head_commit.message, 'nochangelog') &&
!contains(github.event.head_commit.message, 'no-changelog') &&
!contains(github.event.head_commit.message, 'no changelog') &&
!contains(github.event.pull_request.labels.*.name, 'no-changelog')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for CHANGELOG entry
env:
TARGET: ${{ github.event.pull_request.base.ref }}
run: |
FILES_CHANGED=$(git diff --name-only origin/$TARGET...HEAD | grep -E 'CHANGELOG\.md' -c)
if [ "$FILES_CHANGED" != "1" ]; then
echo "CHANGELOG.md was not updated";
exit 1;
fi;
+25
View File
@@ -0,0 +1,25 @@
name: Release Drafter
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update_release_draft:
name: Update release draft
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter-config.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+183
View File
@@ -0,0 +1,183 @@
name: Tests
on:
push:
branches:
- main
- v2.**
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
predis:
name: PHP ${{ matrix.php }} (Redis ${{ matrix.redis }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php:
- '7.2'
- '8.0'
- '8.3'
- '8.4'
redis:
- '4.0'
- '6.2'
- '7.2'
- '7.4'
- '8.0'
steps:
- name: Resolve container name
run: |
# Mapping of original redis versions to client test containers
declare -A redis_clients_version_mapping=(
["8.0"]="8.0-RC2-pre"
["7.4"]="7.4.2"
["7.2"]="7.2.7"
["6.2"]="6.2.17"
)
# Mapping of redis version to stack version
declare -A redis_stack_version_mapping=(
["7.4"]="rs-7.4.0-v3"
["7.2"]="rs-7.2.0-v15"
["6.2"]="rs-6.2.6-v19"
)
if [[ -v redis_clients_version_mapping[${{ matrix.redis }}] ]]; then
echo "REDIS_IMAGE_NAME=redislabs/client-libs-test:${redis_clients_version_mapping[${{ matrix.redis }}]}" >> $GITHUB_ENV
echo "REDIS_STACK_IMAGE_NAME=redislabs/client-libs-test:${redis_stack_version_mapping[${{ matrix.redis }}]}" >> $GITHUB_ENV
echo "DOCKER_SERVICE=redis-clients" >> $GITHUB_ENV
redis_major_version=$(echo "${{ matrix.redis }}" | grep -oP '^\d+')
# Some configuration options available since Redis > 7
if (( redis_major_version < 7 )); then
echo "REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"" >> $GITHUB_ENV
else
# Since 8.0 modules are bundled with core
echo "REDIS_STACK_SERVER_PORT=6379" >> $GITHUB_ENV
fi
else
echo "REDIS_IMAGE_NAME=redis:${{ matrix.redis }}" >> $GITHUB_ENV
echo "DOCKER_SERVICE=redis-official" >> $GITHUB_ENV
fi
- name: Checkout repository
uses: actions/checkout@v3
- name: Start Redis standalone image
uses: hoverkraft-tech/compose-action@v2.0.1
with:
compose-file: .github/docker-compose.yml
services: ${{ env.DOCKER_SERVICE }}
- name: Start Redis stack image
id: stack_infra
uses: hoverkraft-tech/compose-action@v2.0.1
if: ${{ matrix.redis >= '6.2' && matrix.redis < '8.0' }}
with:
compose-file: .github/docker-compose.yml
services: redis-stack
- name: Start Redis cluster image
id: cluster_infra
uses: hoverkraft-tech/compose-action@v2.0.1
if: ${{ matrix.redis > '4.0' }}
with:
compose-file: .github/docker-compose.yml
services: redis-cluster
- 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' }}
- name: Install Composer dependencies
uses: ramsey/composer-install@v2
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' }}
run: vendor/bin/phpunit
- name: Run tests with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
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 >= '6.2' }}
run: vendor/bin/phpunit -c phpunit.relay.xml
- name: Run tests using Relay with coverage
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
run: vendor/bin/phpunit -c phpunit.relay.xml --coverage-php build/cov/coverage-relay.cov --coverage-filter ./src
- name: Run stack tests
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && matrix.redis >= '6.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' }}
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' }}
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' }}
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' }}
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' }}
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' }}
run: |
vendor/bin/phpunit -c phpunit.relay.xml --group cluster
- name: Merge coverage reports
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
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' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
finish:
name: Finish Coverall
needs: predis
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
+8
View File
@@ -0,0 +1,8 @@
/build
/vendor
.php-version
.php_cs.cache
.phpunit.result.cache
.php-cs-fixer.cache
composer.lock
phpunit.xml
+43
View File
@@ -0,0 +1,43 @@
<?php
$PREDIS_HEADER = <<<EOS
This file is part of the Predis package.
(c) 2009-2020 Daniele Alessandri
(c) 2021-2025 Till Krüss
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOS;
$fixer = new PhpCsFixer\Config;
$fixer->setParallelConfig(
\PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()
);
$fixer->setRules([
'@PHP71Migration' => true,
'header_comment' => ['header' => $PREDIS_HEADER],
'@Symfony' => true,
'phpdoc_separation' => false,
'phpdoc_annotation_without_dot' => false,
'no_superfluous_phpdoc_tags' => false,
'no_unneeded_curly_braces' => false,
'no_unneeded_braces' => false,
'global_namespace_import' => true,
'yoda_style' => false,
'single_line_throw' => false,
'concat_space' => ['spacing' => 'one'],
'increment_style' => false,
'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['array_destructuring', 'arrays']]
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__ . '/bin')
->in(__DIR__ . '/examples')
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
);
return $fixer;
-185
View File
@@ -1,185 +0,0 @@
v0.6.2 (2010-11-28)
* Minor internal improvements and clean ups.
* New commands available in the Redis v2.2 profile (dev):
- Strings: STRLEN
- Lists : LINSERT, RPUSHX, LPUSHX
- ZSets : ZREVRANGEBYSCORE
- Misc. : PERSIST
* WATCH also accepts a single array parameter with the keys that should be
monitored during a transaction.
* Improved the behaviour of Predis\MultiExecBlock in certain corner cases.
* Improved parameters checking for the SORT command.
* FIX: the STORE parameter for the SORT command didn't work correctly when
using '0' as the target key (ISSUE #13).
* FIX: the methods for UNWATCH and DISCARD do not break anymore method
chaining with Predis\MultiExecBlock.
v0.6.1 (2010-07-11)
* Minor internal improvements and clean ups.
* New commands available in the Redis v2.2 profile (dev):
- Misc. : WATCH, UNWATCH
* Optional modifiers for ZRANGE, ZREVRANGE and ZRANGEBYSCORE queries are
supported using an associative array passed as the last argument of their
respective methods.
* The LIMIT modifier for ZRANGEBYSCORE can be specified using either:
- an indexed array: array($offset, $count)
- an associative array: array('offset' => $offset, 'count' => $count)
* The method Predis\Client::__construct() now accepts also instances of
Predis\ConnectionParameters.
* Predis\MultiExecBlock and Predis\PubSubContext now throw an exception
when trying to create their instances using a profile that does not
support the required Redis commands or when the client is connected to
a cluster of connections.
* Various improvements to Predis\MultiExecBlock:
- fixes and more consistent behaviour across various usage cases.
- support for WATCH and UNWATCH when using the current development
profile (Redis v2.2) and aborted transactions.
* New signature for Predis\Client::multiExec() which is now able to accept
an array of options for the underlying instance of Predis\MultiExecBlock.
Backwards compatibility with previous releases of Predis is ensured.
* New signature for Predis\Client::pipeline() which is now able to accept
an array of options for the underlying instance of Predis\CommandPipeline.
Backwards compatibility with previous releases of Predis is ensured.
The method Predis\Client::pipelineSafe() is to be considered deprecated.
* FIX: The WEIGHT modifier for ZUNIONSTORE and ZINTERSTORE was handled
incorrectly with more than two weights specified.
v0.6.0 (2010-05-24)
* Switched to the new multi-bulk request protocol for all of the commands
in the Redis 1.2 and Redis 2.0 profiles. Inline and bulk requests are now
deprecated as they will be removed in future releases of Redis.
* The default server profile is "2.0" (targeting Redis 2.0.x). If you are
using older versions of Redis, it is highly recommended that you specify
which server profile the client should use (e.g. "1.2" when connecting
to instances of Redis 1.2.x).
* Support for Redis 1.0 is now optional and it is provided by requiring
'Predis_Compatibility.php' before creating an instance of Predis\Client.
* New commands added to the Redis 2.0 profile since Predis 0.5.1:
- Strings: SETEX, APPEND, SUBSTR
- ZSets : ZCOUNT, ZRANK, ZUNIONSTORE, ZINTERSTORE, ZREMBYRANK, ZREVRANK
- Hashes : HSET, HSETNX, HMSET, HINCRBY, HGET, HMGET, HDEL, HEXISTS,
HLEN, HKEYS, HVALS, HGETALL
- PubSub : PUBLISH, SUBSCRIBE, UNSUBSCRIBE
- Misc. : DISCARD, CONFIG
* Introduced client-level options with the new Predis\ClientOptions class.
Options can be passed to Predis\Client::__construct in its second argument
as an array or an instance of Predis\ClientOptions. For brevity's sake and
compatibility with older versions, the constructor of Predis\Client still
accepts an instance of Predis\RedisServerProfile in its second argument.
The currently supported client options are:
- profile [default: "2.0" as of Predis 0.6.0]
specifies which server profile to use when connecting to Redis. This
option accepts an instance of Predis\RedisServerProfile or a string
that indicates the target version.
- key_distribution [default: Predis\Distribution\HashRing]
specifies which key distribution strategy to use to distribute keys
among the servers that compose a cluster. This option accepts an
instance of Predis\Distribution\IDistributionStrategy so that users
can implement their own key distribution strategy. Optionally, the new
Predis\Distribution\KetamaPureRing class also provides a pure-PHP
implementation of the same algorithm used by libketama.
- throw_on_error [default: TRUE]
server errors can optionally be handled "silently": instead of throwing
an exception, the client returns an error response type.
- iterable_multibulk [EXPERIMENTAL - default: FALSE]
in addition to the classic way of fetching a whole multibulk reply
into an array, the client can now optionally stream a multibulk reply
down to the user code by using PHP iterators. It is just a little bit
slower, but it can save a lot of memory in certain scenarios.
* New parameters for connections:
- alias [default: not set]
every connection can now be identified by an alias that is useful to
get a certain connection when connected to a cluster of Redis servers.
- weight [default: not set]
allows the client to balance the keys asymmetrically across multiple
servers. This might be useful when you have servers with different
amounts of memory and you want to distribute the load of your keys
accordingly.
- connection_async [default: FALSE]
estabilish connections to servers in a non-blocking way, so that the
client is not blocked while the underlying resource performs the actual
connection.
- connection_persistent [default: FALSE]
the underlying connection resource is left open when a script ends its
lifecycle. Persistent connections can lead to unpredictable or strange
behaviours, so they should be used with extreme care.
* Introduced the Predis\Pipeline\IPipelineExecutor interface. Classes that
implements this interface are used internally by the Predis\CommandPipeline
class to change the behaviour of the pipeline when writing/reading commands
from one or multiple servers. Here is the list of the default executors:
- Predis\Pipeline\StandardExecutor
Exceptions generated by server errors might be thrown depending on the
options passed to the client (see "throw_on_error"). Instead, protocol
or network errors always throw exceptions. This is the default executor
for single and clustered connections and shares the same behaviour of
Predis 0.5.x.
- Predis\Pipeline\SafeExecutor
Exceptions generated by server, protocol or network errors are not
thrown, instead they are returned in the response array as instances of
ResponseError or CommunicationException.
- Predis\Pipeline\SafeClusterExecutor
This executor shares the same behaviour of Predis\Pipeline\SafeExecutor
but it is geared towards clustered connections.
* Support for PUBSUB is handled by the new Predis\PubSubContext class, which
could also be used to build a callback dispatcher for PUBSUB scenarios.
* When connected to a cluster of connections, it is now possible to get a
new Predis\Client instance for a single connection of the cluster by
passing its alias/index to the new Predis\Client::getClientFor() method.
* CommandPipeline and MultiExecBlock return their instances when invoking
commands, thus allowing method chaining in pipelines and multi-exec blocks.
* MultiExecBlock instances can handle the new DISCARD command.
* Connections now support float values for the connection_timeout parameter
to express timeouts with a microsecond resolution.
* FIX: TCP connections now respect the read/write timeout parameter when
reading the payload of server responses. Previously, stream_get_contents()
was being used internally to read data from a connection but it looks like
PHP does not honour the specified timeout for socket streams when inside
this function.
* FIX: The GET parameter for the SORT command now accepts also multiple key
patterns by passing an array of strings. (ISSUE #1).
* FIX: Replies to the DEL command return the number of elements deleted by
the server and not 0 or 1 interpreted as a boolean response. (ISSUE #4).
v0.5.1 (2010-01-23)
* RPOPLPUSH has been changed from bulk command to inline command in Redis
1.2.1, so ListPopLastPushHead now extends InlineCommand. The old RPOPLPUSH
behavior is still available via the ListPopLastPushHeadBulk class so that
you can override the server profile if you need the old (and uncorrect)
behaviour when connecting to a Redis 1.2.0 instance.
* Added missing support for BGREWRITEAOF for Redis >= 1.2.0
* Implemented a factory method for the RedisServerProfile class to ease the
creation of new server profile instances based on a version string.
v0.5.0 (2010-01-09)
* First versioned release of Predis
+300
View File
@@ -0,0 +1,300 @@
## Changelog
## v2.4.0 (2025-04-30)
### Added
- Added new hash-field expiration commands (#1520)
- Added missing `FT._LIST` and `BITFIELD_RO` commands (#1521)
### Changed
- Update `WATCH` command to accept `string|string[]` (#1476)
- Optimize cluster slotmap with compact slot range object (#1493)
### Fixed
- Fixed `EVAL_RO` cluster support (#1449)
- Fixed PHP 8.4 compatibility with `stream_context_set_option()` (#1503)
- Prevent named arguments runtime failure (#1509)
- Mark `GEOSEARCH` as read-only to ensure execution on replica (#1481)
- Fixed protocol loss during redis cluster `MOVED` / `ASK` (#1530)
### Maintenance
- Added CI testing with Redis 8.0 (#1510)
- Added test coverage for compatibility with Redis 8.0 (#1513)
- Use parallel on PHP-CS-Fixer (#1489)
## v2.3.0 (2024-11-21)
### Added
- Added `GeoShapeField` field (#1467)
- Added hash expiration commands (#1456)
- Added support for time series `IGNORE` filter (#1458)
- Added `XREAD` commands (#1459)
- Added `NOVALUES` argument support to `HSCAN` (#1459)
- Added support for search `INDEXMISSING` and `INDEXEMPTY` arguments (#1464)
### Changed
- Explicitly mark nullable parameters as nullable (#1448)
- Filter out available replicas based on link status flag (#1440)
- Respect `prefix` for `ZPOPMIN`, `ZPOPMAX`, `ZMSCORE`, `LMOVE`, `BLMOVE`, `SMISMEMBER` and `GEOSEARCH` (#1451, #1453, #1455, #1468)
- Updated test infrastructure (#1510)
### Fixed
- Fixed Relay support when using Redis Cluster (#1397)
- Fixed `cmsincrby()` type annotation (#1333)
- Fixed `set()` type annotation (#1394)
- Fixed operator precedence in connection factory (#1405)
- Fixed a bug with `null` arguments in `set()` method (#1470, #1471)
## v2.2.2 (2023-09-13)
### Added
- Added `client_info` client parameter
- Added support for `CLUSTER` container command
### Fixed
- Fixed `EXPIRETIME` not using `prefix`
- Disabled `CLIENT SETINFO` calls by default
## v2.2.1 (2023-08-15)
### Added
- Added support for `WAITAOF` command (#1357)
- Added support for `SHUTDOWN` command (#1359)
- Added support for `FUNCTION` command (#1332)
- Added support for new optional `PEXPIRE`, `PEXPIREAT` and `COMMAND`
- Added missing Redis Stack commands to `KeyPrefixProcessor` (#1358)
### Changed
- Set client name and version when establishing a connection (#1347)
## v2.2.0 (2023-06-14)
Predis v2.2.0 introduces official support for [Redis Stack](https://redis.io/docs/stack/) as well as a [Relay](https://github.com/cachewerk/relay) integration for substantially [faster read performance](https://github.com/predis/predis/wiki/Using-Relay).
### Added
- Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263)
- Added support for `FCALL_RO` command (#1191)
- Added support for Redis `JSON`, `Bloom`, `Search` and `TimeSeries` module (#1253)
- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands (#1193)
### Changed
- Minor code style and type-hint changes (#1311)
### Fixed
- Fixed prefixes for `XTRIM` and `XREVRANGE` commands (#1230)
- Fixed `fclose()` being called on invalid stream resource (#1199)
- Fixed `BitByte` and `ExpireOptions` traits skip processing on null values (#1169)
- Fixed missing `@return` annotations (#1265)
- Fixed `GETDEL` prefixing (#1306)
## v2.1.2 (2023-03-02)
### Added
- Added stream commands to `KeyPrefixProcessor` (#1051)
- Added `ReplicationStrategy::$loadBalancing` option to disable replica reads (#1168)
- Added support for `FCALL` and `FUNCTIONS` commands (#1049)
- Added support for `PEXPIRETIME` command (#1031)
- Added support for `EXPIRETIME` command (#1029)
- Added support for `EVAL_RO` command (#1032)
- Added support for `LCS` command (#1035)
- Added support for `SORT_RO` command (#1044)
- Added support for `SINTERCARD` command (#1027)
- Added support for `EVALSHA_RO` command (#1034)
- Added support for new arguments for `BITPOS` and `BITCOUNT` commands (#1045)
- Added support for new arguments for `EXPIRE` and `EXPIREAT` commands (#1046)
### Bug Fixes
- Fixed deprecated function call syntax
### Deprecated
- Further deprecated phpiredis and webdis integration (#1179)
### Maintenance
- Applied coding standards
- Pass PHPStan level 2
## v2.1.1 (2023-01-17)
### Bug Fixes
- Fix `@template` in `Predis\Client` (#1017)
- Fix support options array in `ZINTERSTORE` and `ZUNIONSTORE` (#1018)
### Deprecated
- Deprecated phpiredis and webdis connections
## v2.1.0 (2023-01-16)
### New Features
- Implemented `GETEX` command (#872)
- Implemented `GETDEL` command (#869)
- Implemented `COPY` command (#866)
- Implemented `FAILOVER` command (#875)
- Implemented `LMOVE` command (#863)
- Implemented `LMPOP` command (#1013)
- Implemented `HRANDFIELD` command (#870)
- Implemented `SMISMEMBER` command (#871)
- Implemented `ZMPOP` command (#831)
- Implemented `BLMOVE` command (#865)
- Implemented `BLMPOP` command (#1015)
- Implemented `BZMPOP` command (#833)
- Implemented `BZPOPMIN` command (#862)
- Implemented `BZPOPMAX` command (#864)
- Implemented `ZUNION` command (#860)
- Implemented `ZINTER` command (#859)
- Implemented `ZINTERCARD` command (#861)
- Implemented `ZRANGESTORE` command (#829)
- Implemented `ZDIFFSTORE` command (#828)
- Implemented `ZDIFF` command (#826)
- Implemented `ZRANDMEMBER` command (#825)
- Implemented `ZMSCORE` (#823)
- Implemented `GEOSEARCH` command (#867)
- Implemented `GEOSEARCHSTORE` command (#873)
### Bug Fixes
- Added annotations to suppress PHP 8.1 return type deprecation warning (#810)
### Maintenance
- Added mixin annotations for traits (#835)
## v2.0.3 (2022-10-11)
- Improved PHP 8.2 support
- Call `is_resource()` before reading/writing
- Added partial support for Redis Stream commands
- Fixed Sentinel authentication issue
## v2.0.2 (2022-09-06)
- Fixed PHP 8.2 deprecation notice: Use of "static" in callables
## v2.0.1 (2022-09-04)
- Added retry interval to `RedisCluster` with a default of `10ms`
- Avoid PHP 8.2 warning in `Connection\Parameters`
- Fixed Sentinel reconnect issue in long-running PHP processes
## v2.0.0 (2022-06-08)
- Dropped support for PHP 7.1 and older
- Accepted values for some client options have changed, this is the new list of
accepted values:
- `aggregate`: callable returning an aggregate connection.
- `cluster`: string value (`predis`, `redis`), callable returning an aggregate
connection.
- `replication`: string value (`predis`, `sentinel`), callable returning an
aggregate connection.
- `commands`: command factory, named array mapping command IDs to PHP classes,
callable returning a command factory or a named array.
- `connections`: connection factory, callable object returning a connection
factory, named array mapping URI schemes to PHP classes, string identifying
a supported combination of configurations for the connection factory.
- `prefix`: string value, command processor, callable.
- `exceptions`: boolean.
Note that both the `cluster` and `replication` options now return a closure
acting as initializer instead of an aggregate connection instance.
- The `connections` client option now accepts certain string values identifying
certain combinations of configurations for the connection factory. Currently
this is used to provide a short way to configure Predis to load our phpiredis
based connection backends simply, accepted values are:
- `phpiredis-stream` maps `Phpiredis\Connection\PhpiredisStreamConnection` to
`tcp`, `redis`, `unix` URI schemes.
- `phpiredis-socket` maps `Phpiredis\Connection\PhpiredisSocketConnection` to
`tcp`, `redis`, `unix` URI schemes.
- `phpiredis-stream` is simply an alias of `phpiredis-stream`.
- Added the new `Predis\Cluster\Hash\PhpiredisCRC16` class using ext-phpiredis
to speed-up the generation of the CRC16 hash of keys for redis-cluster. Predis
automatically uses this class when ext-phpiredis is loaded, but it is possible
to configure the hash generator using the new `crc16` client option (accepted
values `predis`, `phpiredis` or an hash generator instance).
- Replication backends now use the `role` parameter instead of `alias` in order
to distinguish the role of a connection. Accepted values are `master`, `slave`
and, for redis-sentinel, `sentinel`. This led to a redesign of how connections
can be retrieved from replication backends: the method getConnectionById() now
retrieves a connection only by its ID (ip:port pair), to get a connection by
its alias there is the new method getConnectionByAlias(). This method is not
supported by the redis-sentinel backend due to its dynamic nature (connections
are retrieved and initialized at runtime from sentinels) but it is possible to
get a single connection from the pool by using its ID. It is also possible to
retrieve a connection by role using the method getConnectionByRole().
- The concept of connection ID (ip:port pair) and connection alias (the `alias`
parameter) in `Predis\Connection\Cluster\PredisCluster` has been separated.
This change does not affect distribution and it is safe for existing clusters.
- Client option classes now live in the `Predis\Configuration\Option` namespace.
- Classes for Redis commands have been moved into the new `Predis\Command\Redis`
namespace and each class name mirrors the respective Redis command ID.
- The concept of server profiles is gone, the library now uses a single command
factory to create instances of commands classes. The `profile` option has been
replaced by the `commands` option accepting `Predis\Command\FactoryInterface`
to customize the underlying command factory. The default command factory class
used by Predis is `Predis\Command\RedisFactory` and it still allows developers
to define or override commands with their own implementations. In addition to
that, `Predis\Command\RedisFactory` relies on a convention-over-configuration
approach by looking for a suitable class with the same name as the command ID
in the `Predis\Command\Redis` when the internal class map does not contain a
class associated.
- The method `Predis\Client::getClientFor($connectionID)` has been replaced by
`getClientBy($selector, $value, $callable = null)` which is more flexible as
it is not limited to picking a connection from the underlying replication or
cluster backend by ID, but allows users to specify a `$selector` that can be
either `id` (the old behavior), `key`, `slot` or `command`. The client uses
duck-typing instead of type-checking to verify that the underlying connection
implements a method that matches the specified selector which means that some
selectors may not be available to all kinds of connection backends.
- The method `Predis\Client::getConnectionById($connectionID)` has been removed.
- Changed the signature for the constructor of `Predis\Command\RawCommand`.
- The `Predis\Connection\Aggregate` namespace has been split into two separate
namespaces for cluster backends (`Predis\Connection\Cluster`) and replication
backends (`Predis\Connection\Replication`).
- The method `Predis\Connection\AggregateConnectionInterface::getConnection()`
has been renamed to `getConnectionByCommand()`.
- The methods `switchToMaster()` and `switchToSlave()` have been promoted to be
part of `Predis\Connection\Replication\ReplicationInterface` while the method
`switchTo($connection)` has been removed from it.
- The method `Predis\Connection\Cluster\PredisCluster::executeCommandOnNodes()`
has been removed as it is possible to achieve the same by iterating over the
connection or, even better, over the client instance in order to execute the
same command against all of the registered connections.
- The class `Predis\CommunicationException` now uses the correct default types
for the `$message` (string) and `$code` (integer) parameters.
- The method `onConnectionError()` in `Predis\Connection\AbstractConnection`
class now passes the second argument as an integer value `0` as its default
value instead of `null`.
- Support Pub/Sub and Pipelines when using replication
- The class `Predis\Transaction\AbortedMultiExecException` now uses the correct
default types for the `$code` (integer) parameter.
- __FIX__: using `strval` in `getScanOptions()` method, part of
`Predis\Collection\Iterator\CursorBasedIterator` to make sure we retrieve the
string value of `$this->match` and not passing `null` to `strlen()` function.
- __FIX__: the value returned from `getArgument()` in `isReadOperation()` method,
part of `Predis\Replication\ReplicationStrategy` class, is checked to not pass
`null` to `sha1` function.
- __FIX__: the value returned from `getArgument()` in `parseResponse()`method,
part of `Predis\Command\Redis\SENTINEL` class, is checked to not pass `null`
to `strtolower()` function.
## v2.0.0-beta.1 (2022-05-26)
Same as v2.0.0
+97
View File
@@ -0,0 +1,97 @@
# Frequently asked questions about Predis #
## What is the point of Predis? ##
The main point of Predis is about offering a highly customizable and extensible client for Redis,
that can be easily extended by developers while still being reasonably fast. With Predis you can
swap almost any class with your own custom implementation: you can have custom connection classes,
new distribution strategies for client-side sharding, or handlers to replace or add Redis commands.
All of this can be achieved without messing with the source code of the library and directly in your
own application. Given the fast pace at which Redis is developed and adds new features, this can be
a great asset since it allows developers to add new and still missing features or commands or change
the standard behaviour of the library without the need to break dependencies in production code (at
least to some degree).
## Does Predis support UNIX domain sockets and persistent connections? ##
Yes. Obviously persistent connections actually work only when using PHP configured as a persistent
process reused by the web server (see [PHP-FPM](http://php-fpm.org)).
## Does Predis support SSL-encrypted connections? ##
Yes. Encrypted connections are mostly useful when connecting to Redis instances exposed by various
cloud hosting providers without the need to configure an SSL proxy, but you should also take into
account the general performances degradation especially during the connect() operation when the TLS
handshake must be performed to secure the connection. Persistent SSL-encrypted connections may help
in that respect, but they are supported only when running on PHP >= 7.0.0.
## Does Predis support transparent (de)serialization of values? ##
When using [Relay](https://github.com/cachewerk/relay) as the underlying client, several
serialization and compression algorithms are supported. This slightly increases CPU usage,
but significantly reduces bytes sent over the network and Redis memory usage.
Without Relay, Predis will not serialize data and will never do that by default. The reason
behind this decision is that serialization is usually something that developers prefer to
customize depending on their needs and can not be easily generalized when using Redis because
of the many possible access patterns for your data. This does not mean that it is impossible
to have such a feature since you can leverage the extensibility of this library to define
your own serialization-aware commands. You can find more details about how to do that
[on this issue](http://github.com/predis/predis/issues/29#issuecomment-1202624).
## How can I force Predis to connect to Redis before sending any command? ##
Explicitly connecting to Redis is usually not needed since the client initializes connections lazily
only when they are needed. Admittedly, this behavior can be inconvenient in certain scenarios when
you absolutely need to perform an upfront check to determine if the server is up and running and
eventually catch exceptions on failures. Forcing the client to open the underlying connection can be
done by invoking `Predis\Client::connect()`:
```php
$client = new Predis\Client();
try {
$client->connect();
} catch (Predis\Connection\ConnectionException $exception) {
// We could not connect to Redis! Your handling code goes here.
}
$client->info();
```
## How Predis abstracts Redis commands? ##
The approach used to implement Redis commands is quite simple: by default each command follows the
same signature as defined on the [Redis documentation](http://redis.io/commands) which makes things
pretty easy if you already know how Redis works or you need to look up how to use certain commands.
Alternatively, variadic commands can accept an array for keys or values (depending on the command)
instead of a list of arguments. Commands such as [`RPUSH`](http://redis.io/commands/rpush) and
[`HMSET`](http://redis.io/commands/hmset) are great examples:
```php
$client->rpush('my:list', 'value1', 'value2', 'value3'); // plain method arguments
$client->rpush('my:list', ['value1', 'value2', 'value3']); // single argument array
$client->hmset('my:hash', 'field1', 'value1', 'field2', 'value2'); // plain method arguments
$client->hmset('my:hash', ['field1'=>'value1', 'field2'=>'value2']); // single named array
```
An exception to this rule is [`SORT`](http://redis.io/commands/sort) for which modifiers are passed
[using a named array](tests/Predis/Command/KeySortTest.php#L54-L75).
## When should I use Relay? ##
If you care about performance, __always__. [Relay][relay] is free to use.
## When should I use PhpRedis? ###
Predis is fast enough when Redis is located on the same machine as PHP.
[PhpRedis][phpredis] and [Relay][relay] perform significantly better when network I/O is involved,
due to its ability to compress data by ~75%. Fewer bytes and received sent over the network
[means faster operations][performance], and potentially cost savings when network traffic isn't
free (e.g. AWS ElastiCache Inter-AZ transfer costs).
[phpredis]: https://github.com/phpredis/phpredis
[relay]: [https://github.com/phpredis/phpredis](https://github.com/cachewerk/relay)
[performance]: https://akalongman.medium.com/phpredis-vs-predis-comparison-on-real-production-data-a819b48cbadb
+19 -19
View File
@@ -1,22 +1,22 @@
Copyright (c) 2009-2010 Daniele Alessandri
MIT License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
Copyright (c) 2009-2020 Daniele Alessandri (original work)
Copyright (c) 2021-2024 Till Krüss (modified work)
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-141
View File
@@ -1,141 +0,0 @@
# Predis #
## About ##
Predis is a flexible and feature-complete PHP client library for the Redis key-value
database. It currently comes in two flavors:
- the mainline client library, which targets PHP 5.3.x and leverages a lot of the
features introduced in this new version of the PHP interpreter.
- a backport to PHP 5.2.x for those who can not upgrade their environment yet
(it admittedly has a lower priority compared to the mainline library, although we
try to keep the two versions aligned as much as possible).
Please refer to the TODO file to see which issues are still pending and what is due
to be implemented soon in Predis.
## Main features ##
- Full support for Redis 2.0. Different versions of Redis are supported via server profiles.
- Client-side sharding (support for consistent hashing and custom distribution strategies).
- Command pipelining on single and multiple connections (transparent).
- Lazy connections (connections to Redis instances are only established just in time).
- Flexible system to define and register your own set of commands to a client instance.
## Quick examples ##
See the [official wiki](http://wiki.github.com/nrk/predis) of the project for a more
complete coverage of all the features available in Predis.
### Connecting to a local instance of Redis ###
You don't have to specify a tcp host and port when connecting to Redis instances
running on the localhost on the default port:
$redis = new Predis\Client();
$redis->set('library', 'predis');
$value = $redis->get('library');
### Pipelining multiple commands to a remote instance of Redis ##
Pipelining helps with performances when there is the need to issue many commands
to a server in one go:
$redis = new Predis\Client('redis://10.0.0.1:6379/');
$replies = $redis->pipeline(function($pipe) {
$pipe->ping();
$pipe->incrby('counter', 10);
$pipe->incrby('counter', 30);
$pipe->get('counter');
});
### Pipelining multiple commands to multiple instances of Redis (sharding) ##
Predis supports data sharding using consistent-hashing on keys on the client side.
Furthermore, a pipeline can be initialized on a cluster of redis instances in the
same exact way they are created on single connection. Sharding is still transparent
to the user:
$redis = Predis\Client::create(
array('host' => '10.0.0.1', 'port' => 6379),
array('host' => '10.0.0.2', 'port' => 6379)
);
$replies = $redis->pipeline(function($pipe) {
for ($i = 0; $i < 1000; $i++) {
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
$pipe->get("key:$i");
}
});
### Definition and runtime registration of new commands on the client ###
Let's suppose Redis just added the support for a brand new feature associated
with a new command. If you want to start using the above mentioned new feature
right away without messing with Predis source code or waiting for it to find
its way into a stable Predis release, then you can start off by creating a new
class that matches the command type and its behaviour and then bind it to a
client instance at runtime. Actually, it is easier done than said:
class BrandNewRedisCommand extends \Predis\MultiBulkCommand {
public function getCommandId() { return 'NEWCMD'; }
}
$redis = new Predis\Client();
$redis->getProfile()->registerCommand('BrandNewRedisCommand', 'newcmd');
$redis->newcmd();
## Development ##
Predis is fully backed up by a test suite which tries to cover all the aspects of the
client library and the interaction of every single command with a Redis server. If you
want to work on Predis, it is highly recommended that you first run the test suite to
be sure that everything is OK, and report strange behaviours or bugs.
The recommended way to contribute to Predis is to fork the project on GitHub, fix or
add features on your newly created repository and then submit issues on the Predis
issue tracker with a link to your repository. Obviously, you can use any other Git
hosting provider of you preference. Diff patches will be accepted too, even though
they are not the preferred way to contribute to Predis.
When modifying Predis please be sure that no warnings or notices are emitted by PHP
by running the interpreter in your development environment with the "error_reporting"
variable set to E_ALL | E_STRICT.
## Dependencies ##
- PHP >= 5.3.0 (for the mainline client library)
- PHP >= 5.2.6 (for the backported client library)
- PHPUnit (needed to run the test suite)
## Links ##
### Project ###
- [Source code](http://github.com/nrk/predis/)
- [Wiki](http://wiki.github.com/nrk/predis/)
- [Issue tracker](http://github.com/nrk/predis/issues)
### Related ###
- [Redis](http://code.google.com/p/redis/)
- [PHP](http://php.net/)
- [PHPUnit](http://www.phpunit.de/)
- [Git](http://git-scm.com/)
## Author ##
[Daniele Alessandri](mailto:suppakilla@gmail.com)
## Contributors ##
[Lorenzo Castelli](http://github.com/lcastelli)
## License ##
The code for Predis is distributed under the terms of the MIT license (see LICENSE).
+466
View File
@@ -0,0 +1,466 @@
# Predis #
[![Software license][ico-license]](LICENSE)
[![Latest stable][ico-version-stable]][link-releases]
[![Latest development][ico-version-dev]][link-releases]
[![Monthly installs][ico-downloads-monthly]][link-downloads]
[![Build status][ico-build]][link-actions]
[![Coverage Status][ico-coverage]][link-coverage]
A flexible and feature-complete [Redis](http://redis.io) / [Valkey](https://github.com/valkey-io/valkey) client for PHP 7.2 and newer.
More details about this project can be found on the [frequently asked questions](FAQ.md).
## Main features ##
- Support for Redis from __3.0__ to __8.0__.
- Support for clustering using client-side sharding and pluggable keyspace distributors.
- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel).
- Transparent key prefixing of keys using a customizable prefix strategy.
- Command pipelining on both single nodes and clusters (client-side sharding only).
- Abstraction for Redis transactions (Redis >= 2.0) and CAS operations (Redis >= 2.2).
- Abstraction for Lua scripting (Redis >= 2.6) and automatic switching between `EVALSHA` or `EVAL`.
- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators.
- Connections are established lazily by the client upon the first command and can be persisted.
- Connections can be established via TCP/IP (also TLS/SSL-encrypted) or UNIX domain sockets.
- Support for custom connection classes for providing different network or protocol backends.
- Flexible system for defining custom commands and override the default ones.
## How to _install_ and use Predis ##
This library can be found on [Packagist](http://packagist.org/packages/predis/predis) for an easier
management of projects dependencies using [Composer](http://packagist.org/about-composer).
Compressed archives of each release are [available on GitHub](https://github.com/predis/predis/releases).
```shell
composer require predis/predis
```
### Loading the library ###
Predis relies on the autoloading features of PHP to load its files when needed and complies with the
[PSR-4 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md).
Autoloading is handled automatically when dependencies are managed through Composer, but it is also
possible to leverage its own autoloader in projects or scripts lacking any autoload facility:
```php
// Prepend a base path if Predis is not available in your "include_path".
require 'Predis/Autoloader.php';
Predis\Autoloader::register();
```
### Connecting to Redis ###
When creating a client instance without passing any connection parameter, Predis assumes `127.0.0.1`
and `6379` as default host and port. The default timeout for the `connect()` operation is 5 seconds:
```php
$client = new Predis\Client();
$client->set('foo', 'bar');
$value = $client->get('foo');
```
Connection parameters can be supplied either in the form of URI strings or named arrays. The latter
is the preferred way to supply parameters, but URI strings can be useful when parameters are read
from non-structured or partially-structured sources:
```php
// Parameters passed using a named array:
$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '10.0.0.1',
'port' => 6379,
]);
// Same set of parameters, passed using an URI string:
$client = new Predis\Client('tcp://10.0.0.1:6379');
```
Password protected servers can be accessed by adding `password` to the parameters set. When ACLs are
enabled on Redis >= 6.0, both `username` and `password` are required for user authentication.
It is also possible to connect to local instances of Redis using UNIX domain sockets, in this case
the parameters must use the `unix` scheme and specify a path for the socket file:
```php
$client = new Predis\Client(['scheme' => 'unix', 'path' => '/path/to/redis.sock']);
$client = new Predis\Client('unix:/path/to/redis.sock');
```
The client can leverage TLS/SSL encryption to connect to secured remote Redis instances without the
need to configure an SSL proxy like stunnel. This can be useful when connecting to nodes running on
various cloud hosting providers. Encryption can be enabled with using the `tls` scheme and an array
of suitable [options](http://php.net/manual/context.ssl.php) passed via the `ssl` parameter:
```php
// Named array of connection parameters:
$client = new Predis\Client([
'scheme' => 'tls',
'ssl' => ['cafile' => 'private.pem', 'verify_peer' => true],
]);
// Same set of parameters, but using an URI string:
$client = new Predis\Client('tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1');
```
The connection schemes [`redis`](http://www.iana.org/assignments/uri-schemes/prov/redis) (alias of
`tcp`) and [`rediss`](http://www.iana.org/assignments/uri-schemes/prov/rediss) (alias of `tls`) are
also supported, with the difference that URI strings containing these schemes are parsed following
the rules described on their respective IANA provisional registration documents.
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.
Predis can aggregate multiple connections when providing an array of connection parameters and the
appropriate option to instruct the client about how to aggregate them (clustering, replication or a
custom aggregation logic). Named arrays and URI strings can be mixed when providing configurations
for each node:
```php
$client = new Predis\Client([
'tcp://10.0.0.1?alias=first-node', ['host' => '10.0.0.2', 'alias' => 'second-node'],
], [
'cluster' => 'predis',
]);
```
See the [aggregate connections](#aggregate-connections) section of this document for more details.
Connections to Redis are lazy meaning that the client connects to a server only if and when needed.
While it is recommended to let the client do its own stuff under the hood, there may be times when
it is still desired to have control of when the connection is opened or closed: this can easily be
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.
### Client configuration ###
Many aspects and behaviors of the client can be configured by passing specific client options to the
second argument of `Predis\Client::__construct()`:
```php
$client = new Predis\Client($parameters, ['prefix' => 'sample:']);
```
Options are managed using a mini DI-alike container and their values can be lazily initialized only
when needed. The client options supported by default in Predis are:
- `prefix`: prefix string applied to every key found in commands.
- `exceptions`: whether the client should throw or return responses upon Redis errors.
- `connections`: list of connection backends or a connection factory instance.
- `cluster`: specifies a cluster backend (`predis`, `redis` or callable).
- `replication`: specifies a replication backend (`predis`, `sentinel` or callable).
- `aggregate`: configures the client with a custom aggregate connection (callable).
- `parameters`: list of default connection parameters for aggregate connections.
- `commands`: specifies a command factory instance to use through the library.
Users can also provide custom options with values or callable objects (for lazy initialization) that
are stored in the options container for later use through the library.
### Aggregate connections ###
Aggregate connections are the foundation upon which Predis implements clustering and replication and
they are used to group multiple connections to single Redis nodes and hide the specific logic needed
to handle them properly depending on the context. Aggregate connections usually require an array of
connection parameters along with the appropriate client option when creating a new client instance.
#### Cluster ####
Predis can be configured to work in clustering mode with a traditional client-side sharding approach
to create a cluster of independent nodes and distribute the keyspace among them. This approach needs
some sort of external health monitoring of nodes and requires the keyspace to be rebalanced manually
when nodes are added or removed:
```php
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['cluster' => 'predis'];
$client = new Predis\Client($parameters);
```
Along with Redis 3.0, a new supervised and coordinated type of clustering was introduced in the form
of [redis-cluster](http://redis.io/topics/cluster-tutorial). This kind of approach uses a different
algorithm to distribute the keyspaces, with Redis nodes coordinating themselves by communicating via
a gossip protocol to handle health status, rebalancing, nodes discovery and request redirection. In
order to connect to a cluster managed by redis-cluster, the client requires a list of its nodes (not
necessarily complete since it will automatically discover new nodes if necessary) and the `cluster`
client options set to `redis`:
```php
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['cluster' => 'redis'];
$client = new Predis\Client($parameters, $options);
```
#### Replication ####
The client can be configured to operate in a single master / multiple slaves setup to provide better
service availability. When using replication, Predis recognizes read-only commands and sends them to
a random slave in order to provide some sort of load-balancing and switches to the master as soon as
it detects a command that performs any kind of operation that would end up modifying the keyspace or
the value of a key. Instead of raising a connection error when a slave fails, the client attempts to
fall back to a different slave among the ones provided in the configuration.
The basic configuration needed to use the client in replication mode requires one Redis server to be
identified as the master (this can be done via connection parameters by setting the `role` parameter
to `master`) and one or more slaves (in this case setting `role` to `slave` for slaves is optional):
```php
$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['replication' => 'predis'];
$client = new Predis\Client($parameters, $options);
```
The above configuration has a static list of servers and relies entirely on the client's logic, but
it is possible to rely on [`redis-sentinel`](http://redis.io/topics/sentinel) for a more robust HA
environment with sentinel servers acting as a source of authority for clients for service discovery.
The minimum configuration required by the client to work with redis-sentinel is a list of connection
parameters pointing to a bunch of sentinel instances, the `replication` option set to `sentinel` and
the `service` option set to the name of the service:
```php
$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['replication' => 'sentinel', 'service' => 'mymaster'];
$client = new Predis\Client($sentinels, $options);
```
If the master and slave nodes are configured to require an authentication from clients, a password
must be provided via the global `parameters` client option. This option can also be used to specify
a different database index. The client options array would then look like this:
```php
$options = [
'replication' => 'sentinel',
'service' => 'mymaster',
'parameters' => [
'password' => $secretpassword,
'database' => 10,
],
];
```
While Predis is able to distinguish commands performing write and read-only operations, `EVAL` and
`EVALSHA` represent a corner case in which the client switches to the master node because it cannot
tell when a Lua script is safe to be executed on slaves. While this is indeed the default behavior,
when certain Lua scripts do not perform write operations it is possible to provide an hint to tell
the client to stick with slaves for their execution:
```php
$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
$options = ['replication' => function () {
// Set scripts that won't trigger a switch from a slave to the master node.
$strategy = new Predis\Replication\ReplicationStrategy();
$strategy->setScriptReadOnly($LUA_SCRIPT);
return new Predis\Connection\Replication\MasterSlaveReplication($strategy);
}];
$client = new Predis\Client($parameters, $options);
$client->eval($LUA_SCRIPT, 0); // Sticks to slave using `eval`...
$client->evalsha(sha1($LUA_SCRIPT), 0); // ... and `evalsha`, too.
```
The [`examples`](examples/) directory contains a few scripts that demonstrate how the client can be
configured and used to leverage replication in both basic and complex scenarios.
### Command pipelines ###
Pipelining can help with performances when many commands need to be sent to a server by reducing the
latency introduced by network round-trip timings. Pipelining also works with aggregate connections.
The client can execute the pipeline inside a callable block or return a pipeline instance with the
ability to chain commands thanks to its fluent interface:
```php
// Executes a pipeline inside the given callable block:
$responses = $client->pipeline(function ($pipe) {
for ($i = 0; $i < 1000; $i++) {
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
$pipe->get("key:$i");
}
});
// Returns a pipeline that can be chained thanks to its fluent interface:
$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute();
```
### Transactions ###
The client provides an abstraction for Redis transactions based on `MULTI` and `EXEC` with a similar
interface to command pipelines:
```php
// Executes a transaction inside the given callable block:
$responses = $client->transaction(function ($tx) {
$tx->set('foo', 'bar');
$tx->get('foo');
});
// Returns a transaction that can be chained thanks to its fluent interface:
$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute();
```
This abstraction can perform check-and-set operations thanks to `WATCH` and `UNWATCH` and provides
automatic retries of transactions aborted by Redis when `WATCH`ed keys are touched. For an example
of a transaction using CAS you can see [the following example](examples/transaction_using_cas.php).
### Adding new commands ###
While we try to update Predis to stay up to date with all the commands available in Redis, you might
prefer to stick with an old version of the library or provide a different way to filter arguments or
parse responses for specific commands. To achieve that, Predis provides the ability to implement new
command classes to define or override commands in the default command factory used by the client:
```php
// Define a new command by extending Predis\Command\Command:
class BrandNewRedisCommand extends Predis\Command\Command
{
public function getId()
{
return 'NEWCMD';
}
}
// Inject your command in the current command factory:
$client = new Predis\Client($parameters, [
'commands' => [
'newcmd' => 'BrandNewRedisCommand',
],
]);
$response = $client->newcmd();
```
There is also a method to send raw commands without filtering their arguments or parsing responses.
Users must provide the list of arguments for the command as an array, following the signatures as
defined by the [Redis documentation for commands](http://redis.io/commands):
```php
$response = $client->executeRaw(['SET', 'foo', 'bar']);
```
### Script commands ###
While it is possible to leverage [Lua scripting](http://redis.io/commands/eval) on Redis 2.6+ using
directly [`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha),
Predis offers script commands as an higher level abstraction built upon them to make things simple.
Script commands can be registered in the command factory used by the client and are accessible as if
they were plain Redis commands, but they define Lua scripts that get transmitted to the server for
remote execution. Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and
identify a script by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval)
is used as a fall back when needed:
```php
// Define a new script command by extending Predis\Command\ScriptCommand:
class ListPushRandomValue extends Predis\Command\ScriptCommand
{
public function getKeysCount()
{
return 1;
}
public function getScript()
{
return <<<LUA
math.randomseed(ARGV[1])
local rnd = tostring(math.random())
redis.call('lpush', KEYS[1], rnd)
return rnd
LUA;
}
}
// Inject the script command in the current command factory:
$client = new Predis\Client($parameters, [
'commands' => [
'lpushrand' => 'ListPushRandomValue',
],
]);
$response = $client->lpushrand('random_values', $seed = mt_rand());
```
### Customizable connection backends ###
Predis can use different connection backends to connect to Redis. The builtin Relay integration
leverages the [Relay](https://github.com/cachewerk/relay) extension for PHP for major performance
gains, by caching a partial replica of the Redis dataset in PHP shared runtime memory.
```php
$client = new Predis\Client('tcp://127.0.0.1', [
'connections' => 'relay',
]);
```
Developers can create their own connection classes to support whole new network backends, extend
existing classes or provide completely different implementations. Connection classes must implement
`Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
```php
class MyConnectionClass implements Predis\Connection\NodeConnectionInterface
{
// Implementation goes here...
}
// Use MyConnectionClass to handle connections for the `tcp` scheme:
$client = new Predis\Client('tcp://127.0.0.1', [
'connections' => ['tcp' => 'MyConnectionClass'],
]);
```
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.
## Development ##
### Reporting bugs and contributing code ###
Contributions to Predis are highly appreciated either in the form of pull requests for new features,
bug fixes, or just bug reports. We only ask you to adhere to issue and pull request templates.
### Test suite ###
__ATTENTION__: Do not ever run the test suite shipped with Predis against instances of Redis running
in production environments or containing data you are interested in!
Predis has a comprehensive test suite covering every aspect of the library and that can optionally
perform integration tests against a running instance of Redis (required >= 2.4.0 in order to verify
the correct behavior of the implementation of each command. Integration tests for unsupported Redis
commands are automatically skipped. If you do not have Redis up and running, integration tests can
be disabled. See [the tests README](tests/README.md) for more details about testing this library.
Predis uses GitHub Actions for continuous integration and the history for past and current builds can be
found [on its actions page](https://github.com/predis/predis/actions).
### License ###
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
[ico-license]: https://img.shields.io/github/license/predis/predis.svg?style=flat-square
[ico-version-stable]: https://img.shields.io/github/v/tag/predis/predis?label=stable&style=flat-square
[ico-version-dev]: https://img.shields.io/github/v/tag/predis/predis?include_prereleases&label=pre-release&style=flat-square
[ico-downloads-monthly]: https://img.shields.io/packagist/dm/predis/predis.svg?style=flat-square
[ico-build]: https://img.shields.io/github/actions/workflow/status/predis/predis/tests.yml?branch=main&style=flat-square
[ico-coverage]: https://img.shields.io/coverallsCoverage/github/predis/predis?style=flat-square
[link-releases]: https://github.com/predis/predis/releases
[link-actions]: https://github.com/predis/predis/actions
[link-downloads]: https://packagist.org/packages/predis/predis/stats
[link-coverage]: https://coveralls.io/github/predis/predis
-7
View File
@@ -1,7 +0,0 @@
* Documentation! The README is obviously not enought to show how to use
Predis as it does not cover all of its features.
* Add more tests targeting specific functions of the library.
* Missing tests for commands:
PUBLISH, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE
+1 -1
View File
@@ -1 +1 @@
0.6.2
2.4.0
+12
View File
@@ -0,0 +1,12 @@
<?php
/*
* This file is part of the Predis package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/src/Autoloader.php';
Predis\Autoloader::register();
+274
View File
@@ -0,0 +1,274 @@
#!/usr/bin/env php
<?php
/*
* This file is part of the Predis package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
// -------------------------------------------------------------------------- //
// This script can be used to automatically generate a file with the scheleton
// of a test case to test a Redis command by specifying the name of the class
// in the Predis\Command namespace (only classes in this namespace are valid).
// 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
//
// Here is a list of optional arguments:
//
// --realm: each command has its own realm (commands that operate on strings,
// lists, sets and such) but while this realm is usually inferred from the name
// of the specified class, sometimes it can be useful to override it with a
// custom one.
//
// --output: write the generated test case to the specified path instead of
// the default one.
//
// --overwrite: pre-existing test files are not overwritten unless this option
// is explicitly specified.
// -------------------------------------------------------------------------- //
use Predis\Command\CommandInterface;
use Predis\Command\PrefixableCommandInterface;
class CommandTestCaseGenerator
{
private $options;
public function __construct(array $options)
{
if (!isset($options['class'])) {
throw new RuntimeException("Missing 'class' option.");
}
if (!isset($options['realm'])) {
throw new RuntimeException("Missing 'realm' option.");
}
$this->options = $options;
}
public static function fromCommandLine()
{
$parameters = array(
'c:' => 'class:',
'r::' => 'realm::',
'o::' => 'output::',
'x::' => 'overwrite::'
);
$getops = getopt(implode(array_keys($parameters)), $parameters);
$options = array(
'overwrite' => false,
'tests' => __DIR__.'/../tests/Predis',
);
foreach ($getops as $option => $value) {
switch ($option) {
case 'c':
case 'class':
$options['class'] = $value;
break;
case 'r':
case 'realm':
$options['realm'] = $value;
break;
case 'o':
case 'output':
$options['output'] = $value;
break;
case 'x':
case 'overwrite':
$options['overwrite'] = true;
break;
}
}
if (!isset($options['class'])) {
throw new RuntimeException("Missing 'class' option.");
}
if (!isset($options['realm'])) {
throw new RuntimeException("Missing 'realm' option.");
}
$options['fqn'] = "Predis\\Command\\Redis\\{$options['class']}";
$options['path'] = "Command/Redis/{$options['class']}.php";
$source = __DIR__.'/../src/'.$options['path'];
if (!file_exists($source)) {
throw new RuntimeException("Cannot find class file for {$options['fqn']} in $source.");
}
if (!isset($options['output'])) {
$options['output'] = sprintf("%s/%s", $options['tests'], str_replace('.php', '_Test.php', $options['path']));
}
return new self($options);
}
protected function getTestRealm()
{
if (empty($this->options['realm'])) {
throw new RuntimeException('Invalid value for realm has been specified (empty).');
}
return $this->options['realm'];
}
public function generate()
{
$reflection = new ReflectionClass($class = $this->options['fqn']);
if (!$reflection->isInstantiable()) {
throw new RuntimeException("Class $class must be instantiable, abstract classes or interfaces are not allowed.");
}
if (!$reflection->implementsInterface('Predis\Command\CommandInterface')) {
throw new RuntimeException("Class $class must implement Predis\Command\CommandInterface.");
}
/*
* @var CommandInterface
*/
$instance = $reflection->newInstance();
$buffer = $this->getTestCaseBuffer($instance);
return $buffer;
}
public function save()
{
$options = $this->options;
if (file_exists($options['output']) && !$options['overwrite']) {
throw new RuntimeException("File {$options['output']} already exist. Specify the --overwrite option to overwrite the existing file.");
}
file_put_contents($options['output'], $this->generate());
}
protected function getTestCaseBuffer(CommandInterface $instance)
{
$id = $instance->getId();
$fqn = get_class($instance);
$fqnParts = explode('\\', $fqn);
$class = array_pop($fqnParts) . "Test";
$realm = $this->getTestRealm();
$buffer =<<<PHP
<?php
/*
* This file is part of the Predis package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
/**
* @group commands
* @group realm-$realm
*/
class $class extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return '$fqn';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return '$id';
}
/**
* @group disconnected
*/
public function testFilterArguments(): void
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$arguments = array(/* add arguments */);
\$expected = array(/* add arguments */);
\$command = \$this->getCommand();
\$command->setArguments(\$arguments);
\$this->assertSame(\$expected, \$command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse(): void
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$raw = null;
\$expected = null;
\$command = \$this->getCommand();
\$this->assertSame(\$expected, \$command->parseResponse(\$raw));
}
PHP;
if ($instance instanceof PrefixableCommandInterface) {
$buffer .=<<<PHP
/**
* @group disconnected
*/
public function testPrefixKeys(): void
{
\$this->markTestIncomplete('This test has not been implemented yet.');
\$arguments = array(/* add arguments */);
\$expected = array(/* add arguments */);
\$command = \$this->getCommandWithArgumentsArray(\$arguments);
\$command->prefixKeys('prefix:');
\$this->assertSame(\$expected, \$command->getArguments());
}
/**
* @group disconnected
*/
public function testPrefixKeysIgnoredOnEmptyArguments(): void
{
\$command = \$this->getCommand();
\$command->prefixKeys('prefix:');
\$this->assertSame(array(), \$command->getArguments());
}
PHP;
}
return "$buffer}\n";
}
}
// ------------------------------------------------------------------------- //
require __DIR__.'/../autoload.php';
$generator = CommandTestCaseGenerator::fromCommandLine();
$generator->save();
+52
View File
@@ -0,0 +1,52 @@
{
"name": "predis/predis",
"type": "library",
"description": "A flexible and feature-complete Redis/Valkey client for PHP.",
"keywords": ["nosql", "redis", "predis"],
"homepage": "http://github.com/predis/predis",
"license": "MIT",
"support": {
"issues": "https://github.com/predis/predis/issues"
},
"authors": [
{
"name": "Till Krüss",
"homepage": "https://till.im",
"role": "Maintainer"
}
],
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/tillkruss"
}
],
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^8.0 || ^9.4",
"phpunit/phpcov": "^6.0 || ^8.0"
},
"suggest": {
"ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
},
"scripts": {
"phpstan": "phpstan analyse",
"style": "php-cs-fixer fix --diff --dry-run",
"style:fix": "php-cs-fixer fix"
},
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"config": {
"sort-packages": true,
"preferred-install": "dist"
},
"minimum-stability": "dev",
"prefer-stable": true
}
-38
View File
@@ -1,38 +0,0 @@
<?php
require_once 'SharedConfigurations.php';
// When you have a whole set of consecutive commands to send to
// a redis server, you can use a pipeline to improve performances.
$redis = new Predis\Client($single_server);
$replies = $redis->pipeline(function($pipe) {
$pipe->ping();
$pipe->flushdb();
$pipe->incrby('counter', 10);
$pipe->incrby('counter', 30);
$pipe->exists('counter');
$pipe->get('counter');
$pipe->mget('does_not_exist', 'counter');
});
print_r($replies);
/* OUTPUT:
Array
(
[0] => 1
[1] => 1
[2] => 10
[3] => 40
[4] => 1
[5] => 40
[6] => Array
(
[0] =>
[1] => 40
)
)
*/
?>
@@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../../shared.php';
// Example of JSON.DEBUG command usage:
// 1. Set JSON object
$client = new Client();
$client->jsonset('key', '$', '{"key1":"value1","key2":"value2"}');
// 2. Dump information about json memory usage in bytes
$response = $client->jsondebug->memory('key', '$');
echo 'Response:' . "\n";
print_r($response);
+52
View File
@@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\SchemaFields\AbstractField;
use Predis\Command\Argument\Search\SchemaFields\NumericField;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.AGGREGATE command usage:
// 1. Create index
$client = new Client();
$ftCreateArguments = (new CreateArguments())->prefix(['user:']);
$schema = [
new TextField('name'),
new TextField('country'),
new NumericField('dob', '', AbstractField::SORTABLE),
];
$client->ftcreate('idx', $schema, $ftCreateArguments);
// 2. Add documents
$client->hset('user:0', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
$client->hset('user:1', 'name', 'Vlad', 'country', 'Israel', 'dob', 782265600);
$client->hset('user:2', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
// 3. Execute aggregation query
$ftAggregateArguments = (new AggregateArguments())
->apply('year(@dob)', 'birth')
->groupBy('@country', '@birth')
->reduce('COUNT', true, 'country_birth_Vlad_count')
->sortBy(0, '@birth', 'DESC');
$response = $client->ftaggregate('idx', '@name: "Vlad"', $ftAggregateArguments);
// Response grouped by user country and birth year, with users count in each group, sorted by birth year from DESC.
echo 'Response:' . "\n";
print_r($response);
+41
View File
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.ALTER command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_alter', $schema);
echo 'Default index attributes:' . "\n";
$defaultAttributes = $client->ftinfo('index_alter');
print_r($defaultAttributes[7]);
// 2. Add additional attribute to existing index
$schema = [
new TextField('new_field_name'),
];
$client->ftalter('index_alter', $schema);
echo 'Updated index attributes:' . "\n";
$updatedAttributes = $client->ftinfo('index_alter');
print_r($updatedAttributes[7]);
@@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../../shared.php';
// Example of FT.CONFIG HELP command usage:
// 1. Dump helpful information about FT.CONFIG MAXEXPANSIONS option
$client = new Client();
echo 'Response:' . "\n";
print_r(
$client->ftconfig->help('MAXEXPANSIONS')
);
@@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../../shared.php';
// Example of FT.CONFIG SET command usage:
// 1. Change default timeout setting
$client = new Client();
echo 'Response:' . "\n";
print_r(
$client->ftconfig->set('TIMEOUT', 42)
);
print_r(
$client->ftconfig->get('TIMEOUT')
);
@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\SchemaFields\AbstractField;
use Predis\Command\Argument\Search\SchemaFields\NumericField;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.CURSOR DEL command usage
// 1. Create index
$client = new Client();
$ftCreateArguments = (new CreateArguments())->prefix(['user:']);
$schema = [
new TextField('name'),
new TextField('country'),
new NumericField('dob', '', AbstractField::SORTABLE),
];
$client->ftcreate('index_cursor_del', $schema, $ftCreateArguments);
// 2. Add documents
$client->hset('user:0', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
$client->hset('user:1', 'name', 'Vlad', 'country', 'Israel', 'dob', 782265600);
$client->hset('user:2', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
// 3. Execute aggregation query
$ftAggregateArguments = (new AggregateArguments())
->apply('year(@dob)', 'birth')
->groupBy('@country', '@birth')
->reduce('COUNT', true, 'country_birth_Vlad_count')
->sortBy(0, '@birth', 'DESC')
->withCursor(1);
[$_, $cursor] = $client->ftaggregate('index_cursor_del', '@name: "Vlad"', $ftAggregateArguments);
// 4. Explicitly remove returned cursor
$client->ftcursor->del('index_cursor_del', $cursor);
echo "Cursor with cursorId - {$cursor} was removed";
@@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\SchemaFields\AbstractField;
use Predis\Command\Argument\Search\SchemaFields\NumericField;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.CURSOR READ command usage
// 1. Create index
$client = new Client();
$ftCreateArguments = (new CreateArguments())->prefix(['user:']);
$schema = [
new TextField('name'),
new TextField('country'),
new NumericField('dob', '', AbstractField::SORTABLE),
];
$client->ftcreate('index_cursor_read', $schema, $ftCreateArguments);
// 2. Add documents
$client->hset('user:0', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
$client->hset('user:1', 'name', 'Vlad', 'country', 'Israel', 'dob', 782265600);
$client->hset('user:2', 'name', 'Vlad', 'country', 'Ukraine', 'dob', 813801600);
// 3. Execute aggregation query
$ftAggregateArguments = (new AggregateArguments())
->apply('year(@dob)', 'birth')
->groupBy('@country', '@birth')
->reduce('COUNT', true, 'country_birth_Vlad_count')
->sortBy(0, '@birth', 'DESC')
->withCursor(1);
[$response, $cursor] = $client->ftaggregate('index_cursor_read', '@name: "Vlad"', $ftAggregateArguments);
// 4. Processing response in loop until cursorId exists
$actualResponse = [];
$cursors = [];
while ($cursor) {
$actualResponse[] = $response[1];
$cursors[] = $cursor;
[$response, $cursor] = $client->ftcursor->read('index_cursor_read', $cursor);
}
echo "Response: \n";
print_r($actualResponse);
+32
View File
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.EXPLAIN command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_explain', $schema);
// 2. Run query explanations
$response = $client->ftexplain('index_explain', '(foo bar)|(hello world) @date:[100 200]|@date:[500 +inf]');
echo 'Response:' . "\n";
print_r($response);
+38
View File
@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.PROFILE command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_profile', $schema);
// 2. Create FT.PROFILE command arguments
$arguments = (new ProfileArguments())
->search()
->query('query');
// 3. Run profile query
$response = $client->ftprofile('index_profile', $arguments);
echo 'Response:' . "\n";
print_r($response);
@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SchemaFields\TextField;
use Predis\Command\Argument\Search\SpellcheckArguments;
require __DIR__ . '/../../shared.php';
// Example of FT.SPELLCHECK command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_spellcheck', $schema);
// 2. Add dictionary with terms
$client->ftdictadd('dict', 'hello', 'help');
// 3. Perform spelling correction query
$response = $client->ftspellcheck(
'index_spellcheck',
'held',
(new SpellcheckArguments())->distance(2)->terms('dict')
);
echo 'Response:' . "\n";
print_r($response);
@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SugAddArguments;
use Predis\Command\Argument\Search\SugGetArguments;
require __DIR__ . '/../../shared.php';
// Example of FT.SUGADD, FT.SUGGET, FT.SUGDEL, FT.SUGLEN commands usage:
// 1. Add suggestion to key with payload
$client = new Client();
$client->ftsugadd('key', 'hello', 2, (new SugAddArguments())->payload('payload'));
echo 'Suggestions dictionary length: ' . $client->ftsuglen('key') . "\n";
// 2. Perform fuzzy search by prefix to get previous suggestion with payload
$response = $client->ftsugget('key', 'hellp', (new SugGetArguments())->fuzzy()->withPayloads());
echo 'Suggestion for "hellp" prefix:' . "\n";
print_r($response);
// 3. Removes previous suggestion from key
$client->ftsugdel('key', 'hello');
$response = $client->ftsugget('key', 'hello');
echo 'Suggestions, after removing "hello" suggestion:' . "\n";
print_r($response);
+35
View File
@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.SYNDUMP command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_syndump', $schema);
// 2. Add synonyms group with terms
$client->ftsynupdate('index_syndump', 'synonym1', null, 'term1', 'term2');
// 3. Dump terms with synonyms
$response = $client->ftsyndump('index_syndump');
echo 'Response:' . "\n";
print_r($response);
+32
View File
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\SchemaFields\TextField;
require __DIR__ . '/../../shared.php';
// Example of FT.SYNUPDATE command usage:
// 1. Create index
$client = new Client();
$schema = [
new TextField('text_field'),
];
$client->ftcreate('index_synupdate', $schema);
// 2. Add synonyms into synonym group
$response = $client->ftsynupdate('index_synupdate', 'synonym1', null, 'term1', 'term2');
echo 'Response:' . "\n";
print_r($response);
+37
View File
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\SchemaFields\TagField;
require __DIR__ . '/../../shared.php';
// Example of FT.TAGVALS command usage:
// 1. Create index
$client = new Client();
$schema = [
new TagField('tag_field'),
];
$client->ftcreate('index_tagvals', $schema, (new CreateArguments())->prefix(['prefix:']));
// 2. Add indexed tags
$client->hset('prefix:1', 'tag_field', 'Hello, World');
$client->hset('prefix:2', 'tag_field', 'Hey, World');
// 3. Unique tags value query
$response = $client->fttagvals('index_tagvals', 'tag_field');
echo 'Response:' . "\n";
print_r($response);
+38
View File
@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.ADD command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Add sample into newly created time series
$addArguments = (new AddArguments())
->retentionMsecs(31536000000);
$response = $client->tsadd('temperature:2:32', 123123123123, 27, $addArguments);
echo "Timeseries was added with timestamp: {$response}";
+41
View File
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\AlterArguments;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.ALTER command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$response = $client->tscreate('temperature:2:32', $arguments);
echo "Time series creation status: {$response}\n";
// 2. Update Duplicate policy for time series above
$arguments = (new AlterArguments())
->duplicatePolicy(CommonArguments::POLICY_FIRST);
$response = $client->tsalter('temperature:2:32', $arguments);
$output = ($response == 'OK') ? 'Duplicate policy was successfully updated' : $response;
echo $output;
@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.CREATE command usage:
// Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$response = $client->tscreate('temperature:2:32', $arguments);
echo "Time series creation status: {$response}";
@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.CREATERULE command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->labels('type', 'temp', 'location', 'TLV');
$createResponse = $client->tscreate('temp:TLV', $arguments);
echo "Original time series creation status: {$createResponse}\n";
$createResponse = $client->tscreate('dailyAvgTemp:TLV', $arguments);
echo "Compacted time series creation status: {$createResponse}\n";
$createRuleResponse = $client->tscreaterule('temp:TLV', 'dailyAvgTemp:TLV', 'avg', 1000);
echo "Compacted rule for compacted time series creation status: {$createRuleResponse}\n";
@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\DecrByArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.DECRBY command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Add sample into newly created time series
$addArguments = (new AddArguments())
->retentionMsecs(31536000000);
$response = $client->tsadd('temperature:2:32', 123123123123, 27, $addArguments);
echo "Timeseries was added with timestamp: {$response}\n";
// 3. Increasing value and timestamp
$client->tsdecrby('temperature:2:32', 1, (new DecrByArguments())->timestamp(123123123124));
$response = $client->tsget('temperature:2:32');
echo "Decreased value to - {$response[1]} and timestamp to {$response[0]}";
+47
View File
@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.GET command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Add samples into time series
$client->tsadd('temperature:2:32', 123123123123, 27);
$client->tsadd('temperature:2:32', 123123123124, 28);
$client->tsadd('temperature:2:32', 123123123125, 29);
$response = $client->tsget('temperature:2:32');
echo "Sample with highest timestamp - {$response[0]} and value {$response[1]}\n";
// 3. Removes 2 samples with the highest timestamps
$response = $client->tsdel('temperature:2:32', 123123123124, 123123123125);
echo "Removed {$response} samples from timeseries.\n";
// 3. Retrieve a timestamp with the highest timestamp
$response = $client->tsget('temperature:2:32');
echo "New sample with highest timestamp - {$response[0]} and value {$response[1]}";
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.CREATERULE command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->labels('type', 'temp', 'location', 'TLV');
$createResponse = $client->tscreate('temp:TLV', $arguments);
echo "Original time series creation status: {$createResponse}\n";
$createResponse = $client->tscreate('dailyAvgTemp:TLV', $arguments);
echo "Compacted time series creation status: {$createResponse}\n";
$createRuleResponse = $client->tscreaterule('temp:TLV', 'dailyAvgTemp:TLV', 'avg', 1000);
echo "Compacted rule for compacted time series creation status: {$createRuleResponse}\n";
// 2. Remove compaction rule
$deleteRuleResponse = $client->tsdeleterule('temp:TLV', 'dailyAvgTemp:TLV');
echo "Compacted rule for compacted time series deletion status: {$deleteRuleResponse}\n";
+38
View File
@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.GET command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Add samples into time series
$client->tsadd('temperature:2:32', 123123123123, 27);
$client->tsadd('temperature:2:32', 123123123124, 28);
$client->tsadd('temperature:2:32', 123123123125, 29);
// 3. Retrieve a timestamp with highest timestamp
$response = $client->tsget('temperature:2:32');
echo "Sample with highest timestamp - {$response[0]} and value - {$response[1]}";
@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\IncrByArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.INCRBY command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Add sample into newly created time series
$addArguments = (new AddArguments())
->retentionMsecs(31536000000);
$response = $client->tsadd('temperature:2:32', 123123123123, 27, $addArguments);
echo "Timeseries was added with timestamp: {$response}\n";
// 3. Increasing value and timestamp
$client->tsincrby('temperature:2:32', 1, (new IncrByArguments())->timestamp(123123123124));
$response = $client->tsget('temperature:2:32');
echo "Increased value to - {$response[1]} and timestamp to {$response[0]}";
+32
View File
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.CREATE command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
// 2. Show info about given time series
print_r($client->tsinfo('temperature:2:32'));
+36
View File
@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.MADD command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
$client->tscreate('temperature:2:33', $arguments);
// 2. Add samples into few time series
$response = $client->tsmadd('temperature:2:32', 123123123123, 27, 'temperature:2:33', 123123123124, 28);
$stringResponse = implode(', ', $response);
echo "Samples was added to time series - timestamps: {$stringResponse}";
+41
View File
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CommonArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\MGetArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.MGET command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->retentionMsecs(60000)
->duplicatePolicy(CommonArguments::POLICY_MAX)
->labels('type', 'temp', 'sensor_id', 2, 'area_id', 32);
$client->tscreate('temperature:2:32', $arguments);
$client->tscreate('temperature:2:33', $arguments);
// 2. Add samples into time series
$client->tsadd('temperature:2:32', 123123123123, 27);
$client->tsadd('temperature:2:33', 123123123124, 27);
// 3. Get sample from multiple time series matching given filter expression, with selected labels only
$response = $client->tsmget((new MGetArguments())->selectedLabels('type'), 'type=temp');
echo "Sample from time series, with label = 'type':\n";
print_r($response);
@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.MRANGE command usage:
// 1. Create time series
$client = new Client();
$response = $client->tscreate('stock:A', (new CreateArguments())->labels('type', 'stock', 'name', 'A'));
echo "Time series A creation status: {$response}\n";
$response = $client->tscreate('stock:B', (new CreateArguments())->labels('type', 'stock', 'name', 'B'));
echo "Time series B creation status: {$response}\n";
// 2. Add samples into both time series
$response = $client->tsmadd('stock:A', 1000, 100, 'stock:A', 1010, 110, 'stock:A', 1020, 120);
$stringResponse = implode(', ', $response);
echo "Added samples into time series A with following timestamps: {$stringResponse}\n";
$response = $client->tsmadd('stock:B', 1000, 120, 'stock:B', 1010, 110, 'stock:B', 1020, 100);
$stringResponse = implode(', ', $response);
echo "Added samples into time series B with following timestamps: {$stringResponse}\n";
// 3. Query range across both time series filtered by "type" and grouped by max type
$mrangeArguments = (new MRangeArguments())
->withLabels()
->filter('type=stock')
->groupBy('type', 'max');
$response = $client->tsmrange('-', '+', $mrangeArguments);
echo "Response:\n";
print_r($response);
@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.MREVRANGE command usage:
// 1. Create time series
$client = new Client();
$response = $client->tscreate('stock:A', (new CreateArguments())->labels('type', 'stock', 'name', 'A'));
echo "Time series A creation status: {$response}\n";
$response = $client->tscreate('stock:B', (new CreateArguments())->labels('type', 'stock', 'name', 'B'));
echo "Time series B creation status: {$response}\n";
// 2. Add samples into both time series
$response = $client->tsmadd('stock:A', 1000, 100, 'stock:A', 1010, 110, 'stock:A', 1020, 120);
$stringResponse = implode(', ', $response);
echo "Added samples into time series A with following timestamps: {$stringResponse}\n";
$response = $client->tsmadd('stock:B', 1000, 120, 'stock:B', 1010, 110, 'stock:B', 1020, 100);
$stringResponse = implode(', ', $response);
echo "Added samples into time series B with following timestamps: {$stringResponse}\n";
// 3. Query range across both time series filtered by "type" and grouped by max type
$mrangeArguments = (new MRangeArguments())
->withLabels()
->filter('type=stock')
->groupBy('type', 'max');
$response = $client->tsmrevrange('-', '+', $mrangeArguments);
echo "Response:\n";
print_r($response);
@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.QUERYINDEX command usage:
// 1. Create time series
$client = new Client();
$arguments = (new CreateArguments())
->labels('type', 'temp', 'location', 'TLV');
$createResponse = $client->tscreate('temp:TLV', $arguments);
echo "Time series with location TLV creation status: {$createResponse}\n";
$anotherArguments = (new CreateArguments())
->labels('type', 'temp', 'location', 'JER');
$createResponse = $client->tscreate('temp:JER', $anotherArguments);
echo "Time series with location JER creation status: {$createResponse}\n";
echo "Returns all keys with location=TLV:\n";
print_r($client->tsqueryindex('location=TLV'));
+40
View File
@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.RANGE command usage:
// 1. Create time series
$client = new Client();
$createArguments = (new CreateArguments())->labels('type', 'temp', 'location', 'TLV');
$createResponse = $client->tscreate('temp:TLV', $createArguments);
echo "Time series creation status: {$createResponse}\n";
// 2. Add samples into time series
$maddResponse = $client->tsmadd('temp:TLV', 1000, 30, 'temp:TLV', 1010, 35, 'temp:TLV', 1020, 9999, 'temp:TLV', 1030, 40);
$stringResponse = implode(', ', $maddResponse);
echo "Samples was added with following timestamps: {$stringResponse}\n";
// 3. Query samples by values in the given range
$rangeArguments = (new RangeArguments())->filterByValue(-100, 100);
$rangeResponse = $client->tsrange('temp:TLV', '-', '+', $rangeArguments);
echo "Samples with temperature in range -100 to 100 degrees:\n";
print_r($rangeResponse);
@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
use Predis\Command\Argument\TimeSeries\CreateArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
require __DIR__ . '/../../shared.php';
// Example of TS.REVRANGE command usage:
// 1. Create time series
$client = new Client();
$createArguments = (new CreateArguments())->labels('type', 'temp', 'location', 'TLV');
$createResponse = $client->tscreate('temp:TLV', $createArguments);
echo "Time series creation status: {$createResponse}\n";
// 2. Add samples into time series
$maddResponse = $client->tsmadd('temp:TLV', 1000, 30, 'temp:TLV', 1010, 35, 'temp:TLV', 1020, 9999, 'temp:TLV', 1030, 40);
$stringResponse = implode(', ', $maddResponse);
echo "Samples was added with following timestamps: {$stringResponse}\n";
// 3. Query samples by values in the given range
$rangeArguments = (new RangeArguments())->filterByValue(-100, 100);
$rangeResponse = $client->tsrevrange('temp:TLV', '-', '+', $rangeArguments);
echo "Samples with temperature in range -100 to 100 degrees in reverse order:\n";
print_r($rangeResponse);
+36
View File
@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of ACL DRYRUN command usage:
// 1. Set user with permissions to call only 'SET' command.
$client = new Client($single_server);
$response = $client->acl->setUser('Test_dry', '+SET', '~*');
$created = ($response == 'OK') ? 'Yes' : 'No';
echo "User with username 'Test' was created: {$created}. Permissions only to use SET command\n";
// 2. Dry run 'SET' command under 'Test_dry' user
$response = $client->acl->dryRun('Test_dry', 'SET', 'foo', 'bar');
echo 'Dry run "SET" command.' . "\n";
echo 'Response: ' . $response . "\n";
// 3. Dry run 'GET' command under 'Test_dry' user
$response = $client->acl->dryRun('Test_dry', 'GET', 'foo');
echo 'Dry run "GET" command.' . "\n";
echo 'Response: ' . $response;
+28
View File
@@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of ACL GETUSER command usage:
// 1. Set user
$client = new Client($single_server);
$response = $client->acl->setUser('Test');
// 2. Retrieve user rules:
echo 'Rules: ' . "\n";
print_r(
$client->acl->getUser('Test')
);
+24
View File
@@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of ACL SETUSER command usage:
// 1. Set user
$client = new Client($single_server);
$response = $client->acl->setUser('Test');
$created = ($response == 'OK') ? 'Yes' : 'No';
echo "User with username 'Test' was created: {$created}";
+43
View File
@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of FCALL_RO command usage:
// 1. Set key-value pair
$client = new Client($single_server);
$client->set('foo', 'bar');
echo "Set key 'foo' with value 'bar'\n";
// 2. Load redis function with 'no-writes' flag
$client->function->load(
"#!lua name=mylib
redis.register_function{
function_name='myfunc',
callback=function(keys, args) return redis.call('GET', keys[1]) end,
flags={'no-writes'}
}"
);
echo 'Loaded custom function that perform GET command against provided key.' . "\n";
// 3. Call function above with given key
$response = $client->fcall_ro('myfunc', ['foo']);
echo "Function returned value against provided key 'foo' is '{$response}'";
// 4. Delete test library
$client->function->delete('mylib');
+41
View File
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of WAITAOF command usage:
// 1. Enable appendonly mode if it's not (command works only in appendonly mode)
$client = new Client($single_server);
$info = $client->info();
$enabled = false;
if ($info['Persistence']['aof_enabled'] === '0') {
$client->config('set', 'appendonly', 'yes');
$enabled = true;
}
// 2. Set key value pair
$response = $client->set('foo', 'bar');
echo "Key-value pair set status: {$response}\n";
// 3. Run WAITAOF command to make sure that all previous writes was fsynced
$response = $client->waitaof(1, 0, 0);
echo "Quantity of local instances that was fsynced - {$response[0]}, quantity of replicas - {$response[1]}";
// 4. Disable appendonly mode if it was enabled during script execution
if ($enabled) {
$client->config('set', 'appendonly', 'no');
}
-60
View File
@@ -1,60 +0,0 @@
<?php
require_once 'SharedConfigurations.php';
// Developers can customize the distribution strategy used by the client
// to distribute keys among a cluster of servers simply by creating a class
// that implements the Predis\Distribution\IDistributionAlgorithm interface.
class NaiveDistributionStrategy
implements Predis\Distribution\IDistributionStrategy {
private $_nodes, $_nodesCount;
public function __constructor() {
$this->_nodes = array();
$this->_nodesCount = 0;
}
public function add($node, $weight = null) {
$this->_nodes[] = $node;
$this->_nodesCount++;
}
public function remove($node) {
$this->_nodes = array_filter($this->_nodes, function($n) use($node) {
return $n !== $node;
});
$this->_nodesCount = count($this->_nodes);
}
public function get($key) {
$count = $this->_nodesCount;
if ($count === 0) {
throw new RuntimeException('No connections');
}
return $this->_nodes[$count > 1 ? abs(crc32($key) % $count) : 0];
}
public function generateKey($value) {
return crc32($value);
}
}
$options = array(
'key_distribution' => new NaiveDistributionStrategy(),
);
$redis = new Predis\Client($multiple_servers, $options);
for ($i = 0; $i < 100; $i++) {
$redis->set("key:$i", str_pad($i, 4, '0', 0));
$redis->get("key:$i");
}
$server1 = $redis->getClientFor('first')->info();
$server2 = $redis->getClientFor('second')->info();
printf("Server '%s' has %d keys while server '%s' has %d keys.\n",
'first', $server1['db15']['keys'], 'second', $server2['db15']['keys']
);
?>
-29
View File
@@ -1,29 +0,0 @@
<?php
require_once 'SharedConfigurations.php';
// redis can set keys and their relative values in one go
// using MSET, then the same values can be retrieved with
// a single command using MGET.
$mkv = array(
'usr:0001' => 'First user',
'usr:0002' => 'Second user',
'usr:0003' => 'Third user'
);
$redis = new Predis\Client($single_server);
$redis->mset($mkv);
$retval = $redis->mget(array_keys($mkv));
print_r($retval);
/* OUTPUT:
Array
(
[0] => First user
[1] => Second user
[2] => Third user
)
*/
?>
-52
View File
@@ -1,52 +0,0 @@
<?php
require_once 'SharedConfigurations.php';
// Redis 2.0 features new commands that allow clients to subscribe for
// events published on certain channels (PUBSUB).
// Create a client and disable r/w timeout on the socket
$redis = new Predis\Client($single_server + array('read_write_timeout' => -1));
// Initialize a new pubsub context
$pubsub = $redis->pubSubContext();
// Subscribe to your channels
$pubsub->subscribe('control_channel');
$pubsub->subscribe('notifications');
// Start processing the pubsup messages. Open a terminal and use redis-cli
// to push messages to the channels. Examples:
// ./redis-cli PUBLISH notifications "this is a test"
// ./redis-cli PUBLISH control_channel quit_loop
foreach ($pubsub as $message) {
switch ($message->kind) {
case 'subscribe':
echo "Subscribed to {$message->channel}\n";
break;
case 'message':
if ($message->channel == 'control_channel') {
if ($message->payload == 'quit_loop') {
echo "Aborting pubsub loop...\n";
$pubsub->unsubscribe();
}
else {
echo "Received an unrecognized command: {$message->payload}.\n";
}
}
else {
echo "Received the following message from {$message->channel}:\n",
" {$message->payload}\n\n";
}
break;
}
}
// Always unset the pubsub context instance when you are done! The
// class destructor will take care of cleanups and prevent protocol
// desynchronizations between the client and the server.
unset($pubsub);
// Say goodbye :-)
$info = $redis->info();
print_r("Goodbye from Redis v{$info['redis_version']}!\n");
?>
-24
View File
@@ -1,24 +0,0 @@
<?php
require_once '../lib/Predis.php';
$single_server = array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15
);
$multiple_servers = array(
array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
'alias' => 'first',
),
array(
'host' => '127.0.0.1',
'port' => 6380,
'database' => 15,
'alias' => 'second',
),
);
?>
-16
View File
@@ -1,16 +0,0 @@
<?php
require_once 'SharedConfigurations.php';
// simple set and get scenario
$redis = new Predis\Client($single_server);
$redis->set('library', 'predis');
$retval = $redis->get('library');
print_r($retval);
/* OUTPUT
predis
*/
?>
+118
View File
@@ -0,0 +1,118 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Developers can implement Predis\Distribution\DistributorInterface to create
// their own distributors used by the client to distribute keys among a cluster
// of servers.
use Predis\Cluster\Distributor\DistributorInterface;
use Predis\Cluster\Hash\HashGeneratorInterface;
use Predis\Cluster\PredisStrategy;
use Predis\Connection\Cluster\PredisCluster;
class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
{
private $nodes;
private $nodesCount;
public function __construct()
{
$this->nodes = [];
$this->nodesCount = 0;
}
public function add($node, $weight = null)
{
$this->nodes[] = $node;
++$this->nodesCount;
}
public function remove($node)
{
$this->nodes = array_filter($this->nodes, function ($n) use ($node) {
return $n !== $node;
});
$this->nodesCount = count($this->nodes);
}
public function getSlot($hash)
{
return $this->nodesCount > 1 ? abs($hash % $this->nodesCount) : 0;
}
public function getBySlot($slot)
{
return $this->nodes[$slot] ?? null;
}
public function getByHash($hash)
{
if (!$this->nodesCount) {
throw new RuntimeException('No connections.');
}
$slot = $this->getSlot($hash);
$node = $this->getBySlot($slot);
return $node;
}
public function get($value)
{
$hash = $this->hash($value);
$node = $this->getByHash($hash);
return $node;
}
public function hash($value)
{
return crc32($value);
}
public function getHashGenerator()
{
return $this;
}
}
$options = [
'cluster' => function () {
$distributor = new NaiveDistributor();
$strategy = new PredisStrategy($distributor);
$cluster = new PredisCluster($strategy);
return $cluster;
},
];
$client = new Predis\Client($multiple_servers, $options);
for ($i = 0; $i < 100; ++$i) {
$client->set("key:$i", str_pad($i, 4, '0', 0));
$client->get("key:$i");
}
$server1 = $client->getClientBy('alias', 'first')->info();
$server2 = $client->getClientBy('alias', 'second')->info();
if (isset($server1['Keyspace'], $server2['Keyspace'])) {
$server1 = $server1['Keyspace'];
$server2 = $server2['Keyspace'];
}
printf("Server '%s' has %d keys while server '%s' has %d keys.\n",
'first', $server1['db15']['keys'], 'second', $server2['db15']['keys']
);
+93
View File
@@ -0,0 +1,93 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This is an example of how you can easily extend an existing connection class
// and trace the execution of commands for debugging purposes. This can be quite
// useful as a starting point to understand how your application interacts with
// Redis.
use Predis\Command\CommandInterface;
use Predis\Connection\StreamConnection;
class SimpleDebuggableConnection extends StreamConnection
{
private $tstart = 0;
private $debugBuffer = [];
public function connect()
{
$this->tstart = microtime(true);
parent::connect();
}
private function storeDebug(CommandInterface $command, $direction)
{
$firtsArg = $command->getArgument(0);
$timestamp = round(microtime(true) - $this->tstart, 4);
$debug = $command->getId();
$debug .= isset($firtsArg) ? " $firtsArg " : ' ';
$debug .= "$direction $this";
$debug .= " [{$timestamp}s]";
$this->debugBuffer[] = $debug;
}
public function writeRequest(CommandInterface $command)
{
parent::writeRequest($command);
$this->storeDebug($command, '->');
}
public function readResponse(CommandInterface $command)
{
$response = parent::readResponse($command);
$this->storeDebug($command, '<-');
return $response;
}
public function getDebugBuffer()
{
return $this->debugBuffer;
}
}
$options = [
'connections' => [
'tcp' => 'SimpleDebuggableConnection',
],
];
$client = new Predis\Client($single_server, $options);
$client->set('foo', 'bar');
$client->get('foo');
$client->info();
var_export($client->getConnection()->getDebugBuffer());
/* OUTPUT:
array (
0 => 'SELECT 15 -> 127.0.0.1:6379 [0.0008s]',
1 => 'SELECT 15 <- 127.0.0.1:6379 [0.001s]',
2 => 'SET foo -> 127.0.0.1:6379 [0.001s]',
3 => 'SET foo <- 127.0.0.1:6379 [0.0011s]',
4 => 'GET foo -> 127.0.0.1:6379 [0.0013s]',
5 => 'GET foo <- 127.0.0.1:6379 [0.0015s]',
6 => 'INFO -> 127.0.0.1:6379 [0.0019s]',
7 => 'INFO <- 127.0.0.1:6379 [0.0022s]',
)
*/
+80
View File
@@ -0,0 +1,80 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This is a basic example on how to use the Predis\DispatcherLoop class.
//
// To see this example in action you can just use redis-cli and publish some
// messages to the 'events' and 'control' channel, e.g.:
// ./redis-cli
// PUBLISH events first
// PUBLISH events second
// PUBLISH events third
// PUBLISH control terminate_dispatcher
// Create a client and disable r/w timeout on the socket
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Return an initialized PubSub consumer instance from the client.
$pubsub = $client->pubSubLoop();
// Create a dispatcher loop instance and attach a bunch of callbacks.
$dispatcher = new Predis\PubSub\DispatcherLoop($pubsub);
// Demonstrate how to use a callable class as a callback for the dispatcher loop.
class EventsListener implements Countable
{
private $events;
public function __construct()
{
$this->events = [];
}
public function count()
{
return count($this->events);
}
public function getEvents()
{
return $this->events;
}
public function __invoke($payload, $dispatcher)
{
$this->events[] = $payload;
}
}
// Attach our callable class to the dispatcher.
$dispatcher->attachCallback('events', $events = new EventsListener());
// Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
});
// Run the dispatcher loop until the callback attached to the 'control' channel
// receives 'terminate_dispatcher' as a message.
$dispatcher->run();
// Display our achievements!
echo "We received {$events->count()} messages!", PHP_EOL;
// Say goodbye :-)
$version = redis_version($client->info());
echo "Goodbye from Redis $version!", PHP_EOL;
+63
View File
@@ -0,0 +1,63 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
$client = new Predis\Client($single_server);
// Plain old SET and GET example...
$client->set('library', 'predis');
$response = $client->get('library');
var_export($response);
echo PHP_EOL;
/* OUTPUT: 'predis' */
// Redis has the MSET and MGET commands to set or get multiple keys in one go,
// cases like this Predis accepts arguments for variadic commands both as a list
// of arguments or an array containing all of the keys and/or values.
$mkv = [
'uid:0001' => '1st user',
'uid:0002' => '2nd user',
'uid:0003' => '3rd user',
];
$client->mset($mkv);
$response = $client->mget(array_keys($mkv));
var_export($response);
echo PHP_EOL;
/* OUTPUT:
array (
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
)
*/
// Predis can also send "raw" commands to Redis. The difference between sending
// commands to Redis the usual way and the "raw" way is that in the latter case
// their arguments are not filtered nor responses coming from Redis are parsed.
$response = $client->executeRaw([
'MGET', 'uid:0001', 'uid:0002', 'uid:0003',
]);
var_export($response);
echo PHP_EOL;
/* OUTPUT:
array (
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
)
*/
+37
View File
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Predis can prefix keys found in commands arguments before sending commands to
// Redis, even for complex commands such as SORT, ZUNIONSTORE and ZINTERSTORE.
// Prefixing keys can be useful to create user-level namespaces for you keyspace
// thus reducing the need for separate logical databases in certain scenarios.
$client = new Predis\Client($single_server, ['prefix' => 'nrk:']);
$client->mset(['foo' => 'bar', 'lol' => 'wut']);
var_export($client->mget('foo', 'lol'));
/*
array (
0 => 'bar',
1 => 'wut',
)
*/
var_export($client->keys('*'));
/*
array (
0 => 'nrk:foo',
1 => 'nrk:lol',
)
*/
+68
View File
@@ -0,0 +1,68 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This example will not work with versions of Redis < 2.6.
//
// Additionally to the EVAL command, the Predis\Command\ScriptCommand class can
// be used to leverage an higher level abstraction for Lua scripting that makes
// scripts appear just like any other command on the client-side. This is basic
// example on how a script-based INCREX command can be defined:
use Predis\Command\ScriptCommand;
class IncrementExistingKeysBy extends ScriptCommand
{
public function getKeysCount()
{
// Tell Predis to use all the arguments but the last one as arguments
// for KEYS. The last one will be used to populate ARGV.
return -1;
}
public function getScript()
{
return <<<LUA
local cmd, insert = redis.call, table.insert
local increment, results = ARGV[1], { }
for idx, key in ipairs(KEYS) do
if cmd('exists', key) == 1 then
insert(results, idx, cmd('incrby', key, increment))
else
insert(results, idx, false)
end
end
return results
LUA;
}
}
$client = new Predis\Client($single_server, [
'commands' => [
'increxby' => 'IncrementExistingKeysBy',
],
]);
$client->mset('foo', 10, 'foobar', 100);
var_export($client->increxby('foo', 'foofoo', 'foobar', 50));
/*
array (
0 => 60,
1 => NULL,
2 => 150,
)
*/
+45
View File
@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This is a basic example on how to use the Predis\Monitor\Consumer class. You
// can use redis-cli to send commands to the same Redis instance your client is
// connected to, and then type "ECHO QUIT_MONITOR" in redis-cli when you want to
// exit the monitor loop and terminate this script in a graceful way.
// Create a client and disable r/w timeout on the socket.
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Use only one instance of DateTime, we will update the timestamp later.
$timestamp = new DateTime();
foreach (($monitor = $client->monitor()) as $event) {
$timestamp->setTimestamp((int) $event->timestamp);
// If we notice a ECHO command with the message QUIT_MONITOR, we stop the
// monitor consumer and then break the loop.
if ($event->command === 'ECHO' && $event->arguments === '"QUIT_MONITOR"') {
echo 'Exiting the monitor loop...', PHP_EOL;
$monitor->stop();
break;
}
echo "* Received {$event->command} on DB {$event->database} at {$timestamp->format(DateTime::W3C)}", PHP_EOL;
if (isset($event->arguments)) {
echo " Arguments: {$event->arguments}", PHP_EOL;
}
}
// Say goodbye :-)
$version = redis_version($client->info());
echo "Goodbye from Redis $version!", PHP_EOL;
+46
View File
@@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// When you have a whole set of consecutive commands to send to a redis server,
// you can use a pipeline to dramatically improve performances. Pipelines can
// greatly reduce the effects of network round-trips.
$client = new Predis\Client($single_server);
$responses = $client->pipeline(function ($pipe) {
$pipe->flushdb();
$pipe->incrby('counter', 10);
$pipe->incrby('counter', 30);
$pipe->exists('counter');
$pipe->get('counter');
$pipe->mget('does_not_exist', 'counter');
});
var_export($responses);
/* OUTPUT:
array (
0 => Predis\Response\Status::__set_state(array(
'payload' => 'OK',
)),
1 => 10,
2 => 40,
3 => true,
4 => '40',
5 => array (
0 => NULL,
1 => '40',
),
)
*/
+60
View File
@@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Starting from Redis 2.0 clients can subscribe and listen for events published
// on certain channels using a Publish/Subscribe (PUB/SUB) approach.
// Create a client and disable r/w timeout on the socket
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Initialize a new pubsub consumer.
$pubsub = $client->pubSubLoop();
// Subscribe to your channels
$pubsub->subscribe('control_channel', 'notifications');
// Start processing the pubsub messages. Open a terminal and use redis-cli
// to push messages to the channels. Examples:
// redis-cli PUBLISH notifications "this is a test"
// redis-cli PUBLISH control_channel quit_loop
foreach ($pubsub as $message) {
switch ($message->kind) {
case 'subscribe':
echo "Subscribed to {$message->channel}", PHP_EOL;
break;
case 'message':
if ($message->channel == 'control_channel') {
if ($message->payload == 'quit_loop') {
echo 'Aborting pubsub loop...', PHP_EOL;
$pubsub->unsubscribe();
} else {
echo "Received an unrecognized command: {$message->payload}.", PHP_EOL;
}
} else {
echo "Received the following message from {$message->channel}:",
PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL;
}
break;
}
}
// Always unset the pubsub consumer instance when you are done! The
// class destructor will take care of cleanups and prevent protocol
// desynchronizations between the client and the server.
unset($pubsub);
// Say goodbye :-)
$version = redis_version($client->info());
echo "Goodbye from Redis $version!", PHP_EOL;
+99
View File
@@ -0,0 +1,99 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
use Predis\Collection\Iterator;
// Starting with Redis 2.8, clients can iterate incrementally over collections
// without blocking the server like it happens when a command such as KEYS is
// executed on a Redis instance storing millions of keys. These commands are:
//
// - SCAN (iterates over the keyspace)
// - SSCAN (iterates over members of a set)
// - ZSCAN (iterates over members and ranks of a sorted set)
// - HSCAN (iterates over fields and values of an hash).
// Predis provides a specialized abstraction for each command based on standard
// SPL iterators making it possible to easily consume SCAN-based iterations in
// your PHP code.
//
// See http://redis.io/commands/scan for more details.
//
$client = new Predis\Client($single_server);
// Prepare some keys for our example
$client->del('predis:set', 'predis:zset', 'predis:hash');
for ($i = 0; $i < 5; ++$i) {
$client->sadd('predis:set', "member:$i");
$client->zadd('predis:zset', -$i, "member:$i");
$client->hset('predis:hash', "field:$i", "value:$i");
}
// === Keyspace iterator based on SCAN ===
echo 'Scan the keyspace matching only our prefixed keys:', PHP_EOL;
foreach (new Iterator\Keyspace($client, 'predis:*') as $key) {
echo " - $key", PHP_EOL;
}
/* OUTPUT
Scan the keyspace matching only our prefixed keys:
- predis:zset
- predis:set
- predis:hash
*/
// === Set iterator based on SSCAN ===
echo 'Scan members of `predis:set`:', PHP_EOL;
foreach (new Iterator\SetKey($client, 'predis:set') as $member) {
echo " - $member", PHP_EOL;
}
/* OUTPUT
Scan members of `predis:set`:
- member:1
- member:4
- member:0
- member:3
- member:2
*/
// === Sorted set iterator based on ZSCAN ===
echo 'Scan members and ranks of `predis:zset`:', PHP_EOL;
foreach (new Iterator\SortedSetKey($client, 'predis:zset') as $member => $rank) {
echo " - $member [rank: $rank]", PHP_EOL;
}
/* OUTPUT
Scan members and ranks of `predis:zset`:
- member:4 [rank: -4]
- member:3 [rank: -3]
- member:2 [rank: -2]
- member:1 [rank: -1]
- member:0 [rank: 0]
*/
// === Hash iterator based on HSCAN ===
echo 'Scan fields and values of `predis:hash`:', PHP_EOL;
foreach (new Iterator\HashKey($client, 'predis:hash') as $field => $value) {
echo " - $field => $value", PHP_EOL;
}
/* OUTPUT
Scan fields and values of `predis:hash`:
- field:0 => value:0
- field:1 => value:1
- field:2 => value:2
- field:3 => value:3
- field:4 => value:4
*/
+51
View File
@@ -0,0 +1,51 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Enable igbinary serializer as well as LZ4 compression
$options = [
'serializer' => 'igbinary',
'compression' => 'lz4',
];
$client = new Predis\Client($single_server + $options, [
'connections' => 'relay',
]);
$quote = (object) [
'author' => 'Jean-Luc Picard',
'text' => 'I look forward to your report Mr. Broccoli.',
];
// Serialize object and apply LZ4 compression, then write key to Redis
$client->set('quote', $client->pack($quote));
// NOTE: In Predis v3.x serialization and compression will happen
// automatically without the need to call `pack()` and `unpack()`
// Retrieve raw binary value from Redis
$raw = $client->get('quote');
// Decompress and unserialize binary value
$data = $client->unpack($raw);
var_dump($quote == $data); // true
var_dump($data);
/*
object(stdClass)#11 (2) {
["author"]=>string(15) "Jean-Luc Picard"
["text"]=>string(43) "I look forward to your report Mr. Broccoli."
}
*/
+55
View File
@@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
$options = [
'timeout' => 1.0,
'read_write_timeout' => 1.0,
// Relay specific options
'cache' => true,
// 'compression' => 'lz4',
// 'serializer' => 'igbinary',
];
$client = new Predis\Client($single_server + $options, [
'connections' => 'relay',
]);
// Write key to Redis
$client->set('torpedo', mt_rand());
// Retrieve key from Redis
$client->get('torpedo');
// Retrieve key from Relay (without talking to Redis)
// This key is now available to all PHP workers in this FPM pool
$client->get('torpedo');
// For debugging only:
var_export(
$client->getConnection()->getClient()->_getKeys()
);
/*
array (
'torpedo' => array (
0 => array (
'type' => 'string',
'local-len' => 10,
'remote-len' => 10,
'size' => 10,
),
),
)
*/
+61
View File
@@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
$key = null;
$client = new Predis\Client($single_server, [
'connections' => 'relay',
]);
/** @var Predis\Connection\RelayConnection $relay */
$relay = $client->getConnection();
// establish connection
$client->ping();
// register `FLUSH*` callback
$relay->onFlushed(
static function (Relay\Event $event) use (&$key) {
echo 'Redis was flushed, unsetting $key...' . PHP_EOL;
$key = null;
}
);
// register `INVALIDATE` callback
$relay->onInvalidated(
static function (Relay\Event $event) use (&$key) {
if ($event->key === 'library') {
echo "The `{$event->key}` key was invalidated, unsetting \$key..." . PHP_EOL;
$key = null;
}
}
);
// Write key to Redis
$client->set('library', mt_rand());
// Retrieve key once from Redis, then cached in Relay and $key
$key = $client->get('library');
while (true) {
echo '$key is: ' . var_export($key, true) . PHP_EOL;
// To trigger our event callbacks, we need to either interact with Relay:
$client->get(mt_rand());
// ... or alternatively dispatch events directly on Relay:
$relay->dispatchEvents();
sleep(1);
}
+59
View File
@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Create a Relay client and disable r/w timeout on the connection
$client = new Predis\Client(
$single_server + ['read_write_timeout' => 0],
['connections' => 'relay']
);
// Initialize a new pubsub consumer.
$pubsub = $client->pubSubLoop();
// When using Relay you cannot use foreach-loops to iterate
// over messages instead use a callback function
$poorMansKafka = function ($message, $client) {
switch ($message->kind) {
case 'subscribe':
echo "Subscribed to {$message->channel}", PHP_EOL;
break;
case 'message':
case 'pmessage':
if ($message->channel == 'control_channel') {
if ($message->payload == 'quit_loop') {
echo 'Aborting pubsub loop...', PHP_EOL;
$client->unsubscribe();
} else {
echo "Received an unrecognized command: {$message->payload}.", PHP_EOL;
}
} else {
echo "Received the message from `{$message->channel}` channel:",
PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL;
}
}
};
// Subscribe to your channels and start processing the messages.
$pubsub->subscribe('control_channel', 'notifications', $poorMansKafka);
// Open a terminal and use redis-cli to push messages to the channels. Examples:
// redis-cli PUBLISH notifications "this is a test"
// redis-cli PUBLISH control_channel quit_loop
// When using Relay, there is no need to unset the pubsub consumer instance when you are done
// Say goodbye :-)
$version = redis_version($client->info());
echo "Goodbye from Redis $version!", PHP_EOL;
+83
View File
@@ -0,0 +1,83 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Predis allows to set Lua scripts as read-only operations for replication.
// This works for both EVAL and EVALSHA and also for the client-side abstraction
// built upon them (Predis\Command\ScriptCommand). This example shows a slightly
// more complex configuration that injects a new script command in the command
// factory used by the client and marks it as a read-only operation so that it
// will be executed on slaves.
use Predis\Command\ScriptCommand;
use Predis\Connection\Replication\MasterSlaveReplication;
use Predis\Replication\ReplicationStrategy;
// ------------------------------------------------------------------------- //
// Define a new script command that returns all the fields of a variable number
// of hashes with a single roundtrip.
class HashMultipleGetAll extends ScriptCommand
{
public const BODY = <<<LUA
local hashes = {}
for _, key in pairs(KEYS) do
table.insert(hashes, key)
table.insert(hashes, redis.call('hgetall', key))
end
return hashes
LUA;
public function getScript()
{
return self::BODY;
}
}
// ------------------------------------------------------------------------- //
$parameters = [
'tcp://127.0.0.1:6381?role=master&database=15',
'tcp://127.0.0.1:6382?role=slave&alias=slave-01&database=15',
];
$options = [
'commands' => [
'hmgetall' => 'HashMultipleGetAll',
],
'replication' => function () {
$strategy = new ReplicationStrategy();
$strategy->setScriptReadOnly(HashMultipleGetAll::BODY);
$replication = new MasterSlaveReplication($strategy);
return $replication;
},
];
// ------------------------------------------------------------------------- //
$client = new Predis\Client($parameters, $options);
// Execute the following commands on the master server using redis-cli:
// $ ./redis-cli HMSET metavars foo bar hoge piyo
// $ ./redis-cli HMSET servers master host1 slave host2
$hashes = $client->hmgetall('metavars', 'servers');
$replication = $client->getConnection();
$stillOnSlave = $replication->getCurrent() === $replication->getConnectionByAlias('slave-01');
echo 'Is still on slave? ', $stillOnSlave ? 'YES!' : 'NO!', PHP_EOL;
var_export($hashes);
+59
View File
@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Predis supports redis-sentinel to provide high availability in master / slave
// scenarios. The only but relevant difference with a basic replication scenario
// is that sentinel servers can manage the master server and its slaves based on
// their state, which means that they are able to provide an authoritative and
// updated configuration to clients thus avoiding static configurations for the
// replication servers and their roles.
// Instead of connection parameters pointing to redis nodes, we provide a list
// of instances of redis-sentinel. Users should always provide a timeout value
// low enough to not hinder operations just in case a sentinel is unreachable
// but Predis uses a default value of 100 milliseconds for sentinel parameters
// without an explicit timeout value.
//
// NOTE: in real-world scenarios sentinels should be running on different hosts!
$sentinels = [
'tcp://127.0.0.1:5380?timeout=0.100',
'tcp://127.0.0.1:5381?timeout=0.100',
'tcp://127.0.0.1:5382?timeout=0.100',
];
$client = new Predis\Client($sentinels, [
'replication' => 'sentinel',
'service' => 'mymaster',
]);
// Read operation.
$exists = $client->exists('foo') ? 'yes' : 'no';
$current = $client->getConnection()->getCurrent()->getParameters();
echo "Does 'foo' exist on {$current->role}? $exists.", PHP_EOL;
// Write operation.
$client->set('foo', 'bar');
$current = $client->getConnection()->getCurrent()->getParameters();
echo "Now 'foo' has been set to 'bar' on {$current->role}!", PHP_EOL;
// Read operation.
$bar = $client->get('foo');
$current = $client->getConnection()->getCurrent()->getParameters();
echo "We fetched 'foo' from {$current->role} and its value is '$bar'.", PHP_EOL;
/* OUTPUT:
Does 'foo' exist on slave-127.0.0.1:6381? yes.
Now 'foo' has been set to 'bar' on master!
We fetched 'foo' from master and its value is 'bar'.
*/
+53
View File
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// Predis supports master / slave replication scenarios where write operations
// are performed on the master server and read operations are executed against
// one of the slaves. The behavior of commands or EVAL scripts can be customized
// at will. As soon as a write operation is performed the client switches to the
// master server for all the subsequent requests (either reads and writes).
//
// This example must be executed using the second Redis server configured as the
// slave of the first one (see the "SLAVEOF" command).
//
$parameters = [
'tcp://127.0.0.1:6381?role=master&database=15',
'tcp://127.0.0.1:6382?role=slave&database=15',
];
$options = ['replication' => 'predis'];
$client = new Predis\Client($parameters, $options);
// Read operation.
$exists = $client->exists('foo') ? 'yes' : 'no';
$current = $client->getConnection()->getCurrent()->getParameters();
echo "Does 'foo' exist on {$current->role}? $exists.", PHP_EOL;
// Write operation.
$client->set('foo', 'bar');
$current = $client->getConnection()->getCurrent()->getParameters();
echo "Now 'foo' has been set to 'bar' on {$current->role}!", PHP_EOL;
// Read operation.
$bar = $client->get('foo');
$current = $client->getConnection()->getCurrent()->getParameters();
echo "We fetched 'foo' from {$current->role} and its value is '$bar'.", PHP_EOL;
/* OUTPUT:
Does 'foo' exist on slave? yes.
Now 'foo' has been set to 'bar' on master!
We fetched 'foo' from master and its value is 'bar'.
*/
+53
View File
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This example demonstrates how to use Predis to save PHP sessions on Redis.
//
// The value of `session.gc_maxlifetime` in `php.ini` will be used by default as
// the TTL for keys holding session data but this value can be overridden when
// creating the session handler instance using the `gc_maxlifetime` option.
//
// NOTE: this class requires PHP >= 5.4 but can be used on PHP 5.3 if a polyfill
// for SessionHandlerInterface is provided either by you or an external package
// like `symfony/http-foundation`.
//
// See http://www.php.net/class.sessionhandlerinterface.php for more details.
//
if (!interface_exists('SessionHandlerInterface')) {
exit('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ' .
"or a polyfill for SessionHandlerInterface provided by an external package.\n");
}
// Instantiate a new client just like you would normally do. Using a prefix for
// keys will effectively prefix all session keys with the specified string.
$client = new Predis\Client($single_server, ['prefix' => 'sessions:']);
// Set `gc_maxlifetime` to specify a time-to-live of 5 seconds for session keys.
$handler = new Predis\Session\Handler($client, ['gc_maxlifetime' => 5]);
// Register the session handler.
$handler->register();
// We just set a fixed session ID only for the sake of our example.
session_id('example_session_id');
session_start();
if (isset($_SESSION['foo'])) {
echo "Session has `foo` set to {$_SESSION['foo']}", PHP_EOL;
} else {
$_SESSION['foo'] = $value = mt_rand();
echo "Empty session, `foo` has been set with $value", PHP_EOL;
}
+49
View File
@@ -0,0 +1,49 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (PHP_SAPI !== 'cli') {
exit('Example scripts are meant to be executed locally via CLI.');
}
require __DIR__ . '/../autoload.php';
function redis_version($info)
{
if (isset($info['Server']['redis_version'])) {
return $info['Server']['redis_version'];
} elseif (isset($info['redis_version'])) {
return $info['redis_version'];
} else {
return 'unknown version';
}
}
$single_server = [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
];
$multiple_servers = [
[
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
'alias' => 'first',
],
[
'host' => '127.0.0.1',
'port' => 6380,
'database' => 15,
'alias' => 'second',
],
];
+53
View File
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__ . '/shared.php';
// This is an implementation of an atomic client-side ZPOP using the support for
// check-and-set (CAS) operations with MULTI/EXEC transactions, as described in
// "WATCH explained" from http://redis.io/topics/transactions
//
// First, populate your database with a tiny sample data set:
//
// ./redis-cli
// SELECT 15
// ZADD zset 1 a 2 b 3 c
//
// Then execute this script four times and see its output.
//
function zpop($client, $key)
{
$element = null;
$options = [
'cas' => true, // Initialize with support for CAS operations
'watch' => $key, // Key that needs to be WATCHed to detect changes
'retry' => 3, // Number of retries on aborted transactions, after
// which the client bails out with an exception.
];
$client->transaction($options, function ($tx) use ($key, &$element) {
@[$element] = $tx->zrange($key, 0, 0);
if (isset($element)) {
$tx->multi(); // With CAS, MULTI *must* be explicitly invoked.
$tx->zrem($key, $element);
}
});
return $element;
}
$client = new Predis\Client($single_server);
$zpopped = zpop($client, 'zset');
echo isset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
-2987
View File
File diff suppressed because it is too large Load Diff
-500
View File
@@ -1,500 +0,0 @@
<?php
namespace Predis;
RedisServerProfile::registerProfile('\Predis\RedisServer_v1_0', '1.0');
class RedisServer_v1_0 extends \Predis\RedisServerProfile {
public function getVersion() { return '1.0'; }
public function getSupportedCommands() {
return array(
/* miscellaneous commands */
'ping' => '\Predis\Compatibility\v1_0\Commands\Ping',
'echo' => '\Predis\Compatibility\v1_0\Commands\DoEcho',
'auth' => '\Predis\Compatibility\v1_0\Commands\Auth',
/* connection handling */
'quit' => '\Predis\Compatibility\v1_0\Commands\Quit',
/* commands operating on string values */
'set' => '\Predis\Compatibility\v1_0\Commands\Set',
'setnx' => '\Predis\Compatibility\v1_0\Commands\SetPreserve',
'setPreserve' => '\Predis\Compatibility\v1_0\Commands\SetPreserve',
'get' => '\Predis\Compatibility\v1_0\Commands\Get',
'mget' => '\Predis\Compatibility\v1_0\Commands\GetMultiple',
'getMultiple' => '\Predis\Compatibility\v1_0\Commands\GetMultiple',
'getset' => '\Predis\Compatibility\v1_0\Commands\GetSet',
'getSet' => '\Predis\Compatibility\v1_0\Commands\GetSet',
'incr' => '\Predis\Compatibility\v1_0\Commands\Increment',
'increment' => '\Predis\Compatibility\v1_0\Commands\Increment',
'incrby' => '\Predis\Compatibility\v1_0\Commands\IncrementBy',
'incrementBy' => '\Predis\Compatibility\v1_0\Commands\IncrementBy',
'decr' => '\Predis\Compatibility\v1_0\Commands\Decrement',
'decrement' => '\Predis\Compatibility\v1_0\Commands\Decrement',
'decrby' => '\Predis\Compatibility\v1_0\Commands\DecrementBy',
'decrementBy' => '\Predis\Compatibility\v1_0\Commands\DecrementBy',
'exists' => '\Predis\Compatibility\v1_0\Commands\Exists',
'del' => '\Predis\Compatibility\v1_0\Commands\Delete',
'delete' => '\Predis\Compatibility\v1_0\Commands\Delete',
'type' => '\Predis\Compatibility\v1_0\Commands\Type',
/* commands operating on the key space */
'keys' => '\Predis\Compatibility\v1_0\Commands\Keys',
'randomkey' => '\Predis\Compatibility\v1_0\Commands\RandomKey',
'randomKey' => '\Predis\Compatibility\v1_0\Commands\RandomKey',
'rename' => '\Predis\Compatibility\v1_0\Commands\Rename',
'renamenx' => '\Predis\Compatibility\v1_0\Commands\RenamePreserve',
'renamePreserve' => '\Predis\Compatibility\v1_0\Commands\RenamePreserve',
'expire' => '\Predis\Compatibility\v1_0\Commands\Expire',
'expireat' => '\Predis\Compatibility\v1_0\Commands\ExpireAt',
'expireAt' => '\Predis\Compatibility\v1_0\Commands\ExpireAt',
'dbsize' => '\Predis\Compatibility\v1_0\Commands\DatabaseSize',
'databaseSize' => '\Predis\Compatibility\v1_0\Commands\DatabaseSize',
'ttl' => '\Predis\Compatibility\v1_0\Commands\TimeToLive',
'timeToLive' => '\Predis\Compatibility\v1_0\Commands\TimeToLive',
/* commands operating on lists */
'rpush' => '\Predis\Compatibility\v1_0\Commands\ListPushTail',
'pushTail' => '\Predis\Compatibility\v1_0\Commands\ListPushTail',
'lpush' => '\Predis\Compatibility\v1_0\Commands\ListPushHead',
'pushHead' => '\Predis\Compatibility\v1_0\Commands\ListPushHead',
'llen' => '\Predis\Compatibility\v1_0\Commands\ListLength',
'listLength' => '\Predis\Compatibility\v1_0\Commands\ListLength',
'lrange' => '\Predis\Compatibility\v1_0\Commands\ListRange',
'listRange' => '\Predis\Compatibility\v1_0\Commands\ListRange',
'ltrim' => '\Predis\Compatibility\v1_0\Commands\ListTrim',
'listTrim' => '\Predis\Compatibility\v1_0\Commands\ListTrim',
'lindex' => '\Predis\Compatibility\v1_0\Commands\ListIndex',
'listIndex' => '\Predis\Compatibility\v1_0\Commands\ListIndex',
'lset' => '\Predis\Compatibility\v1_0\Commands\ListSet',
'listSet' => '\Predis\Compatibility\v1_0\Commands\ListSet',
'lrem' => '\Predis\Compatibility\v1_0\Commands\ListRemove',
'listRemove' => '\Predis\Compatibility\v1_0\Commands\ListRemove',
'lpop' => '\Predis\Compatibility\v1_0\Commands\ListPopFirst',
'popFirst' => '\Predis\Compatibility\v1_0\Commands\ListPopFirst',
'rpop' => '\Predis\Compatibility\v1_0\Commands\ListPopLast',
'popLast' => '\Predis\Compatibility\v1_0\Commands\ListPopLast',
/* commands operating on sets */
'sadd' => '\Predis\Compatibility\v1_0\Commands\SetAdd',
'setAdd' => '\Predis\Compatibility\v1_0\Commands\SetAdd',
'srem' => '\Predis\Compatibility\v1_0\Commands\SetRemove',
'setRemove' => '\Predis\Compatibility\v1_0\Commands\SetRemove',
'spop' => '\Predis\Compatibility\v1_0\Commands\SetPop',
'setPop' => '\Predis\Compatibility\v1_0\Commands\SetPop',
'smove' => '\Predis\Compatibility\v1_0\Commands\SetMove',
'setMove' => '\Predis\Compatibility\v1_0\Commands\SetMove',
'scard' => '\Predis\Compatibility\v1_0\Commands\SetCardinality',
'setCardinality' => '\Predis\Compatibility\v1_0\Commands\SetCardinality',
'sismember' => '\Predis\Compatibility\v1_0\Commands\SetIsMember',
'setIsMember' => '\Predis\Compatibility\v1_0\Commands\SetIsMember',
'sinter' => '\Predis\Compatibility\v1_0\Commands\SetIntersection',
'setIntersection' => '\Predis\Compatibility\v1_0\Commands\SetIntersection',
'sinterstore' => '\Predis\Compatibility\v1_0\Commands\SetIntersectionStore',
'setIntersectionStore' => '\Predis\Compatibility\v1_0\Commands\SetIntersectionStore',
'sunion' => '\Predis\Compatibility\v1_0\Commands\SetUnion',
'setUnion' => '\Predis\Compatibility\v1_0\Commands\SetUnion',
'sunionstore' => '\Predis\Compatibility\v1_0\Commands\SetUnionStore',
'setUnionStore' => '\Predis\Compatibility\v1_0\Commands\SetUnionStore',
'sdiff' => '\Predis\Compatibility\v1_0\Commands\SetDifference',
'setDifference' => '\Predis\Compatibility\v1_0\Commands\SetDifference',
'sdiffstore' => '\Predis\Compatibility\v1_0\Commands\SetDifferenceStore',
'setDifferenceStore' => '\Predis\Compatibility\v1_0\Commands\SetDifferenceStore',
'smembers' => '\Predis\Compatibility\v1_0\Commands\SetMembers',
'setMembers' => '\Predis\Compatibility\v1_0\Commands\SetMembers',
'srandmember' => '\Predis\Compatibility\v1_0\Commands\SetRandomMember',
'setRandomMember' => '\Predis\Compatibility\v1_0\Commands\SetRandomMember',
/* multiple databases handling commands */
'select' => '\Predis\Compatibility\v1_0\Commands\SelectDatabase',
'selectDatabase' => '\Predis\Compatibility\v1_0\Commands\SelectDatabase',
'move' => '\Predis\Compatibility\v1_0\Commands\MoveKey',
'moveKey' => '\Predis\Compatibility\v1_0\Commands\MoveKey',
'flushdb' => '\Predis\Compatibility\v1_0\Commands\FlushDatabase',
'flushDatabase' => '\Predis\Compatibility\v1_0\Commands\FlushDatabase',
'flushall' => '\Predis\Compatibility\v1_0\Commands\FlushAll',
'flushDatabases' => '\Predis\Compatibility\v1_0\Commands\FlushAll',
/* sorting */
'sort' => '\Predis\Compatibility\v1_0\Commands\Sort',
/* remote server control commands */
'info' => '\Predis\Compatibility\v1_0\Commands\Info',
'slaveof' => '\Predis\Compatibility\v1_0\Commands\SlaveOf',
'slaveOf' => '\Predis\Compatibility\v1_0\Commands\SlaveOf',
/* persistence control commands */
'save' => '\Predis\Compatibility\v1_0\Commands\Save',
'bgsave' => '\Predis\Compatibility\v1_0\Commands\BackgroundSave',
'backgroundSave' => '\Predis\Compatibility\v1_0\Commands\BackgroundSave',
'lastsave' => '\Predis\Compatibility\v1_0\Commands\LastSave',
'lastSave' => '\Predis\Compatibility\v1_0\Commands\LastSave',
'shutdown' => '\Predis\Compatibility\v1_0\Commands\Shutdown',
);
}
}
/* ------------------------------------------------------------------------- */
namespace Predis\Compatibility\v1_0\Commands;
/* miscellaneous commands */
class Ping extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'PING'; }
public function parseResponse($data) {
return $data === 'PONG' ? true : false;
}
}
class DoEcho extends \Predis\BulkCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'ECHO'; }
}
class Auth extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'AUTH'; }
}
/* connection handling */
class Quit extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'QUIT'; }
public function closesConnection() { return true; }
}
/* commands operating on string values */
class Set extends \Predis\BulkCommand {
public function getCommandId() { return 'SET'; }
}
class SetPreserve extends \Predis\BulkCommand {
public function getCommandId() { return 'SETNX'; }
public function parseResponse($data) { return (bool) $data; }
}
class Get extends \Predis\InlineCommand {
public function getCommandId() { return 'GET'; }
}
class GetMultiple extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'MGET'; }
}
class GetSet extends \Predis\BulkCommand {
public function getCommandId() { return 'GETSET'; }
}
class Increment extends \Predis\InlineCommand {
public function getCommandId() { return 'INCR'; }
}
class IncrementBy extends \Predis\InlineCommand {
public function getCommandId() { return 'INCRBY'; }
}
class Decrement extends \Predis\InlineCommand {
public function getCommandId() { return 'DECR'; }
}
class DecrementBy extends \Predis\InlineCommand {
public function getCommandId() { return 'DECRBY'; }
}
class Exists extends \Predis\InlineCommand {
public function getCommandId() { return 'EXISTS'; }
public function parseResponse($data) { return (bool) $data; }
}
class Delete extends \Predis\InlineCommand {
public function getCommandId() { return 'DEL'; }
}
class Type extends \Predis\InlineCommand {
public function getCommandId() { return 'TYPE'; }
}
/* commands operating on the key space */
class Keys extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'KEYS'; }
public function parseResponse($data) {
return strlen($data) > 0 ? explode(' ', $data) : array();
}
}
class RandomKey extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'RANDOMKEY'; }
public function parseResponse($data) { return $data !== '' ? $data : null; }
}
class Rename extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'RENAME'; }
}
class RenamePreserve extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'RENAMENX'; }
public function parseResponse($data) { return (bool) $data; }
}
class Expire extends \Predis\InlineCommand {
public function getCommandId() { return 'EXPIRE'; }
public function parseResponse($data) { return (bool) $data; }
}
class ExpireAt extends \Predis\InlineCommand {
public function getCommandId() { return 'EXPIREAT'; }
public function parseResponse($data) { return (bool) $data; }
}
class DatabaseSize extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'DBSIZE'; }
}
class TimeToLive extends \Predis\InlineCommand {
public function getCommandId() { return 'TTL'; }
}
/* commands operating on lists */
class ListPushTail extends \Predis\BulkCommand {
public function getCommandId() { return 'RPUSH'; }
}
class ListPushHead extends \Predis\BulkCommand {
public function getCommandId() { return 'LPUSH'; }
}
class ListLength extends \Predis\InlineCommand {
public function getCommandId() { return 'LLEN'; }
}
class ListRange extends \Predis\InlineCommand {
public function getCommandId() { return 'LRANGE'; }
}
class ListTrim extends \Predis\InlineCommand {
public function getCommandId() { return 'LTRIM'; }
}
class ListIndex extends \Predis\InlineCommand {
public function getCommandId() { return 'LINDEX'; }
}
class ListSet extends \Predis\BulkCommand {
public function getCommandId() { return 'LSET'; }
}
class ListRemove extends \Predis\BulkCommand {
public function getCommandId() { return 'LREM'; }
}
class ListPopFirst extends \Predis\InlineCommand {
public function getCommandId() { return 'LPOP'; }
}
class ListPopLast extends \Predis\InlineCommand {
public function getCommandId() { return 'RPOP'; }
}
/* commands operating on sets */
class SetAdd extends \Predis\BulkCommand {
public function getCommandId() { return 'SADD'; }
public function parseResponse($data) { return (bool) $data; }
}
class SetRemove extends \Predis\BulkCommand {
public function getCommandId() { return 'SREM'; }
public function parseResponse($data) { return (bool) $data; }
}
class SetPop extends \Predis\InlineCommand {
public function getCommandId() { return 'SPOP'; }
}
class SetMove extends \Predis\BulkCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'SMOVE'; }
public function parseResponse($data) { return (bool) $data; }
}
class SetCardinality extends \Predis\InlineCommand {
public function getCommandId() { return 'SCARD'; }
}
class SetIsMember extends \Predis\BulkCommand {
public function getCommandId() { return 'SISMEMBER'; }
public function parseResponse($data) { return (bool) $data; }
}
class SetIntersection extends \Predis\InlineCommand {
public function getCommandId() { return 'SINTER'; }
}
class SetIntersectionStore extends \Predis\InlineCommand {
public function getCommandId() { return 'SINTERSTORE'; }
}
class SetUnion extends \Predis\InlineCommand {
public function getCommandId() { return 'SUNION'; }
}
class SetUnionStore extends \Predis\InlineCommand {
public function getCommandId() { return 'SUNIONSTORE'; }
}
class SetDifference extends \Predis\InlineCommand {
public function getCommandId() { return 'SDIFF'; }
}
class SetDifferenceStore extends \Predis\InlineCommand {
public function getCommandId() { return 'SDIFFSTORE'; }
}
class SetMembers extends \Predis\InlineCommand {
public function getCommandId() { return 'SMEMBERS'; }
}
class SetRandomMember extends \Predis\InlineCommand {
public function getCommandId() { return 'SRANDMEMBER'; }
}
/* multiple databases handling commands */
class SelectDatabase extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'SELECT'; }
}
class MoveKey extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'MOVE'; }
public function parseResponse($data) { return (bool) $data; }
}
class FlushDatabase extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'FLUSHDB'; }
}
class FlushAll extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'FLUSHALL'; }
}
/* sorting */
class Sort extends \Predis\InlineCommand {
public function getCommandId() { return 'SORT'; }
public function filterArguments(Array $arguments) {
if (count($arguments) === 1) {
return $arguments;
}
// TODO: add more parameters checks
$query = array($arguments[0]);
$sortParams = $arguments[1];
if (isset($sortParams['by'])) {
$query[] = 'BY';
$query[] = $sortParams['by'];
}
if (isset($sortParams['get'])) {
$getargs = $sortParams['get'];
if (is_array($getargs)) {
foreach ($getargs as $getarg) {
$query[] = 'GET';
$query[] = $getarg;
}
}
else {
$query[] = 'GET';
$query[] = $getargs;
}
}
if (isset($sortParams['limit']) && is_array($sortParams['limit'])) {
$query[] = 'LIMIT';
$query[] = $sortParams['limit'][0];
$query[] = $sortParams['limit'][1];
}
if (isset($sortParams['sort'])) {
$query[] = strtoupper($sortParams['sort']);
}
if (isset($sortParams['alpha']) && $sortParams['alpha'] == true) {
$query[] = 'ALPHA';
}
if (isset($sortParams['store']) && $sortParams['store'] == true) {
$query[] = 'STORE';
$query[] = $sortParams['store'];
}
return $query;
}
}
/* persistence control commands */
class Save extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'SAVE'; }
}
class BackgroundSave extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'BGSAVE'; }
public function parseResponse($data) {
if ($data == 'Background saving started') {
return true;
}
return $data;
}
}
class LastSave extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'LASTSAVE'; }
}
class Shutdown extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'SHUTDOWN'; }
public function closesConnection() { return true; }
}
/* remote server control commands */
class Info extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'INFO'; }
public function parseResponse($data) {
$info = array();
$infoLines = explode("\r\n", $data, -1);
foreach ($infoLines as $row) {
list($k, $v) = explode(':', $row);
if (!preg_match('/^db\d+$/', $k)) {
$info[$k] = $v;
}
else {
$db = array();
foreach (explode(',', $v) as $dbvar) {
list($dbvk, $dbvv) = explode('=', $dbvar);
$db[trim($dbvk)] = $dbvv;
}
$info[$k] = $db;
}
}
return $info;
}
}
class SlaveOf extends \Predis\InlineCommand {
public function canBeHashed() { return false; }
public function getCommandId() { return 'SLAVEOF'; }
public function filterArguments(Array $arguments) {
if (count($arguments) === 0 || $arguments[0] === 'NO ONE') {
return array('NO', 'ONE');
}
return $arguments;
}
}
?>
+15
View File
@@ -0,0 +1,15 @@
parameters:
level: 0
paths:
- tests/
ignoreErrors:
# Uses func_get_args()
- message: "#^Static method Predis\\\\Command\\\\RawCommand\\:\\:create\\(\\) invoked with 0 parameters, at least 1 required\\.$#"
count: 1
path: tests/Predis/Command/RawCommandTest.php
# Mockery
- message: "#^Call to an undefined method Predis\\\\Configuration\\\\Option\\\\AggregateTest\\:\\:getMockConnectionClass\\(\\)\\.$#"
count: 2
path: tests/Predis/Configuration/Option/AggregateTest.php
+56
View File
@@ -0,0 +1,56 @@
parameters:
level: 2
paths:
- src/
ignoreErrors:
# Tricky ones
- message: "#^Cannot cast Predis\\\\Response\\\\ResponseInterface to string\\.$#"
count: 1
path: src/Client.php
- message: "#^Cannot cast Predis\\\\Connection\\\\ConnectionInterface to string\\.$#"
count: 1
path: src/Client.php
# phpiredis extension is not installed
- "#^Function phpiredis_\\w+ not found\\.$#"
- "#^Constant PHPIREDIS_#"
# "new static" in non-final classes
- message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 3
path: src/Client.php
- message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 1
path: src/Connection/Parameters.php
# Using an interface as concrete type
- message: "#^Call to an undefined method Predis\\\\Command\\\\FactoryInterface\\:\\:define\\(\\)\\.$#"
count: 1
path: src/Configuration/Option/Commands.php
- message: "#^Call to an undefined method Predis\\\\Command\\\\FactoryInterface\\:\\:undefine\\(\\)\\.$#"
count: 1
path: src/Configuration/Option/Commands.php
- message: "#^Access to an undefined property Predis\\\\Configuration\\\\OptionsInterface\\:\\:\\$parameters\\.$#"
count: 1
path: src/Configuration/Option/Connections.php
- 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
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$role\\.$#"
count: 1
path: src/Connection/Replication/SentinelReplication.php
# try/catch problems
- message: "#^Variable \\$connection 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/MasterSlaveReplication.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 1
path: src/Connection/Replication/SentinelReplication.php
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true"
>
<testsuites>
<testsuite name="Predis Test Suite">
<directory phpVersion="7.4">tests/Predis/</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>relay-incompatible</group>
<group>relay-resp3</group>
<group>realm-webdis</group>
<group>realm-stack</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
</exclude>
</groups>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<php>
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
<const name="REDIS_SERVER_PORT" value="6379" />
<const name="REDIS_SERVER_DBNUM" value="0" />
<env name="USE_RELAY" value="true" />
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
<!-- Redis Cluster -->
<!-- Only master nodes endpoints included -->
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
</php>
</phpunit>
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true"
>
<testsuites>
<testsuite name="Predis Test Suite">
<directory>tests/Predis/</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>
<groups>
<exclude>
<group>realm-webdis</group>
<group>realm-stack</group>
<group>ext-relay</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
<!-- <group>connected</group> -->
<!-- <group>disconnected</group> -->
<!-- <group>commands</group> -->
<!-- <group>slow</group> -->
</exclude>
</groups>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<php>
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
<const name="REDIS_SERVER_PORT" value="6379" />
<const name="REDIS_SERVER_DBNUM" value="0" />
<env name="USE_RELAY" value="false" />
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
<!-- Redis Cluster -->
<!-- Only master nodes endpoints included -->
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
</php>
</phpunit>
+64
View File
@@ -0,0 +1,64 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis;
/**
* Implements a lightweight PSR-0 compliant autoloader for Predis.
*
* @author Eric Naeseth <eric@thumbtack.com>
* @author Daniele Alessandri <suppakilla@gmail.com>
* @codeCoverageIgnore
*/
class Autoloader
{
private $directory;
private $prefix;
private $prefixLength;
/**
* @param string $baseDirectory Base directory where the source files are located.
*/
public function __construct($baseDirectory = __DIR__)
{
$this->directory = $baseDirectory;
$this->prefix = __NAMESPACE__ . '\\';
$this->prefixLength = strlen($this->prefix);
}
/**
* Registers the autoloader class with the PHP SPL autoloader.
*
* @param bool $prepend Prepend the autoloader on the stack instead of appending it.
*/
public static function register($prepend = false)
{
spl_autoload_register([new self(), 'autoload'], true, $prepend);
}
/**
* Loads a class from a file using its fully qualified name.
*
* @param string $className Fully qualified name of a class.
*/
public function autoload($className)
{
if (0 === strpos($className, $this->prefix)) {
$parts = explode('\\', substr($className, $this->prefixLength));
$filepath = $this->directory . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $parts) . '.php';
if (is_file($filepath)) {
require $filepath;
}
}
}
}
+612
View File
@@ -0,0 +1,612 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis;
use ArrayIterator;
use InvalidArgumentException;
use IteratorAggregate;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Command\Redis\Container\ContainerFactory;
use Predis\Command\Redis\Container\ContainerInterface;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
use Predis\Connection\RelayConnection;
use Predis\Monitor\Consumer as MonitorConsumer;
use Predis\Pipeline\Atomic;
use Predis\Pipeline\FireAndForget;
use Predis\Pipeline\Pipeline;
use Predis\Pipeline\RelayAtomic;
use Predis\Pipeline\RelayPipeline;
use Predis\PubSub\Consumer as PubSubConsumer;
use Predis\PubSub\RelayConsumer as RelayPubSubConsumer;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ResponseInterface;
use Predis\Response\ServerException;
use Predis\Transaction\MultiExec as MultiExecTransaction;
use ReturnTypeWillChange;
use RuntimeException;
use Traversable;
/**
* Client class used for connecting and executing commands on Redis.
*
* This is the main high-level abstraction of Predis upon which various other
* abstractions are built. Internally it aggregates various other classes each
* one with its own responsibility and scope.
*
* @template-implements \IteratorAggregate<string, static>
*/
class Client implements ClientInterface, IteratorAggregate
{
public const VERSION = '2.4.0';
/** @var OptionsInterface */
private $options;
/** @var ConnectionInterface */
private $connection;
/** @var Command\FactoryInterface */
private $commands;
/**
* @param mixed $parameters Connection parameters for one or more servers.
* @param mixed $options Options to configure some behaviours of the client.
*/
public function __construct($parameters = null, $options = null)
{
$this->options = static::createOptions($options ?? new Options());
$this->connection = static::createConnection($this->options, $parameters ?? new Parameters());
$this->commands = $this->options->commands;
}
/**
* Creates a new set of client options for the client.
*
* @param array|OptionsInterface $options Set of client options
*
* @return OptionsInterface
* @throws InvalidArgumentException
*/
protected static function createOptions($options)
{
if (is_array($options)) {
return new Options($options);
} elseif ($options instanceof OptionsInterface) {
return $options;
} else {
throw new InvalidArgumentException('Invalid type for client options');
}
}
/**
* Creates single or aggregate connections from supplied arguments.
*
* This method accepts the following types to create a connection instance:
*
* - Array (dictionary: single connection, indexed: aggregate connections)
* - String (URI for a single connection)
* - Callable (connection initializer callback)
* - Instance of Predis\Connection\ParametersInterface (used as-is)
* - Instance of Predis\Connection\ConnectionInterface (returned as-is)
*
* When a callable is passed, it receives the original set of client options
* and must return an instance of Predis\Connection\ConnectionInterface.
*
* Connections are created using the connection factory (in case of single
* connections) or a specialized aggregate connection initializer (in case
* of cluster and replication) retrieved from the supplied client options.
*
* @param OptionsInterface $options Client options container
* @param mixed $parameters Connection parameters
*
* @return ConnectionInterface
* @throws InvalidArgumentException
*/
protected static function createConnection(OptionsInterface $options, $parameters)
{
if ($parameters instanceof ConnectionInterface) {
return $parameters;
}
if ($parameters instanceof ParametersInterface || is_string($parameters)) {
return $options->connections->create($parameters);
}
if (is_array($parameters)) {
if (!isset($parameters[0])) {
return $options->connections->create($parameters);
} elseif ($options->defined('cluster') && $initializer = $options->cluster) {
return $initializer($parameters, true);
} elseif ($options->defined('replication') && $initializer = $options->replication) {
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'
);
}
}
if (is_callable($parameters)) {
$connection = call_user_func($parameters, $options);
if (!$connection instanceof ConnectionInterface) {
throw new InvalidArgumentException('Callable parameters must return a valid connection');
}
return $connection;
}
throw new InvalidArgumentException('Invalid type for connection parameters');
}
/**
* {@inheritdoc}
*/
public function getCommandFactory()
{
return $this->commands;
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return $this->options;
}
/**
* Creates a new client using a specific underlying connection.
*
* This method allows to create a new client instance by picking a specific
* connection out of an aggregate one, with the same options of the original
* client instance.
*
* The specified selector defines which logic to use to look for a suitable
* connection by the specified value. Supported selectors are:
*
* - `id`
* - `key`
* - `slot`
* - `command`
* - `alias`
* - `role`
*
* Internally the client relies on duck-typing and follows this convention:
*
* $selector string => getConnectionBy$selector($value) method
*
* This means that support for specific selectors may vary depending on the
* actual logic implemented by connection classes and there is no interface
* binding a connection class to implement any of these.
*
* @param string $selector Type of selector.
* @param mixed $value Value to be used by the selector.
*
* @return ClientInterface
*/
public function getClientBy($selector, $value)
{
$selector = strtolower($selector);
if (!in_array($selector, ['id', 'key', 'slot', 'role', 'alias', 'command'])) {
throw new InvalidArgumentException("Invalid selector type: `$selector`");
}
if (!method_exists($this->connection, $method = "getConnectionBy$selector")) {
$class = get_class($this->connection);
throw new InvalidArgumentException("Selecting connection by $selector is not supported by $class");
}
if (!$connection = $this->connection->$method($value)) {
throw new InvalidArgumentException("Cannot find a connection by $selector matching `$value`");
}
return new static($connection, $this->getOptions());
}
/**
* Opens the underlying connection and connects to the server.
*/
public function connect()
{
$this->connection->connect();
}
/**
* Closes the underlying connection and disconnects from the server.
*/
public function disconnect()
{
$this->connection->disconnect();
}
/**
* Closes the underlying connection and disconnects from the server.
*
* This is the same as `Client::disconnect()` as it does not actually send
* the `QUIT` command to Redis, but simply closes the connection.
*/
public function quit()
{
$this->disconnect();
}
/**
* Returns the current state of the underlying connection.
*
* @return bool
*/
public function isConnected()
{
return $this->connection->isConnected();
}
/**
* {@inheritdoc}
*/
public function getConnection()
{
return $this->connection;
}
/**
* Applies the configured serializer and compression to given value.
*
* @param mixed $value
* @return string
*/
public function pack($value)
{
return $this->connection instanceof RelayConnection
? $this->connection->pack($value)
: $value;
}
/**
* Deserializes and decompresses to given value.
*
* @param mixed $value
* @return string
*/
public function unpack($value)
{
return $this->connection instanceof RelayConnection
? $this->connection->unpack($value)
: $value;
}
/**
* Executes a command without filtering its arguments, parsing the response,
* applying any prefix to keys or throwing exceptions on Redis errors even
* regardless of client options.
*
* It is possible to identify Redis error responses from normal responses
* using the second optional argument which is populated by reference.
*
* @param array $arguments Command arguments as defined by the command signature.
* @param bool $error Set to TRUE when Redis returned an error response.
*
* @return mixed
*/
public function executeRaw(array $arguments, &$error = null)
{
$error = false;
$commandID = array_shift($arguments);
$response = $this->connection->executeCommand(
new RawCommand($commandID, $arguments)
);
if ($response instanceof ResponseInterface) {
if ($response instanceof ErrorResponseInterface) {
$error = true;
}
return (string) $response;
}
return $response;
}
/**
* {@inheritdoc}
*/
public function __call($commandID, $arguments)
{
return $this->executeCommand(
$this->createCommand($commandID, $arguments)
);
}
/**
* {@inheritdoc}
*/
public function createCommand($commandID, $arguments = [])
{
return $this->commands->create($commandID, $arguments);
}
/**
* @param string $name
* @return ContainerInterface
*/
public function __get(string $name)
{
return ContainerFactory::create($this, $name);
}
/**
* @param string $name
* @param mixed $value
* @return mixed
*/
public function __set(string $name, $value)
{
throw new RuntimeException('Not allowed');
}
/**
* @param string $name
* @return mixed
*/
public function __isset(string $name)
{
throw new RuntimeException('Not allowed');
}
/**
* {@inheritdoc}
*/
public function executeCommand(CommandInterface $command)
{
$response = $this->connection->executeCommand($command);
if ($response instanceof ResponseInterface) {
if ($response instanceof ErrorResponseInterface) {
$response = $this->onErrorResponse($command, $response);
}
return $response;
}
return $command->parseResponse($response);
}
/**
* Handles -ERR responses returned by Redis.
*
* @param CommandInterface $command Redis command that generated the error.
* @param ErrorResponseInterface $response Instance of the error response.
*
* @return mixed
* @throws ServerException
*/
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
{
if ($command instanceof ScriptCommand && $response->getErrorType() === 'NOSCRIPT') {
$response = $this->executeCommand($command->getEvalCommand());
if (!$response instanceof ResponseInterface) {
$response = $command->parseResponse($response);
}
return $response;
}
if ($this->options->exceptions) {
throw new ServerException($response->getMessage());
}
return $response;
}
/**
* Executes the specified initializer method on `$this` by adjusting the
* actual invocation depending on the arity (0, 1 or 2 arguments). This is
* simply an utility method to create Redis contexts instances since they
* follow a common initialization path.
*
* @param string $initializer Method name.
* @param array $argv Arguments for the method.
*
* @return mixed
*/
private function sharedContextFactory($initializer, $argv = null)
{
switch (count($argv)) {
case 0:
return $this->$initializer();
case 1:
return is_array($argv[0])
? $this->$initializer($argv[0])
: $this->$initializer(null, $argv[0]);
case 2:
[$arg0, $arg1] = $argv;
return $this->$initializer($arg0, $arg1);
default:
return $this->$initializer($this, $argv);
}
}
/**
* Creates a new pipeline context and returns it, or returns the results of
* a pipeline executed inside the optionally provided callable object.
*
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return Pipeline|array
*/
public function pipeline(...$arguments)
{
return $this->sharedContextFactory('createPipeline', func_get_args());
}
/**
* Actual pipeline context initializer method.
*
* @param array|null $options Options for the context.
* @param mixed $callable Optional callable used to execute the context.
*
* @return Pipeline|array
*/
protected function createPipeline(?array $options = null, $callable = null)
{
if (isset($options['atomic']) && $options['atomic']) {
$class = Atomic::class;
} elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) {
$class = FireAndForget::class;
} else {
$class = Pipeline::class;
}
if ($this->connection instanceof RelayConnection) {
if (isset($options['atomic']) && $options['atomic']) {
$class = RelayAtomic::class;
} elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) {
throw new NotSupportedException('The "relay" extension does not support fire-and-forget pipelines.');
} else {
$class = RelayPipeline::class;
}
}
/*
* @var ClientContextInterface
*/
$pipeline = new $class($this);
if (isset($callable)) {
return $pipeline->execute($callable);
}
return $pipeline;
}
/**
* Creates a new transaction context and returns it, or returns the results
* of a transaction executed inside the optionally provided callable object.
*
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return MultiExecTransaction|array
*/
public function transaction(...$arguments)
{
return $this->sharedContextFactory('createTransaction', func_get_args());
}
/**
* Actual transaction context initializer method.
*
* @param array|null $options Options for the context.
* @param mixed $callable Optional callable used to execute the context.
*
* @return MultiExecTransaction|array
*/
protected function createTransaction(?array $options = null, $callable = null)
{
$transaction = new MultiExecTransaction($this, $options);
if (isset($callable)) {
return $transaction->execute($callable);
}
return $transaction;
}
/**
* Creates a new publish/subscribe context and returns it, or starts its loop
* inside the optionally provided callable object.
*
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return PubSubConsumer|null
*/
public function pubSubLoop(...$arguments)
{
return $this->sharedContextFactory('createPubSub', func_get_args());
}
/**
* Actual publish/subscribe context initializer method.
*
* @param array|null $options Options for the context.
* @param mixed $callable Optional callable used to execute the context.
*
* @return PubSubConsumer|null
*/
protected function createPubSub(?array $options = null, $callable = null)
{
if ($this->connection instanceof RelayConnection) {
$pubsub = new RelayPubSubConsumer($this, $options);
} else {
$pubsub = new PubSubConsumer($this, $options);
}
if (!isset($callable)) {
return $pubsub;
}
foreach ($pubsub as $message) {
if (call_user_func($callable, $pubsub, $message) === false) {
$pubsub->stop();
}
}
return null;
}
/**
* Creates a new monitor consumer and returns it.
*
* @return MonitorConsumer
*/
public function monitor()
{
return new MonitorConsumer($this);
}
/**
* @return Traversable<string, static>
*/
#[ReturnTypeWillChange]
public function getIterator()
{
$clients = [];
$connection = $this->getConnection();
if (!$connection instanceof Traversable) {
return new ArrayIterator([
(string) $connection => new static($connection, $this->getOptions()),
]);
}
foreach ($connection as $node) {
$clients[(string) $node] = new static($node, $this->getOptions());
}
return new ArrayIterator($clients);
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis;
class ClientConfiguration
{
/**
* @var array{modules: array}|string[][]
*/
private static $config = [
'modules' => [
['name' => 'Json', 'commandPrefix' => 'JSON'],
['name' => 'BloomFilter', 'commandPrefix' => 'BF'],
['name' => 'CuckooFilter', 'commandPrefix' => 'CF'],
['name' => 'CountMinSketch', 'commandPrefix' => 'CMS'],
['name' => 'TDigest', 'commandPrefix' => 'TDIGEST'],
['name' => 'TopK', 'commandPrefix' => 'TOPK'],
['name' => 'Search', 'commandPrefix' => 'FT'],
['name' => 'TimeSeries', 'commandPrefix' => 'TS'],
],
];
/**
* Returns available modules with configuration.
*
* @return array|string[][]
*/
public static function getModules(): array
{
return self::$config['modules'];
}
}
+396
View File
@@ -0,0 +1,396 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis;
use Predis\Command\Argument\Geospatial\ByInterface;
use Predis\Command\Argument\Geospatial\FromInterface;
use Predis\Command\Argument\Search\AggregateArguments;
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\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
use Predis\Command\Argument\Search\SearchArguments;
use Predis\Command\Argument\Search\SugAddArguments;
use Predis\Command\Argument\Search\SugGetArguments;
use Predis\Command\Argument\Search\SynUpdateArguments;
use Predis\Command\Argument\Server\LimitOffsetCount;
use Predis\Command\Argument\Server\To;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\AlterArguments as TSAlterArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments as TSCreateArguments;
use Predis\Command\Argument\TimeSeries\DecrByArguments;
use Predis\Command\Argument\TimeSeries\GetArguments;
use Predis\Command\Argument\TimeSeries\IncrByArguments;
use Predis\Command\Argument\TimeSeries\InfoArguments;
use Predis\Command\Argument\TimeSeries\MGetArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
use Predis\Command\CommandInterface;
use Predis\Command\Redis\Container\ACL;
use Predis\Command\Redis\Container\CLUSTER;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
use Predis\Command\Redis\HGETEX;
use Predis\Command\Redis\HSETEX;
/**
* 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 dump($key)
* @method $this exists($key)
* @method $this expire($key, $seconds, string $expireOption = '')
* @method $this expireat($key, $timestamp, string $expireOption = '')
* @method $this expiretime(string $key)
* @method $this keys($pattern)
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
* @method $this persist($key)
* @method $this pexpire($key, $milliseconds)
* @method $this pexpireat($key, $timestamp)
* @method $this pttl($key)
* @method $this randomkey()
* @method $this rename($key, $target)
* @method $this renamenx($key, $target)
* @method $this scan($cursor, ?array $options = null)
* @method $this sort($key, ?array $options = null)
* @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 append($key, $value)
* @method $this bfadd(string $key, $item)
* @method $this bfexists(string $key, $item)
* @method $this bfinfo(string $key, string $modifier = '')
* @method $this bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method $this bfloadchunk(string $key, int $iterator, $data)
* @method $this bfmadd(string $key, ...$item)
* @method $this bfmexists(string $key, ...$item)
* @method $this bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method $this bfscandump(string $key, int $iterator)
* @method $this bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method $this bitop($operation, $destkey, $key)
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
* @method $this bitfield_ro(string $key, ?array $encodingOffsetMap = null)
* @method $this bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
* @method $this blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method $this bzpopmax(array $keys, int $timeout)
* @method $this bzpopmin(array $keys, int $timeout)
* @method $this bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method $this cfadd(string $key, $item)
* @method $this cfaddnx(string $key, $item)
* @method $this cfcount(string $key, $item)
* @method $this cfdel(string $key, $item)
* @method $this cfexists(string $key, $item)
* @method $this cfloadchunk(string $key, int $iterator, $data)
* @method $this cfmexists(string $key, ...$item)
* @method $this cfinfo(string $key)
* @method $this cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1)
* @method $this cfscandump(string $key, int $iterator)
* @method $this cmsincrby(string $key, string|int...$itemIncrementDictionary)
* @method $this cmsinfo(string $key)
* @method $this cmsinitbydim(string $key, int $width, int $depth)
* @method $this cmsinitbyprob(string $key, float $errorRate, float $probability)
* @method $this cmsmerge(string $destination, array $sources, array $weights = [])
* @method $this cmsquery(string $key, string ...$item)
* @method $this decr($key)
* @method $this decrby($key, $decrement)
* @method $this failover(?To $to = null, bool $abort = false, int $timeout = -1)
* @method $this fcall(string $function, array $keys, ...$args)
* @method $this fcall_ro(string $function, array $keys, ...$args)
* @method $this ft_list()
* @method $this ftaggregate(string $index, string $query, ?AggregateArguments $arguments = null)
* @method $this ftaliasadd(string $alias, string $index)
* @method $this ftaliasdel(string $alias)
* @method $this ftaliasupdate(string $alias, string $index)
* @method $this ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method $this ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method $this ftdictadd(string $dict, ...$term)
* @method $this ftdictdel(string $dict, ...$term)
* @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 ftinfo(string $index)
* @method $this ftprofile(string $index, ProfileArguments $arguments)
* @method $this ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
* @method $this ftspellcheck(string $index, string $query, ?SearchArguments $arguments = null)
* @method $this ftsugadd(string $key, string $string, float $score, ?SugAddArguments $arguments = null)
* @method $this ftsugdel(string $key, string $string)
* @method $this ftsugget(string $key, string $prefix, ?SugGetArguments $arguments = null)
* @method $this ftsuglen(string $key)
* @method $this ftsyndump(string $index)
* @method $this ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method $this fttagvals(string $index, string $fieldName)
* @method $this get($key)
* @method $this getbit($key, $offset)
* @method $this getex(string $key, $modifier = '', $value = false)
* @method $this getrange($key, $start, $end)
* @method $this getdel(string $key)
* @method $this getset($key, $value)
* @method $this incr($key)
* @method $this incrby($key, $increment)
* @method $this incrbyfloat($key, $increment)
* @method $this mget(array $keys)
* @method $this mset(array $dictionary)
* @method $this msetnx(array $dictionary)
* @method $this psetex($key, $milliseconds, $value)
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method $this setbit($key, $offset, $value)
* @method $this setex($key, $seconds, $value)
* @method $this setnx($key, $value)
* @method $this setrange($key, $offset, $value)
* @method $this strlen($key)
* @method $this hdel($key, array $fields)
* @method $this hexists($key, $field)
* @method $this hexpire(string $key, int $seconds, array $fields, string $flag = null)
* @method $this hexpireat(string $key, int $unixTimeSeconds, array $fields, string $flag = null)
* @method $this hexpiretime(string $key, array $fields)
* @method $this hpersist(string $key, array $fields)
* @method $this hpexpire(string $key, int $milliseconds, array $fields, string $flag = null)
* @method $this hpexpireat(string $key, int $unixTimeMilliseconds, array $fields, string $flag = null)
* @method $this hpexpiretime(string $key, array $fields)
* @method $this hget($key, $field)
* @method $this hgetex(string $key, array $fields, string $modifier = HGETEX::NULL)
* @method $this hgetall($key)
* @method $this hgetdel(string $key, array $fields)
* @method $this hincrby($key, $field, $increment)
* @method $this hincrbyfloat($key, $field, $increment)
* @method $this hkeys($key)
* @method $this hlen($key)
* @method $this hmget($key, array $fields)
* @method $this hmset($key, array $dictionary)
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method $this hscan($key, $cursor, ?array $options = null)
* @method $this hset($key, $field, $value)
* @method $this hsetex(string $key, array $fieldValueMap, string $setModifier = HSETEX::SET_NULL, string $ttlModifier = HSETEX::TTL_NULL, int|bool $ttlModifierValue = false)
* @method $this hsetnx($key, $field, $value)
* @method $this httl(string $key, array $fields)
* @method $this hpttl(string $key, array $fields)
* @method $this hvals($key)
* @method $this hstrlen($key, $field)
* @method $this jsonarrappend(string $key, string $path = '$', ...$value)
* @method $this jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method $this jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method $this jsonarrlen(string $key, string $path = '$')
* @method $this jsonarrpop(string $key, string $path = '$', int $index = -1)
* @method $this jsonarrtrim(string $key, string $path, int $start, int $stop)
* @method $this jsonclear(string $key, string $path = '$')
* @method $this jsondel(string $key, string $path = '$')
* @method $this jsonforget(string $key, string $path = '$')
* @method $this jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method $this jsonnumincrby(string $key, string $path, int $value)
* @method $this jsonmerge(string $key, string $path, string $value)
* @method $this jsonmget(array $keys, string $path)
* @method $this jsonmset(string ...$keyPathValue)
* @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 jsonstrappend(string $key, string $path, string $value)
* @method $this jsonstrlen(string $key, string $path = '$')
* @method $this jsontoggle(string $key, string $path)
* @method $this jsontype(string $key, string $path = '$')
* @method $this blmove(string $source, string $destination, string $where, string $to, int $timeout)
* @method $this blpop(array|string $keys, $timeout)
* @method $this brpop(array|string $keys, $timeout)
* @method $this brpoplpush($source, $destination, $timeout)
* @method $this lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method $this lindex($key, $index)
* @method $this linsert($key, $whence, $pivot, $value)
* @method $this llen($key)
* @method $this lmove(string $source, string $destination, string $where, string $to)
* @method $this lmpop(array $keys, string $modifier = 'left', int $count = 1)
* @method $this lpop($key)
* @method $this lpush($key, array $values)
* @method $this lpushx($key, array $values)
* @method $this lrange($key, $start, $stop)
* @method $this lrem($key, $count, $value)
* @method $this lset($key, $index, $value)
* @method $this ltrim($key, $start, $stop)
* @method $this rpop($key)
* @method $this rpoplpush($source, $destination)
* @method $this rpush($key, array $values)
* @method $this rpushx($key, array $values)
* @method $this sadd($key, array $members)
* @method $this scard($key)
* @method $this sdiff(array|string $keys)
* @method $this sdiffstore($destination, array|string $keys)
* @method $this sinter(array|string $keys)
* @method $this sintercard(array $keys, int $limit = 0)
* @method $this sinterstore($destination, array|string $keys)
* @method $this sismember($key, $member)
* @method $this smembers($key)
* @method $this smismember(string $key, string ...$members)
* @method $this smove($source, $destination, $member)
* @method $this spop($key, $count = null)
* @method $this srandmember($key, $count = null)
* @method $this srem($key, $member)
* @method $this sscan($key, $cursor, ?array $options = null)
* @method $this sunion(array|string $keys)
* @method $this sunionstore($destination, array|string $keys)
* @method $this tdigestadd(string $key, float ...$value)
* @method $this tdigestbyrank(string $key, int ...$rank)
* @method $this tdigestbyrevrank(string $key, int ...$reverseRank)
* @method $this tdigestcdf(string $key, int ...$value)
* @method $this tdigestcreate(string $key, int $compression = 0)
* @method $this tdigestinfo(string $key)
* @method $this tdigestmax(string $key)
* @method $this tdigestmerge(string $destinationKey, array $sourceKeys, int $compression = 0, bool $override = false)
* @method $this tdigestquantile(string $key, float ...$quantile)
* @method $this tdigestmin(string $key)
* @method $this tdigestrank(string $key, ...$value)
* @method $this tdigestreset(string $key)
* @method $this tdigestrevrank(string $key, float ...$value)
* @method $this tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method $this topkadd(string $key, ...$items)
* @method $this topkincrby(string $key, ...$itemIncrement)
* @method $this topkinfo(string $key)
* @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 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)
* @method $this tsdecrby(string $key, float $value, ?DecrByArguments $arguments = null)
* @method $this tsdel(string $key, int $fromTimestamp, int $toTimestamp)
* @method $this tsdeleterule(string $sourceKey, string $destKey)
* @method $this tsget(string $key, ?GetArguments $arguments = null)
* @method $this tsincrby(string $key, float $value, ?IncrByArguments $arguments = null)
* @method $this tsinfo(string $key, ?InfoArguments $arguments = null)
* @method $this tsmadd(mixed ...$keyTimestampValue)
* @method $this tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method $this tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @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 zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
* @method $this zdiff(array $keys, bool $withScores = false)
* @method $this zdiffstore(string $destination, array $keys)
* @method $this zincrby($key, $increment, $member)
* @method $this zintercard(array $keys, int $limit = 0)
* @method $this zinterstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zinter(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zmpop(array $keys, string $modifier = 'min', int $count = 1)
* @method $this zmscore(string $key, string ...$member)
* @method $this zrandmember(string $key, int $count = 1, bool $withScores = false)
* @method $this zrange($key, $start, $stop, ?array $options = null)
* @method $this zrangebyscore($key, $min, $max, ?array $options = null)
* @method $this zrangestore(string $destination, string $source, int|string $min, string|int $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
* @method $this zrank($key, $member)
* @method $this zrem($key, $member)
* @method $this zremrangebyrank($key, $start, $stop)
* @method $this zremrangebyscore($key, $min, $max)
* @method $this zrevrange($key, $start, $stop, ?array $options = null)
* @method $this zrevrangebyscore($key, $max, $min, ?array $options = null)
* @method $this zrevrank($key, $member)
* @method $this zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zscore($key, $member)
* @method $this zscan($key, $cursor, ?array $options = null)
* @method $this zrangebylex($key, $start, $stop, ?array $options = null)
* @method $this zrevrangebylex($key, $start, $stop, ?array $options = null)
* @method $this zremrangebylex($key, $min, $max)
* @method $this zlexcount($key, $min, $max)
* @method $this pexpiretime(string $key)
* @method $this pfadd($key, array $elements)
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
* @method $this pfcount(array|string $keys)
* @method $this pubsub($subcommand, $argument)
* @method $this publish($channel, $message)
* @method $this discard()
* @method $this exec()
* @method $this multi()
* @method $this unwatch()
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
* @method $this script($subcommand, $argument = null)
* @method $this shutdown(?bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method $this auth($password)
* @method $this echo($message)
* @method $this ping($message = null)
* @method $this select($database)
* @method $this bgrewriteaof()
* @method $this bgsave()
* @method $this client($subcommand, $argument = null)
* @method $this config($subcommand, $argument = null)
* @method $this dbsize()
* @method $this flushall()
* @method $this flushdb()
* @method $this info($section = null)
* @method $this lastsave()
* @method $this save()
* @method $this slaveof($host, $port)
* @method $this slowlog($subcommand, $argument = null)
* @method $this time()
* @method $this command()
* @method $this geoadd($key, $longitude, $latitude, $member)
* @method $this geohash($key, array $members)
* @method $this geopos($key, array $members)
* @method $this geodist($key, $member1, $member2, $unit = null)
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, ?array $options = null)
* @method $this georadiusbymember($key, $member, $radius, $unit, ?array $options = null)
* @method $this geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* Container commands
* @property CLUSTER $cluster
* @property FunctionContainer $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
*/
interface ClientContextInterface
{
/**
* Sends the specified command instance to Redis.
*
* @param CommandInterface $command Command instance.
*
* @return mixed
*/
public function executeCommand(CommandInterface $command);
/**
* Sends the specified command with its arguments to Redis.
*
* @param string $method Command ID.
* @param array $arguments Arguments for the command.
*
* @return mixed
*/
public function __call($method, $arguments);
/**
* Starts the execution of the context.
*
* @param mixed $callable Optional callback for execution.
*
* @return array
*/
public function execute($callable = null);
}

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