Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Cache] Add ability to configure predis client.#28175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
effe292 to05c319fComparenicolas-grekas commentedAug 9, 2018
Hello, thanks for the PR. Here is the options reference: To understand better, which options are useful in your case? |
jralph commentedAug 9, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
No problem, I'd be happy to provide some more info! The predis docs are a little off in the wiki. The readme.md specifies there are 3 options, the one mentioned in the wiki, plus either See:https://github.com/nrk/predis#client-configuration The |
nicolas-grekas commentedAug 14, 2018
Thanks for the links. Right now, Predis is skipped when ext-redis is installed. |
jralph commentedAug 14, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Do you reckon it would be better to throw an exception in that case, or to enforce the use of predis instead? This could be could be done expanding uppon the if statement that checks for the existence of ext-redis. It could check for ext-redis as well as predis options and default to predis if they are present. It's possible someone could have ext-redis available, but would prefer to use predis for the clustering capability. But still use ext-redis for other redis instances that are not clustered. Allowing the |
nicolas-grekas commentedAug 14, 2018
Setting the |
0f08f1b to2fe2f53Comparejralph commentedAug 15, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I haven't got much experience with the redis extension, does the I agree, I think having the code work out what you're trying to use and fail on an invalid configuration setup is ideal. I've updated the code to reflect the more automated configuration approach as well as added tests to check this config. If a predis option is specified and predis is not available it will throw a |
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
some more comment to help move forward.
LGTM afterwards, thanks.
| $params +=$options +self::$defaultConnectionOptions; | ||
| if (null ===$params['class'] && !\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { | ||
| thrownewCacheException(sprintf('Cannot find the "redis" extension, and "predis/predis" is not installed: %s',$dsn)); | ||
| }elseif (isset($params['predis_options']) && !class_exists(\Predis\Client::class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
we prefer replacing such "elseif" by an "if" (can be done when the previous "if" break the code flow, with throw or return typically. (same below)
| if (null ===$params['class'] && !\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { | ||
| thrownewCacheException(sprintf('Cannot find the "redis" extension, and "predis/predis" is not installed: %s',$dsn)); | ||
| }elseif (isset($params['predis_options']) && !class_exists(\Predis\Client::class)) { | ||
| thrownewCacheException(sprintf('DSN contains "predis_options" and "predis/predis" is not installed: %s',$dsn)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The option can come from the $options argument, so the message should not tell about the DSN I'd say.
What about `Invalid connection option: "predis_options" provided but "predis/predis" is not installed.', $dsn));
| thrownewCacheException(sprintf('DSN contains "predis_options" and "predis/predis" is not installed: %s',$dsn)); | ||
| }elseif (isset($params['predis_options']) || !\extension_loaded('redis')) { | ||
| if (null !==$params['class'] && !is_a($params['class'], \Predis\Client::class,true)) { | ||
| thrownewInvalidArgumentException(sprintf('Cannot find the "redis" extension and expected an instance of %s, instead got: %s', \Predis\Client::class,$params['class'])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
the message is confusing: when the extensionis installed, we should tell otherwise.
| thrownewInvalidArgumentException(sprintf('Cannot find the "redis" extension and expected an instance of %s, instead got: %s', \Predis\Client::class,$params['class'])); | ||
| } | ||
| $class =null ===$params['class'] ? \Predis\Client::class :$params['class']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
$class = $params['class'] ?? \Predis\Client::class; (same below)
| $params['password'] =$auth; | ||
| $redis =new$class((newFactory())->create($params)); | ||
| $predisOptions =false !==isset($params['predis_options']) &&true ===\is_array($params['predis_options']) ?$params['predis_options'] :array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
no need for the boolean comparisons:$predisOptions = isset($params['predis_options']) && \is_array($params['predis_options']) ? $params['predis_options'] : array();
but shouldn't we throw when predis_options is not an array?
5794698 to1ac9b3eComparejralph commentedAug 16, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Great, I've made those suggested changes now and cleaned up a few of the exception messages a bit! |
| * added sub-second expiry accuracy for backends that support it | ||
| * added support for phpredis 4`compression` and`tcp_keepalive` options | ||
| * added automatic table creation when using Doctrine DBAL with PDO-based backends | ||
| * added support for a`predis_options` query parameter array in the redis dsn. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
DSN
| $predisOptions =$params['predis_options'] ??array(); | ||
| if (!\is_array($predisOptions)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
We are not doing this kind of checks anywhere in the code base, not sure if we want it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
What would you recommend instead? If we don't check and throw an exception predis will, I would imagine this would suffice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Letting predis handle the situation seems better.
jralph commentedAug 20, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I've made the suggested changes in the code and the Was the line doing |
dcff981 toa260177CompareWhen the predis driver is created, there is no current way toconfigure the predis client options (such as setting the clustermode to redis). This merge allows you to add a predis_optionsparameter to the dsn to allow configuration of options.
jralph commentedAug 21, 2018
I'm not sure what's caused the tests to fail for travic-ci there. Any ideas? Seems to be something to do with the Process component? |
jralph commentedSep 10, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@fabpot Were the changes made suitable for what you mentioned? |
nicolas-grekas commentedSep 10, 2018
See proposal in#28300 (comment) |
jralph commentedSep 13, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Having done some more debugging on this, I do not believe my merge is yet complete so please do not accept it yet. There is an issue where passing in a single host to predis causes it to ignore the clustering setup completely, using the default stream connection instead of creating a cluster. (For example, aws elasticache redis clusters that have a single entry endpoint.) I'm not yet quite sure on how to approach this, possibly if clustering is expected, to pass in an array of hosts (an array of 1 host works), instead of a single string to the factory. It also appears the predis factory does not support creating a redis cluster connection. The current tests pass only because when calling the code to get the I think this changes the scope of changes required to the |
nicolas-grekas commentedOct 3, 2018
Closing in favor of#28713 |
… via DSN (nicolas-grekas)This PR was merged into the 4.2-dev branch.Discussion----------[Cache] added support for connecting to Redis clusters via DSN| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | -| License | MIT| Doc PR | -Replaces#28300 and#28175This PR allows configuring a cluster of Redis servers using all available options of either the phpredis extension or the Predis package:- the `redis_cluster=0/1` boolean option configures whether the client should use the Redis cluster protocol;- several hosts can be provided using a syntax very similar to#28598, enabling consistent hashing distribution of keys;- `failover=error/distribute/slaves` can be set to direct reads at slave servers;- extra options are passed as is to the driver (e.g. `profile=2.8`)- Predis per-server settings are also possible, using e.g. `host[localhost][alias]=foo` in the query string, or `host[localhost]=alias%3Dfoo` (ie PHP query arrays or urlencoded key/value pairs)Commits-------a42e877 [Cache] added support for connecting to Redis clusters via DSN
Uh oh!
There was an error while loading.Please reload this page.
When using
predis/predis, there is currently no way to set any options as the 2nd parameter in thePredis\Clientconstructor. This merge allows you to define these options with apredis_optionsquery parameter in the dsn.Example: