Commit Graph

2133 Commits

Author SHA1 Message Date
Daniele Alessandri 6e8e23279e [tests] Update Predis\Connection\Aggregate\SentinelReplication tests.
Updated to verify that new sentinels retrieved from "SENTINEL" response
have their role automatically set to "sentinel". Also applied some minor
changes by dropping useless alias.
2020-09-12 19:44:56 +02:00
Daniele Alessandri 0392208520 Update README and CHANGELOG for role-specific default parameters. 2020-09-12 19:44:40 +02:00
Daniele Alessandri d9de9b5df3 Implement role-specific default parameters.
Until now users could specify a set of default parameters applied to all
connections created by the connection factory when not explicitly set in
the user-supplied set of parameters of each single node connection. This
is definitely handy, but it has some limits especially when dealing with
sentinel nodes since there are times when it is better to use different
defaults (e.g. "timeout") and they do not support certain parameters.

This commit adds the ability to specify role-specific default parameters
that gets applied only to connections targeting specific roles. This is
mostly useful for sentinels as they usually require lower timeouts than
normal Redis nodes and may also have a different password.

Role-specific parameters are passed as part of the "parameters" client
option in the form of named sub-arrays and take precedence over global
parameters, but they still do not override parameters explicitly set by
the user for single nodes.

Supported keys are "role.sentinel", "role.master" and "role.slave". In
regards to "role.sentinel", please note that:

  - sentinels do not support ACL authentication or database selection so
    so "username" and "database" are always stripped off.
  - "password" is never inherited from global defaults because users can
    have password-protected Redis nodes but unprotected Redis sentinels.
    In such cases, users must explicitly set a password either for each
    sentinel connection or just once in "role.sentinel".

Here is a brief example showing how to configure Predis for replication
supervised by redis-sentinel using different timeout and password values
for sentinel nodes compared to normal master and replica nodes.

  $client = new Predis\Client($arrayOfSentinels, [
    'replication' => 'sentinel',
    'service' => $sentinelService,

    'parameters' => [
      // Set of global default parameters, applied to *any* connection:
      'scheme' => true,
      'tcp_nodelay' => true,
      'timeout' => 5,
      'username' => $redisUsername, // Won't be inherited by sentinels.
      'password' => $redisPassword, // Won't be inherited by sentinels.

      // Set of sentinels-specific default parameters:
      'role.sentinel' => [
        // For sentinels, "scheme" and "tcp_nodelay" are inherited from
        // default parameters and "timeout" is overridden. On the other
        // hand both "username" and "password" are never inherited but
        // still explicitly set a password for sentinels because, in our
        // example, sentinels are indeed password-protected.
        'timeout' => 0.200,
        'password' => $sentinelPassword,
      ],
  ]);
2020-09-12 17:27:32 +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) 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) 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