#113071 init Namoshek
This commit is contained in:
parent
3421b02c8b
commit
0e934d08ac
|
@ -0,0 +1,152 @@
|
||||||
|
скопированно отсюда https://github.com/Namoshek/laravel-redis-sentinel/tree/master
|
||||||
|
|
||||||
|
# Laravel Redis Sentinel driver for `phpredis/phpredis` PHP extension
|
||||||
|
|
||||||
|
[](https://packagist.org/packages/namoshek/laravel-redis-sentinel)
|
||||||
|
[](https://packagist.org/packages/namoshek/laravel-redis-sentinel)
|
||||||
|
[](https://github.com/Namoshek/laravel-redis-sentinel/actions?query=workflow%3ATests)
|
||||||
|
[](https://sonarcloud.io/dashboard?id=namoshek_laravel-redis-sentinel)
|
||||||
|
[](https://sonarcloud.io/dashboard?id=namoshek_laravel-redis-sentinel)
|
||||||
|
[](https://sonarcloud.io/dashboard?id=namoshek_laravel-redis-sentinel)
|
||||||
|
[](https://sonarcloud.io/dashboard?id=namoshek_laravel-redis-sentinel)
|
||||||
|
[](https://sonarcloud.io/dashboard?id=namoshek_laravel-redis-sentinel)
|
||||||
|
[](https://packagist.org/packages/namoshek/laravel-redis-sentinel)
|
||||||
|
|
||||||
|
This package provides a Laravel Redis driver which allows connecting to a Redis master through a Redis Sentinel instance.
|
||||||
|
The package is intended to be used in a Kubernetes environment or similar, where connecting to Redis Sentinels is possible through a load balancer.
|
||||||
|
|
||||||
|
This driver is an alternative to [`monospice/laravel-redis-sentinel-drivers`](https://github.com/monospice/laravel-redis-sentinel-drivers).
|
||||||
|
The primary difference is that this driver supports the [`phpredis/phpredis` PHP extension](https://github.com/phpredis/phpredis)
|
||||||
|
and has significantly simpler configuration, due to a simpler architecture.
|
||||||
|
In detail this means that this package does not override the entire Redis subsystem of Laravel, it only adds an additional driver.
|
||||||
|
|
||||||
|
By default, Laravel supports the `predis` and `phpredis` drivers. This package adds a third `phpredis-sentinel` driver,
|
||||||
|
which is an extension of the `phpredis` driver for Redis Sentinel.
|
||||||
|
An extension for `predis` is currently not available and not necessary, since [`predis/predis`](https://github.com/predis/predis) already supports
|
||||||
|
connecting to Redis through one or more Sentinels.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
You can install the package via composer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require namoshek/laravel-redis-sentinel
|
||||||
|
```
|
||||||
|
|
||||||
|
The service provider which comes with the package is registered automatically.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The package requires no extra configuration and does therefore not provide an additional configuration file.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use the Redis Sentinel driver, the `redis` section in `config/database.php` needs to be adjusted:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'redis' => [
|
||||||
|
'client' => env('REDIS_CLIENT', 'phpredis-sentinel'),
|
||||||
|
|
||||||
|
'default' => [
|
||||||
|
'sentinel_host' => env('REDIS_SENTINEL_HOST', '127.0.0.1'),
|
||||||
|
'sentinel_port' => (int) env('REDIS_SENTINEL_PORT', 26379),
|
||||||
|
'sentinel_service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
|
||||||
|
'sentinel_timeout' => (float) env('REDIS_SENTINEL_TIMEOUT', 0),
|
||||||
|
'sentinel_persistent' => env('REDIS_SENTINEL_PERSISTENT'),
|
||||||
|
'sentinel_retry_interval' => (int) env('REDIS_SENTINEL_RETRY_INTERVAL', 0),
|
||||||
|
'sentinel_read_timeout' => (float) env('REDIS_SENTINEL_READ_TIMEOUT', 0),
|
||||||
|
'sentinel_username' => env('REDIS_SENTINEL_USERNAME'),
|
||||||
|
'sentinel_password' => env('REDIS_SENTINEL_PASSWORD'),
|
||||||
|
'password' => env('REDIS_PASSWORD'),
|
||||||
|
'database' => (int) env('REDIS_DB', 0),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of changing `redis.client` in the configuration file directly, you can also set `REDIS_CLIENT=phpredis-sentinel` in the environment variables.
|
||||||
|
|
||||||
|
As you can see, there are also a few new `sentinel_*` options available for each Redis connection.
|
||||||
|
Most of them work very similar to the normal Redis options, except that they are used for the connection to Redis Sentinel.
|
||||||
|
Noteworthy is the `sentinel_service`, which represents the instance name of the monitored Redis master.
|
||||||
|
|
||||||
|
All other options are the same for the Redis Sentinel driver, except that `url` is not supported and `host` and `port` are ignored.
|
||||||
|
|
||||||
|
### SSL/TLS Support
|
||||||
|
|
||||||
|
If you want to use SSL/TLS to connect to Redis Sentinel, you need to add an additional configuration option `sentinel_ssl` next to the other `sentinel_*` settings:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'sentinel_ssl' => [
|
||||||
|
// ... SSL settings ...
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
Available SSL context options can be found in the [official PHP documentation](https://www.php.net/manual/en/context.ssl.php). Please note that SSL support for the Sentinel connection was added to the `phpredis` extension starting in version 6.1.
|
||||||
|
|
||||||
|
Also note that if your Redis Sentinel resolves SSL connections to Redis, you potentially need to add additional context options for your Redis connection:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'context' => [
|
||||||
|
'stream' => [
|
||||||
|
// ... SSL settings ...
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'scheme' => 'tls',
|
||||||
|
```
|
||||||
|
|
||||||
|
A full configuration example using SSL for Redis Sentinel as well as Redis looks like this if authentication is also enabled (environment variables omitted for clarity):
|
||||||
|
|
||||||
|
```php
|
||||||
|
'redis' => [
|
||||||
|
'client' => 'phpredis-sentinel',
|
||||||
|
|
||||||
|
'redis_with_tls' => [
|
||||||
|
'sentinel_host' => 'tls://sentinel_host',
|
||||||
|
'sentinel_port' => 26379,
|
||||||
|
'sentinel_service' => 'mymaster',
|
||||||
|
'sentinel_timeout' => 0,
|
||||||
|
'sentinel_persistent' => false,
|
||||||
|
'sentinel_retry_interval' => 0,
|
||||||
|
'sentinel_read_timeout' => 0,
|
||||||
|
'sentinel_username' => 'sentinel_username',
|
||||||
|
'sentinel_password' => 'sentinel_password',
|
||||||
|
'sentinel_ssl' => [
|
||||||
|
'cafile' => '/path/to/sentinel_ca.crt',
|
||||||
|
],
|
||||||
|
'context' => [
|
||||||
|
'stream' => [
|
||||||
|
'cafile' => '/path/to/redis_ca.crt',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'scheme' => 'tls',
|
||||||
|
'username' => 'redis_username',
|
||||||
|
'password' => 'redis_password',
|
||||||
|
'database' => 1,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
The important parts are the `tls://` protocol in `sentinel_host` as well as the `tls` in `scheme`, plus the `sentinel_ssl` and `context.stream` options.
|
||||||
|
|
||||||
|
Because Redis Sentinel resolves Redis instances by IP and port, your Redis certificate needs to have the IP as SAN. Alternatively, you can set `verify_peer` and maybe also `verify_peer_name` to `false`.
|
||||||
|
|
||||||
|
### How does it work?
|
||||||
|
|
||||||
|
An additional Laravel Redis driver is added (`phpredis-sentinel`), which resolves the currently declared master instance of a replication
|
||||||
|
cluster as active Redis instance. Under the hood, this driver relies on the framework driver for [`phpredis/phpredis`](https://github.com/phpredis/phpredis),
|
||||||
|
it only wraps the connection part of it and adds some error handling which forcefully reconnects in case of a failover.
|
||||||
|
|
||||||
|
Please be aware that this package does not manage load balancing between Sentinels (which is supposed to be done on an infrastructure level)
|
||||||
|
and does also not load balance read/write calls to replica/master nodes. All traffic is sent to the currently reported master.
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
To run the tests locally, a Redis cluster needs to be running.
|
||||||
|
The repository contains a script (thanks to [`monospice/laravel-redis-sentinel-drivers`](https://github.com/monospice/laravel-redis-sentinel-drivers))
|
||||||
|
which can be used to start one by running `sh start-redis-cluster.sh`.
|
||||||
|
The script requires that Redis is installed on your machine. To install Redis on Ubuntu or Debian,
|
||||||
|
you can use `sudo apt update && sudo apt install redis-server`. For other operating systems, please see [redis.io](https://redis.io/).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
|
@ -11,7 +11,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"namoshek/laravel-redis-sentinel": "^0.8|^0.9"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* @noinspection PhpRedundantCatchClauseInspection */
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Namoshek\Redis\Sentinel\Connections;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Redis\Connections\PhpRedisConnection;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Redis;
|
||||||
|
use RedisException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection to Redis after connecting through a Sentinel using the PhpRedis extension.
|
||||||
|
*/
|
||||||
|
class PhpRedisSentinelConnection extends PhpRedisConnection
|
||||||
|
{
|
||||||
|
// The following array contains all exception message parts which are interpreted as a connection loss or
|
||||||
|
// another unavailability of Redis.
|
||||||
|
private const ERROR_MESSAGES_INDICATING_UNAVAILABILITY = [
|
||||||
|
'connection closed',
|
||||||
|
'connection refused',
|
||||||
|
'connection lost',
|
||||||
|
'failed while reconnecting',
|
||||||
|
'is loading the dataset in memory',
|
||||||
|
'php_network_getaddresses',
|
||||||
|
'read error on connection',
|
||||||
|
'socket',
|
||||||
|
'went away',
|
||||||
|
'loading',
|
||||||
|
'readonly',
|
||||||
|
"can't write against a read only replica",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function scan($cursor, $options = []): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::scan($cursor, $options);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function zscan($key, $cursor, $options = []): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::zscan($key, $cursor, $options);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hscan($key, $cursor, $options = []): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::hscan($key, $cursor, $options);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function sscan($key, $cursor, $options = []): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::sscan($key, $cursor, $options);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function pipeline(?callable $callback = null): Redis|array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::pipeline($callback);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function transaction(?callable $callback = null): Redis|array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::transaction($callback);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function evalsha($script, $numkeys, ...$arguments): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::evalsha($script, $numkeys, $arguments);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function subscribe($channels, Closure $callback): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
parent::subscribe($channels, $callback);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function psubscribe($channels, Closure $callback): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
parent::psubscribe($channels, $callback);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function flushdb(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
parent::flushdb();
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function command($method, array $parameters = []): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::command($method, $parameters);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function __call($method, $parameters): mixed
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::__call(strtolower($method), $parameters);
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$this->reconnectIfRedisIsUnavailableOrReadonly($e);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inspects the given exception and reconnects the client if the reported error indicates that the server
|
||||||
|
* went away or is in readonly mode, which may happen in case of a Redis Sentinel failover.
|
||||||
|
*/
|
||||||
|
private function reconnectIfRedisIsUnavailableOrReadonly(RedisException $exception): void
|
||||||
|
{
|
||||||
|
// We convert the exception message to lower-case in order to perform case-insensitive comparison.
|
||||||
|
$exceptionMessage = strtolower($exception->getMessage());
|
||||||
|
|
||||||
|
// Because we also match only partial exception messages, we cannot use in_array() at this point.
|
||||||
|
foreach (self::ERROR_MESSAGES_INDICATING_UNAVAILABILITY as $errorMessage) {
|
||||||
|
if (str_contains($exceptionMessage, $errorMessage)) {
|
||||||
|
// Here we reconnect through Redis Sentinel if we lost connection to the server or if another unavailability occurred.
|
||||||
|
// We may actually reconnect to the same, broken server. But after a failover occured, we should be ok.
|
||||||
|
// It may take a moment until the Sentinel returns the new master, so this may be triggered multiple times.
|
||||||
|
$this->reconnect();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconnects to the Redis server by overriding the current connection.
|
||||||
|
*/
|
||||||
|
private function reconnect(): void
|
||||||
|
{
|
||||||
|
$this->client = $this->connector ? call_user_func($this->connector) : $this->client;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,29 +2,125 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Dominion\Redis\Sentinel\Connectors;
|
namespace Namoshek\Redis\Sentinel\Connectors;
|
||||||
|
|
||||||
|
use Illuminate\Redis\Connectors\PhpRedisConnector;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Namoshek\Redis\Sentinel\Connections\PhpRedisSentinelConnection;
|
||||||
|
use Namoshek\Redis\Sentinel\Exceptions\ConfigurationException;
|
||||||
|
use Redis;
|
||||||
|
use RedisException;
|
||||||
use RedisSentinel;
|
use RedisSentinel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to connect to a Sentinel driven Redis master using the PhpRedis extension.
|
* Allows to connect to a Sentinel driven Redis master using the PhpRedis extension.
|
||||||
*/
|
*/
|
||||||
class PhpRedisSentinelConnector extends \Namoshek\Redis\Sentinel\Connectors\PhpRedisSentinelConnector
|
class PhpRedisSentinelConnector extends PhpRedisConnector
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function connect(array $config, array $options): PhpRedisSentinelConnection
|
||||||
|
{
|
||||||
|
$connector = function () use ($config, $options) {
|
||||||
|
return $this->createClient(array_merge(
|
||||||
|
$config,
|
||||||
|
$options,
|
||||||
|
Arr::pull($config, 'options', [])
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
return new PhpRedisSentinelConnection($connector(), $connector, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the PhpRedis client instance which connects to Redis Sentinel.
|
||||||
|
*
|
||||||
|
* @throws ConfigurationException
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
protected function createClient(array $config): Redis
|
||||||
|
{
|
||||||
|
$service = $config['sentinel_service'] ?? 'mymaster';
|
||||||
|
|
||||||
|
$sentinel = $this->connectToSentinel($config);
|
||||||
|
|
||||||
|
$master = $sentinel->master($service);
|
||||||
|
|
||||||
|
if (! $this->isValidMaster($master)) {
|
||||||
|
throw new RedisException(sprintf("No master found for service '%s'.", $service));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::createClient(array_merge($config, [
|
||||||
|
'host' => $master['ip'],
|
||||||
|
'port' => $master['port'],
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether master is valid or not.
|
||||||
|
*/
|
||||||
|
protected function isValidMaster(mixed $master): bool
|
||||||
|
{
|
||||||
|
return is_array($master) && isset($master['ip']) && isset($master['port']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the configured Redis Sentinel instance.
|
||||||
|
*
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
private function connectToSentinel(array $config): RedisSentinel
|
private function connectToSentinel(array $config): RedisSentinel
|
||||||
{
|
{
|
||||||
$hosts = is_array($config['sentinel_host']) ? $config['sentinel_host'] : [$config['sentinel_host']];
|
$host = $config['sentinel_host'] ?? '';
|
||||||
foreach ($hosts as $host)
|
$port = $config['sentinel_port'] ?? 26379;
|
||||||
{
|
$timeout = $config['sentinel_timeout'] ?? 0.2;
|
||||||
$newConfig = $config;
|
$persistent = $config['sentinel_persistent'] ?? null;
|
||||||
$newConfig['sentinel_host'] = $host;
|
$retryInterval = $config['sentinel_retry_interval'] ?? 0;
|
||||||
$RedisSentinel = parent::connectToSentinel($newConfig);
|
$readTimeout = $config['sentinel_read_timeout'] ?? 0;
|
||||||
if($RedisSentinel->ping())
|
$username = $config['sentinel_username'] ?? '';
|
||||||
{
|
$password = $config['sentinel_password'] ?? '';
|
||||||
break;
|
$ssl = $config['sentinel_ssl'] ?? null;
|
||||||
}
|
|
||||||
|
if (strlen(trim($host)) === 0) {
|
||||||
|
throw new ConfigurationException('No host has been specified for the Redis Sentinel connection.');
|
||||||
}
|
}
|
||||||
return $RedisSentinel;
|
|
||||||
|
$auth = null;
|
||||||
|
if (strlen(trim($username)) !== 0 && strlen(trim($password)) !== 0) {
|
||||||
|
$auth = [$username, $password];
|
||||||
|
} elseif (strlen(trim($password)) !== 0) {
|
||||||
|
$auth = $password;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_compare(phpversion('redis'), '6.0', '>=')) {
|
||||||
|
$options = [
|
||||||
|
'host' => $host,
|
||||||
|
'port' => $port,
|
||||||
|
'connectTimeout' => $timeout,
|
||||||
|
'persistent' => $persistent,
|
||||||
|
'retryInterval' => $retryInterval,
|
||||||
|
'readTimeout' => $readTimeout,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($auth !== null) {
|
||||||
|
$options['auth'] = $auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_compare(phpversion('redis'), '6.1', '>=') && $ssl !== null) {
|
||||||
|
$options['ssl'] = $ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RedisSentinel($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($auth !== null) {
|
||||||
|
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||||
|
return new RedisSentinel($host, $port, $timeout, $persistent, $retryInterval, $readTimeout, $auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RedisSentinel($host, $port, $timeout, $persistent, $retryInterval, $readTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Namoshek\Redis\Sentinel\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception to be used if wrong application configuration is encountered.
|
||||||
|
*/
|
||||||
|
class ConfigurationException extends \RuntimeException
|
||||||
|
{
|
||||||
|
}
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Dominion\Redis\Sentinel;
|
namespace Namoshek\Redis\Sentinel;
|
||||||
|
|
||||||
use Illuminate\Redis\RedisManager;
|
use Illuminate\Redis\RedisManager;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Dominion\Redis\Sentinel\Connectors\PhpRedisSentinelConnector;
|
use Namoshek\Redis\Sentinel\Connectors\PhpRedisSentinelConnector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers and boots services of the Laravel Redis Sentinel package.
|
* Registers and boots services of the Laravel Redis Sentinel package.
|
||||||
|
@ -21,7 +21,7 @@ class RedisSentinelServiceProvider extends ServiceProvider
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
$this->app->extend('redis', function (RedisManager $service) {
|
$this->app->extend('redis', function (RedisManager $service) {
|
||||||
return $service->extend('dominion-phpredis-sentinel', fn () => new PhpRedisSentinelConnector);
|
return $service->extend('phpredis-sentinel', fn () => new PhpRedisSentinelConnector);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue