From 1c3ef9a08790a24e6c7b5221e4f007b45b61881e Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 11:43:19 +0800 Subject: [PATCH 01/97] =?UTF-8?q?Update:=20=E5=AE=9E=E7=8E=B0=E6=96=B0?= =?UTF-8?q?=E7=9A=84=20Redis=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/model/src/RedisModel.php | 89 ++- src/Components/redis/composer.json | 38 ++ src/Components/redis/dev/Dev.php | 77 +++ src/Components/redis/helper.php | 4 + .../redis/src}/Annotation/RedisInject.php | 0 .../redis/src/Connector/IRedisConnector.php | 15 + .../redis/src/Connector/PhpRedisConnector.php | 78 +++ .../redis/src/Connector/PredisConnector.php | 60 ++ .../src/Connector/RedisConnectionDriver.php | 77 +++ .../redis/src/Connector/RedisDriverConfig.php | 48 ++ src/Components/redis/src/Enum/RedisMode.php | 23 + .../src/Handler/AbstractRedisHandler.php | 15 + .../src/Handler/IRedisClusterHandler.php | 13 + .../redis/src/Handler/IRedisHandler.php | 12 + .../redis/src/Handler/IRedisScanExMethod.php | 16 + .../src/Handler/PhpRedisClusterHandler.php | 62 ++ .../redis/src/Handler/PhpRedisHandler.php | 49 ++ .../src/Handler/PredisClusterHandler.php | 85 +++ .../redis/src/Handler/PredisHandler.php | 53 ++ src/{Redis => Components/redis/src}/Redis.php | 38 +- src/Components/redis/src/RedisManager.php | 139 +++++ .../redis/src/Traits/TPhpRedisMethod.php | 181 ++++++ .../redis/src/Traits/TPredisMethod.php | 133 +++++ src/Components/redis/tests/PHPUnitHook.php | 37 ++ .../tests/Tests/AbstractRedisTestCase.php | 23 + .../tests/Tests/Model/AbstractRedisModel.php | 345 +++++++++++ .../Tests/Model/AbstractRedisModelHash.php | 224 +++++++ .../Model/AbstractRedisModelHashObject.php | 206 +++++++ .../PhpRedis/PhpRedisModelHashObjectTest.php | 14 + .../Model/PhpRedis/PhpRedisModelHashTest.php | 14 + .../Model/PhpRedis/PhpRedisModelTest.php | 14 + .../PhpRedisModelHashObjectTest.php | 14 + .../PhpRedisCluster/PhpRedisModelHashTest.php | 14 + .../PhpRedisCluster/PhpRedisModelTest.php | 14 + .../tests/Tests/Model/Predis/PredisModel.php | 16 + .../Tests/Model/Predis/PredisModelHash.php | 16 + .../Model/Predis/PredisModelHashObject.php | 16 + .../redis/tests/Tests/PhpRedisClusterTest.php | 38 ++ .../redis/tests/Tests/PhpRedisTest.php | 186 ++++++ .../redis/tests/Tests/PredisClusterTest.php | 52 ++ .../redis/tests/Tests/PredisTest.php | 41 ++ .../redis/tests}/Tests/RedisManagerTest.php | 30 +- .../redis/tests}/Tests/RedisTest.php | 19 +- src/Components/redis/tests/bootstrap.php | 5 + src/Components/redis/tests/config/config.php | 184 ++++++ src/Components/redis/tests/phpunit.xml | 24 + .../src/Redis/Pool/CoroutineRedisPool.php | 26 - src/Redis/Enum/RedisMode.php | 25 - src/Redis/Listener/CheckPoolResource.php | 3 + src/Redis/RedisHandler.php | 548 ------------------ src/Redis/RedisManager.php | 210 ------- src/Redis/RedisResource.php | 54 +- src/Redis/SyncRedisPool.php | 3 + src/Redis/Traits/TRedisPool.php | 53 +- 54 files changed, 2838 insertions(+), 935 deletions(-) create mode 100644 src/Components/redis/composer.json create mode 100644 src/Components/redis/dev/Dev.php create mode 100644 src/Components/redis/helper.php rename src/{Redis => Components/redis/src}/Annotation/RedisInject.php (100%) create mode 100644 src/Components/redis/src/Connector/IRedisConnector.php create mode 100644 src/Components/redis/src/Connector/PhpRedisConnector.php create mode 100644 src/Components/redis/src/Connector/PredisConnector.php create mode 100644 src/Components/redis/src/Connector/RedisConnectionDriver.php create mode 100644 src/Components/redis/src/Connector/RedisDriverConfig.php create mode 100644 src/Components/redis/src/Enum/RedisMode.php create mode 100644 src/Components/redis/src/Handler/AbstractRedisHandler.php create mode 100644 src/Components/redis/src/Handler/IRedisClusterHandler.php create mode 100644 src/Components/redis/src/Handler/IRedisHandler.php create mode 100644 src/Components/redis/src/Handler/IRedisScanExMethod.php create mode 100644 src/Components/redis/src/Handler/PhpRedisClusterHandler.php create mode 100644 src/Components/redis/src/Handler/PhpRedisHandler.php create mode 100644 src/Components/redis/src/Handler/PredisClusterHandler.php create mode 100644 src/Components/redis/src/Handler/PredisHandler.php rename src/{Redis => Components/redis/src}/Redis.php (88%) create mode 100644 src/Components/redis/src/RedisManager.php create mode 100644 src/Components/redis/src/Traits/TPhpRedisMethod.php create mode 100644 src/Components/redis/src/Traits/TPredisMethod.php create mode 100644 src/Components/redis/tests/PHPUnitHook.php create mode 100644 src/Components/redis/tests/Tests/AbstractRedisTestCase.php create mode 100644 src/Components/redis/tests/Tests/Model/AbstractRedisModel.php create mode 100644 src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php create mode 100644 src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelHashObjectTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelHashTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php create mode 100644 src/Components/redis/tests/Tests/Model/Predis/PredisModel.php create mode 100644 src/Components/redis/tests/Tests/Model/Predis/PredisModelHash.php create mode 100644 src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObject.php create mode 100644 src/Components/redis/tests/Tests/PhpRedisClusterTest.php create mode 100644 src/Components/redis/tests/Tests/PhpRedisTest.php create mode 100644 src/Components/redis/tests/Tests/PredisClusterTest.php create mode 100644 src/Components/redis/tests/Tests/PredisTest.php rename {tests/unit/Component => src/Components/redis/tests}/Tests/RedisManagerTest.php (75%) rename {tests/unit/Component => src/Components/redis/tests}/Tests/RedisTest.php (92%) create mode 100644 src/Components/redis/tests/bootstrap.php create mode 100644 src/Components/redis/tests/config/config.php create mode 100644 src/Components/redis/tests/phpunit.xml delete mode 100644 src/Components/swoole/src/Redis/Pool/CoroutineRedisPool.php delete mode 100644 src/Redis/Enum/RedisMode.php delete mode 100644 src/Redis/RedisHandler.php delete mode 100644 src/Redis/RedisManager.php diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index 840918f51f..552e59a291 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -17,6 +17,8 @@ use Imi\Redis\RedisHandler; use Imi\Redis\RedisManager; use Imi\Util\Format\IFormat; +use Imi\Util\Imi; +use function Imi\dump; /** * Redis 模型. @@ -53,6 +55,14 @@ abstract class RedisModel extends BaseModel */ protected ?int $__ttl = null; + /** + * 动态模型集合. + */ + protected static array $__forks = []; + + /** + * @param class-string|RedisModel|null $object + */ public static function __getRedisEntity(string|self|null $object = null): ?RedisEntity { if (null === $object) @@ -468,7 +478,9 @@ public function safeDelete(): bool $data = $formatter->encode($data); } $redis = static::__getRedis($this); - $data = $redis->_serialize($data); + if ($redis->isSupportSerialize()) { + $data = $redis->_serialize($data); + } return (bool) $redis->evalEx(<<<'LUA' if (ARGV[1] == redis.call('get', KEYS[1])) then @@ -485,7 +497,9 @@ public function safeDelete(): bool $data = $formatter->encode($data); } $redis = static::__getRedis($this); - $data = $redis->_serialize($data); + if ($redis->isSupportSerialize()) { + $data = $redis->_serialize($data); + } return (bool) $redis->evalEx(<<<'LUA' if (ARGV[2] == redis.call('hget', KEYS[1], ARGV[1])) then @@ -500,7 +514,9 @@ public function safeDelete(): bool foreach ($data as $key => $value) { $argv[] = $key; - $argv[] = $redis->_serialize($value); + if ($redis->isSupportSerialize()) { + $argv[] = $redis->_serialize($value); + } } return (bool) $redis->evalEx(<<<'LUA' @@ -656,7 +672,7 @@ public function __getMember(): string */ public static function __getRedis(?self $redisModel = null): RedisHandler { - $annotation = static::__getRedisEntity($redisModel ?? static::class); + $annotation = static::__getRedisEntity($redisModel ?? static::class, false); $redis = RedisManager::getInstance($annotation->poolName); if (null !== $annotation->db) { @@ -718,8 +734,7 @@ public static function __getKeyRule(string|self|null $object = null): KeyRule } else { - /** @var RedisEntity|null $redisEntity */ - $redisEntity = AnnotationManager::getClassAnnotations($class, RedisEntity::class, true, true); + $redisEntity = static::__getRedisEntity($class); $key = $redisEntity ? $redisEntity->key : ''; preg_match_all('/{([^}]+)}/', $key, $matches); @@ -747,8 +762,7 @@ public static function __getMemberRule(string|self|null $object = null): KeyRule } else { - /** @var RedisEntity|null $redisEntity */ - $redisEntity = AnnotationManager::getClassAnnotations($class, RedisEntity::class, true, true); + $redisEntity = static::__getRedisEntity($object); $key = $redisEntity ? $redisEntity->member : ''; preg_match_all('/{([^}]+)}/', $key, $matches); @@ -827,4 +841,63 @@ protected function parseSaveData(array &$data): void } } } + + /** + * Fork 模型. + * + * @param class-string|null $formatter + * @return class-string + */ + public static function fork(?int $db = null, ?string $poolName = null, ?string $formatter = null): string + { + // todo 觉得 model 的 meta 设置不统一, 建议 BaseModel 能提供更多底层支持扩展支持 + // 建议能传入 RedisEntity 对象的全部参数,能适用于更多场景 + $forks = &self::$__forks; + if (isset($forks[static::class][$db][$poolName])) + { + return $forks[static::class][$db][$poolName]; + } + $namespace = Imi::getClassNamespace(static::class); + $entity = static::__getRedisEntity(); + if (null !== $db) + { + $entity->db = $db; + } + if (null !== $poolName) + { + $entity->poolName = $poolName; + } + if (null !== $formatter) { + $entity->formatter = $formatter; + } + $entityData = \var_export(\serialize($entity), true); + $class = str_replace('\\', '__', static::class . '\\' . md5($db . '\\' . $poolName . '\\' . $formatter)); + $extendsClass = static::class; + + Imi::eval(<<getComposer()->getPackage(); + $requires = $package->getRequires(); + foreach ($requires as $name => &$require) + { + if ('imiphp/' !== substr($name, 0, 7) || !is_dir(\dirname($dir) . '/' . substr($name, 11))) + { + continue; + } + // @phpstan-ignore-next-line + $require = new Link($require->getSource(), $require->getTarget(), new MultiConstraint([ + new Constraint('>=', '3.0'), + new Constraint('<', '3.1'), + ]), $require->getDescription()); + } + $package->setRequires($requires); + + $requires = $package->getDevRequires(); + foreach ($requires as $name => &$require) + { + if ('imiphp/' !== substr($name, 0, 7) || !is_dir(\dirname($dir) . '/' . substr($name, 11))) + { + continue; + } + // @phpstan-ignore-next-line + $require = new Link($require->getSource(), $require->getTarget(), new MultiConstraint([ + new Constraint('>=', '3.0'), + new Constraint('<', '3.1'), + ]), $require->getDescription()); + } + $package->setDevRequires($requires); + } + + // @phpstan-ignore-next-line + public static function postUpdate(Event $event): void + { + // @phpstan-ignore-next-line + $componentsName = $event->getComposer()->getPackage()->getName(); + $dir = \dirname(__DIR__); + + foreach (InstalledVersions::getInstalledPackages() as $name) + { + if ($componentsName === $name) + { + continue; + } + $componentDir = \dirname($dir) . '/' . substr($name, 11); + if ('imiphp/' !== substr($name, 0, 7) || !is_dir($componentDir)) + { + continue; + } + + $path = "{$dir}/vendor/{$name}"; + $cmd = "rm -rf {$path} && ln -s -f {$componentDir} {$path}"; + echo '[cmd] ', $cmd, \PHP_EOL; + echo shell_exec($cmd), \PHP_EOL; + } + } +} diff --git a/src/Components/redis/helper.php b/src/Components/redis/helper.php new file mode 100644 index 0000000000..23d72b4634 --- /dev/null +++ b/src/Components/redis/helper.php @@ -0,0 +1,4 @@ +host; + if (str_contains($host, '/')) + { + // unix socket + $redis->connect($host); + } + else + { + $redis->connect($host, $config->port, $config->timeout); + } + if (('' !== ($config->password)) && !$redis->auth($config->password)) + { + throw new \RedisException($redis->getLastError()); + } + if (null !== $config->database && !$redis->select($config->database)) + { + throw new \RedisException($redis->getLastError()); + } + + self::applyOptions($redis, $config); + + return new PhpRedisHandler($redis); + } + + public static function connectCluster(RedisDriverConfig $config): PhpRedisClusterHandler + { + $seeds = $config->seeds; + $timeout = $config->timeout; + $readTimeout = $config->readTimeout; + $password = $config->password; + + $redis = new \RedisCluster(null, $seeds, $timeout, $readTimeout, false, $password); + + self::applyOptions($redis, $config); + + return new PhpRedisClusterHandler($redis); + } + + protected static function applyOptions(\Redis|\RedisCluster $redis, RedisDriverConfig $config): void + { + $options = $config->options ?? []; + // 兼容序列化定义 + if ($config->serialize && !isset($options[\Redis::OPT_SERIALIZER])) + { + $options[\Redis::OPT_SERIALIZER] = \Redis::SERIALIZER_PHP; + } + // 设置自定义选项 + if ($options) + { + foreach ($options as $key => $value) + { + if (!$redis->setOption($key, $value)) + { + throw new \RuntimeException(sprintf('Redis setOption %s=%s failed', $key, $value)); + } + } + } + } +} diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php new file mode 100644 index 0000000000..b144b8b607 --- /dev/null +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -0,0 +1,60 @@ + 'tcp', + 'host' => $config->host, + 'port' => $config->port, + ]; + if ($config->password) { + $params['password'] = $config->password; + } + if (null !== $config->database) { + $params['database'] = $config->database; + } + if ($config->prefix) { + $params['prefix'] = $config->prefix; + } + $client = new \Predis\Client($params); + $client->connect(); + + return new PredisHandler($client); + } + + public static function connectCluster(RedisDriverConfig $config): PredisClusterHandler + { + $seeds = $config->seeds ?? []; + $options['cluster'] = 'redis'; + + if ($config->password) + { + $options['parameters']['password'] = $config->password; + } + if (null !== $config->database) + { + $options['parameters']['database'] = $config->database; + } + if ($config->prefix) { + $options['prefix'] = $config->prefix; + } + + $client = new \Predis\Client($seeds, $options); + $client->connect(); + + return new PredisClusterHandler($client); + } +} diff --git a/src/Components/redis/src/Connector/RedisConnectionDriver.php b/src/Components/redis/src/Connector/RedisConnectionDriver.php new file mode 100644 index 0000000000..b9159065ff --- /dev/null +++ b/src/Components/redis/src/Connector/RedisConnectionDriver.php @@ -0,0 +1,77 @@ +client) + { + 'phpredis' => PhpRedisConnector::class, + 'predis' => PredisConnector::class, + }; + + return match ($config->mode) + { + RedisMode::Standalone => $connector::connect($config), + RedisMode::Cluster => $connector::connectCluster($config), + RedisMode::Sentinel => throw new \RuntimeException('To be implemented'), + }; + } + + public static function createConnectionConfig(array|string $config): IConnectionConfig + { + return RedisDriverConfig::create($config); + } + + /** + * @param IRedisHandler $instance + */ + public function connect(object $instance): object + { + return $instance; + } + + /** + * @param IRedisHandler $instance + */ + public function close(object $instance): void + { + } + + /** + * @param IRedisHandler $instance + */ + public function reset(object $instance): void + { + } + + /** + * @param IRedisHandler $instance + */ + public function checkAvailable(object $instance): bool + { + return $instance->isConnected(); + } + + /** + * @param IRedisHandler $instance + */ + public function ping(object $instance): bool + { + return $instance->isConnected(); + } +} diff --git a/src/Components/redis/src/Connector/RedisDriverConfig.php b/src/Components/redis/src/Connector/RedisDriverConfig.php new file mode 100644 index 0000000000..ec07fbd45b --- /dev/null +++ b/src/Components/redis/src/Connector/RedisDriverConfig.php @@ -0,0 +1,48 @@ + + */ + public function getNodes(): array; +} diff --git a/src/Components/redis/src/Handler/IRedisHandler.php b/src/Components/redis/src/Handler/IRedisHandler.php new file mode 100644 index 0000000000..40fcb94699 --- /dev/null +++ b/src/Components/redis/src/Handler/IRedisHandler.php @@ -0,0 +1,12 @@ +client = $client; + } + + public function getInstance(): \RedisCluster + { + return $this->client; + } + + public function __call(string $name, array $arguments): mixed + { + return $this->client->{$name}(...$arguments); + } + + public function getNodes(): array + { + return $this->client->_masters(); + } + + public function isConnected(): bool + { + foreach ($this->getNodes() as $node) + { + $this->client->ping($node); + } + + return true; + } + + /** + * scan. + */ + public function scan(?int &$iterator, array|string $node, ?string $pattern = null, int $count = 0): array + { + return $this->client->scan($iterator, $node, $pattern, $count); + } + + public function isSupportSerialize(): bool + { + return true; + } +} diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php new file mode 100644 index 0000000000..0680a27327 --- /dev/null +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -0,0 +1,49 @@ +client; + } + + public function __call(string $name, array $arguments): mixed + { + return $this->client->{$name}(...$arguments); + } + + public function isConnected(): bool + { + $result = $this->client->ping(); + + // PHPRedis 扩展,5.0.0 版本开始,ping() 返回为 true,旧版本为 +PONG + return true === $result || '+PONG' === $result; + } + + public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ?string $type = null) + { + return $this->client->scan($iterator, $pattern, $count, $type); + } + + public function isSupportSerialize(): bool + { + return true; + } +} diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php new file mode 100644 index 0000000000..cfebfe073d --- /dev/null +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -0,0 +1,85 @@ +client; + } + + public function getNodes(): array + { + // 详细说明: https://github.com/predis/predis/issues/571#issuecomment-678300308 + /** @var RedisCluster $connection */ + $connection = $this->client->getConnection(); + $nodes = $connection->getSlotMap()->getNodes(); + + return \array_map(function ($node) { + $arr = \explode(':', $node); + $arr[1] = (int) $arr[1]; + return $arr; + }, $nodes); + } + + public function isConnected(): bool + { + foreach ($this->getNodes() as $node) + { + $client = $this->client->getClientBy('id', "{$node[0]}:{$node[1]}"); + if ('PONG' !== (string) $client->ping()) + { + return false; + } + } + + return true; + } + + public function __call(string $name, array $arguments): mixed + { + $result = $this->client->{$name}(...$arguments); + + if ($result instanceof \Predis\Response\Status && 'OK' === (string) $result) + { + return true; + } + + return $result; + } + + /** + * scan. + */ + public function scan(string $node, $cursor, $options): array + { + return $this->client->getClientBy('id', $node)->scan($cursor, $options); + } + + public function close(): void + { + $this->client->disconnect(); + } + + public function isSupportSerialize(): bool + { + return false; + } +} diff --git a/src/Components/redis/src/Handler/PredisHandler.php b/src/Components/redis/src/Handler/PredisHandler.php new file mode 100644 index 0000000000..77b2d7e29b --- /dev/null +++ b/src/Components/redis/src/Handler/PredisHandler.php @@ -0,0 +1,53 @@ +client; + } + + public function isConnected(): bool + { + return 'PONG' === (string) $this->client->ping(); + } + + public function __call(string $name, array $arguments): mixed + { + $result = $this->client->{$name}(...$arguments); + + if ($result instanceof \Predis\Response\Status && 'OK' === (string) $result) + { + return true; + } + + return $result; + } + + public function close(): void + { + $this->client->disconnect(); + } + + public function isSupportSerialize(): bool + { + return false; + } +} diff --git a/src/Redis/Redis.php b/src/Components/redis/src/Redis.php similarity index 88% rename from src/Redis/Redis.php rename to src/Components/redis/src/Redis.php index 5a27c5cd6e..11cf7c63c9 100644 --- a/src/Redis/Redis.php +++ b/src/Components/redis/src/Redis.php @@ -4,9 +4,10 @@ namespace Imi\Redis; -use Imi\Config; +use Imi\ConnectionCenter\Contract\IConnection; +use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Pool\Interfaces\IPoolResource; -use Imi\Pool\PoolManager; +use Imi\Redis\Handler\IRedisHandler; /** * Redis 快捷操作类. @@ -84,7 +85,6 @@ * @method static mixed hSetNx($key, $member, $value) * @method static mixed hStrLen($key, $member) * @method static mixed hVals($key) - * @method static mixed hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) * @method static mixed incr($key) * @method static mixed incrBy($key, $value) * @method static mixed incrByFloat($key, $value) @@ -147,7 +147,6 @@ * @method static mixed sUnion($key, ...$other_keys) * @method static mixed sUnionStore($dst, $key, ...$other_keys) * @method static mixed save() - * @method static mixed scan(&$i_iterator, $str_pattern = null, $i_count = null) * @method static mixed scard($key) * @method static mixed script($cmd, ...$args) * @method static mixed select($dbindex) @@ -166,7 +165,6 @@ * @method static mixed sortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) * @method static mixed sortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) * @method static mixed srem($key, $member, ...$other_members) - * @method static mixed sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) * @method static mixed strlen($key) * @method static mixed subscribe(array $channels, $callback) * @method static mixed swapdb($srcdb, $dstdb) @@ -212,7 +210,6 @@ * @method static mixed zRevRank($key, $member) * @method static mixed zScore($key, $member) * @method static mixed zinterstore($key, array $keys, ?array $weights = null, $aggregate = null) - * @method static mixed zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) * @method static mixed zunionstore($key, array $keys, ?array $weights = null, $aggregate = null) * @method static mixed delete($key, ...$other_keys) * @method static mixed evaluate($script, $args = null, $num_keys = null) @@ -256,31 +253,34 @@ class Redis public static function __callStatic(string $name, array $arguments): mixed { - if (Config::get('@currentServer.redis.quickFromRequestContext', true)) + if (RedisManager::isQuickFromRequestContext()) { return RedisManager::getInstance()->{$name}(...$arguments); } else { - return PoolManager::use(RedisManager::getDefaultPoolName(), static fn (IPoolResource $resource, RedisHandler $redis) => $redis->{$name}(...$arguments)); + return RedisManager::use( + RedisManager::getDefaultPoolName(), + static fn (IConnection $resource, IRedisHandler $redis) => $redis->{$name}(...$arguments), + ); } } /** * 使用回调来使用池子中的资源,无需手动释放 - * 回调有 1 个参数:$instance(操作实例对象,\Imi\Redis\RedisHandler 类型) + * 回调有 1 个参数:$instance(操作实例对象,Imi\Redis\Handler\IRedisHandler 类型) * 本方法返回值为回调的返回值 */ public static function use(callable $callable, ?string $poolName = null, bool $forceUse = false): mixed { $poolName = RedisManager::parsePoolName($poolName); - if (!$forceUse && Config::get('@currentServer.redis.quickFromRequestContext', true) || !PoolManager::exists($poolName)) + if (!$forceUse && RedisManager::isQuickFromRequestContext() || !ConnectionCenter::hasConnectionManager($poolName)) { return $callable(RedisManager::getInstance($poolName)); } else { - return PoolManager::use($poolName, static fn (IPoolResource $resource, RedisHandler $redis) => $callable($redis)); + return RedisManager::use($poolName, static fn (IConnection $resource, IRedisHandler $redis) => $callable($redis)); } } @@ -289,13 +289,13 @@ public static function use(callable $callable, ?string $poolName = null, bool $f */ public static function scan(?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (Config::get('@currentServer.redis.quickFromRequestContext', true)) + if (RedisManager::isQuickFromRequestContext()) { return RedisManager::getInstance()->scan($iterator, $pattern, $count); } else { - return PoolManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, RedisHandler $redis) use (&$iterator, $pattern, $count) { + return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use (&$iterator, $pattern, $count) { return $redis->scan($iterator, $pattern, $count); }); } @@ -306,13 +306,13 @@ public static function scan(?int &$iterator, ?string $pattern = null, int $count */ public static function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (Config::get('@currentServer.redis.quickFromRequestContext', true)) + if (RedisManager::isQuickFromRequestContext()) { return RedisManager::getInstance()->hscan($key, $iterator, $pattern, $count); } else { - return PoolManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, RedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { return $redis->hscan($key, $iterator, $pattern, $count); }); } @@ -323,13 +323,13 @@ public static function hscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (Config::get('@currentServer.redis.quickFromRequestContext', true)) + if (RedisManager::isQuickFromRequestContext()) { return RedisManager::getInstance()->sscan($key, $iterator, $pattern, $count); } else { - return PoolManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, RedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { return $redis->sscan($key, $iterator, $pattern, $count); }); } @@ -340,13 +340,13 @@ public static function sscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (Config::get('@currentServer.redis.quickFromRequestContext', true)) + if (RedisManager::isQuickFromRequestContext()) { return RedisManager::getInstance()->zscan($key, $iterator, $pattern, $count); } else { - return PoolManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, RedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { return $redis->zscan($key, $iterator, $pattern, $count); }); } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php new file mode 100644 index 0000000000..c56b918ad6 --- /dev/null +++ b/src/Components/redis/src/RedisManager.php @@ -0,0 +1,139 @@ +getInstance(); + self::recordInstanceLinkPool($instance, $connection); + return $instance; + } + + /** + * 获取 Redis 连接实例,每个RequestContext中共用一个. + * + * @param string $poolName 连接池名称 + */ + public static function getInstance(?string $poolName = null): IRedisHandler + { + $poolName = self::parsePoolName($poolName); + $connection = ConnectionCenter::getRequestContextConnection($poolName); + /** @var IRedisHandler $instance */ + $instance = $connection->getInstance(); + self::recordInstanceLinkPool($instance, $connection); + return $instance; + } + + /** + * 使用回调来使用池子中的资源,无需手动释放 + * 回调有两个参数:$connection(连接对象), $instance(操作实例对象,Redis实例) + * 本方法返回值为回调的返回值 + */ + public static function use(string $name, callable $callback): mixed + { + $resource = static::getNewInstance($name); + try + { + $connection = self::getConnectionByInstance($resource); + return $callback($connection, $resource); + } + finally + { + static::release($resource); + } + } + + protected static function recordInstanceLinkPool(IRedisHandler $handler, IConnection $connection): void + { + if (!isset(self::$instanceLinkConnectionMap)) { + self::$instanceLinkConnectionMap = new \WeakMap(); + } + + self::$instanceLinkConnectionMap[$handler] = $connection; + } + + protected static function getConnectionByInstance(IRedisHandler $handler): ?IConnection + { + return self::$instanceLinkConnectionMap[$handler] ?? null; + } + + protected static function unsetConnectionInstance(IRedisHandler $handler): void + { + unset(self::$instanceLinkConnectionMap[$handler]); + } + + /** + * 释放 Redis 连接实例. + */ + public static function release(IRedisHandler $redis): void + { + $connection = self::getConnectionByInstance($redis); + if (null === $connection) { + throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); + } + if ($connection->getStatus() === ConnectionStatus::WaitRelease) { + $connection->getManager()->releaseConnection($connection); + } + self::unsetConnectionInstance($redis); + } + + /** + * 处理连接池 名称. + */ + public static function parsePoolName(?string $poolName = null): string + { + if (null === $poolName || '' === $poolName) + { + $poolName = static::getDefaultPoolName(); + } + + return $poolName; + } + + /** + * 获取默认池子名称. + */ + public static function getDefaultPoolName(): string + { + return Config::get('@currentServer.redis.defaultPool'); + } + + /** + * 从当前上下文中获取公用连接 + */ + public static function isQuickFromRequestContext(): bool + { + return Config::get('@currentServer.redis.quickFromRequestContext', true); + } +} diff --git a/src/Components/redis/src/Traits/TPhpRedisMethod.php b/src/Components/redis/src/Traits/TPhpRedisMethod.php new file mode 100644 index 0000000000..eb45ee0a1a --- /dev/null +++ b/src/Components/redis/src/Traits/TPhpRedisMethod.php @@ -0,0 +1,181 @@ +client; + $client->clearLastError(); + + $result = $client->evalSha($sha1, $args, $numKeys); + $error = $client->getLastError(); + if ($error) + { + if ('NOSCRIPT No matching script. Please use EVAL.' === $error) + { + $client->clearLastError(); + $result = $client->eval($script, $args, $numKeys); + $error = $client->getLastError(); + if ($error) + { + throw new \RedisException($error); + } + } + else + { + throw new \RedisException($error); + } + } + + return $result; + } + + /** + * scan 方法的扩展简易遍历方法. + */ + public function scanEach(?string $pattern = null, int $count = 0): mixed + { + if ($this->isCluster()) + { + foreach ($this->getNodes() as $node) + { + $it = null; + do + { + $keys = $this->client->scan($it, $node, $pattern, $count); + + if ($keys) + { + yield from $keys; + } + } + while ($it > 0); + } + } + else + { + $it = null; + do + { + $keys = $this->client->scan($it, $pattern, $count); + + if ($keys) + { + yield from $keys; + } + } + while ($it > 0); + } + } + + /** + * hscan. + * + * @see \Redis::hscan() + */ + public function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed + { + return $this->client->hscan($key, $iterator, $pattern, $count); + } + + /** + * hscan 方法的扩展简易遍历方法. + */ + public function hscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + { + $it = null; + do + { + $result = $this->client->hscan($key, $it, $pattern, $count); + if ($result) + { + yield from $result; + } + } + while ($it > 0); + } + + /** + * sscan. + */ + public function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed + { + return $this->client->sscan($key, $iterator, $pattern, $count); + } + + /** + * sscan 方法的扩展简易遍历方法. + */ + public function sscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + { + $it = null; + do + { + $result = $this->client->sscan($key, $it, $pattern, $count); + if ($result) + { + yield from $result; + } + } + while ($it > 0); + } + + /** + * zscan. + */ + public function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed + { + return $this->client->zscan($key, $iterator, $pattern, $count); + } + + /** + * zscan 方法的扩展简易遍历方法. + */ + public function zscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + { + $it = null; + do + { + $result = $this->client->zscan($key, $it, $pattern, $count); + if ($result) + { + yield from $result; + } + } + while ($it > 0); + } + + /** + * geoadd. + * + * 当开启序列化后,经纬度会被序列化,并返回错误:ERR value is not a valid float + * + * 如下链接,官方认为这不算 BUG,所以这里做了一个兼容处理 + * + * @see https://github.com/phpredis/phpredis/issues/1549 + * @see \Redis::geoadd + */ + public function geoadd(string $key, float|string $lng, float|string $lat, string $member, mixed ...$other_triples_and_options): mixed + { + $serializer = $this->client->getOption(\Redis::OPT_SERIALIZER); + $this->client->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE); + try + { + return $this->client->geoadd($key, $lng, $lat, $member, ...$other_triples_and_options); + } + finally + { + $this->client->setOption(\Redis::OPT_SERIALIZER, $serializer); + } + } +} diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php new file mode 100644 index 0000000000..21ed10cce3 --- /dev/null +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -0,0 +1,133 @@ +isCluster()) + { + return 0; + } + + $clientId = $this->client->client('id'); + $info = $this->client->client('list'); + + foreach ($info as $item) + { + if ($item['id'] === $clientId) + { + return $item['db'] ?? 0; + } + } + + return 0; + } + + /** + * eval扩展方法,结合了 eval、evalSha. + * + * 优先使用 evalSha 尝试,失败则使用 eval 方法 + */ + public function evalEx(string $script, ?array $args = null, ?int $numKeys = null): mixed + { + $sha1 = sha1($script); + $client = $this->client; + + try { + return $client->evalSha($sha1, $numKeys, ...$args); + } catch (PredisException $exception) { + if ('NOSCRIPT No matching script. Please use EVAL.' === $exception->getMessage()) { + return $client->eval($script, $numKeys, ...$args); + } else { + throw $exception; + } + } + } + + public function scanEach(?string $pattern = null, int $count = 0) + { + if ($this->isCluster()) + { + foreach ($this->getNodes() as $node) + { + $cursor = null; + do + { + $result = $this->scan("{$node[0]}:{$node[1]}", $cursor, ['match' => $pattern, 'count' => $count]); + [$cursor, $keys] = $result; + if ($keys) + { + yield from $keys; + } + } + while ($cursor > 0); + } + } + else + { + $cursor = null; + do + { + $result = $this->client->scan($cursor, ['match' => $pattern, 'count' => $count]); + [$cursor, $keys] = $result; + if ($keys) + { + yield from $keys; + } + } + while ($cursor > 0); + } + } + + public function hscanEach(string $key, ?string $pattern = null, int $count = 0) + { + $cursor = null; + do + { + $result = $this->client->hscan($key, $cursor, ['match' => $pattern, 'count' => $count]); + [$cursor, $keys] = $result; + if ($keys) + { + yield from $keys; + } + } + while ($cursor > 0); + } + + public function sscanEach(string $key, ?string $pattern = null, int $count = 0) + { + $cursor = null; + do + { + $result = $this->client->sscan($key, $cursor, ['match' => $pattern, 'count' => $count]); + [$cursor, $keys] = $result; + if ($keys) + { + yield from $keys; + } + } + while ($cursor > 0); + } + + public function zscanEach(string $key, ?string $pattern = null, int $count = 0) + { + $cursor = null; + do + { + $result = $this->client->zscan($key, $cursor, ['match' => $pattern, 'count' => $count]); + [$cursor, $keys] = $result; + if ($keys) + { + yield from $keys; + } + } + while ($cursor > 0); + } +} diff --git a/src/Components/redis/tests/PHPUnitHook.php b/src/Components/redis/tests/PHPUnitHook.php new file mode 100644 index 0000000000..434f7c9d3d --- /dev/null +++ b/src/Components/redis/tests/PHPUnitHook.php @@ -0,0 +1,37 @@ +stopPropagation(); + }, 1); + try + { + App::run('Imi\Redis\Test', CliApp::class, static function (): void { + }); + } + catch (\Throwable $th) + { + var_dump((string) $th); // 方便错误调试查看 + throw $th; + } + } +} diff --git a/src/Components/redis/tests/Tests/AbstractRedisTestCase.php b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php new file mode 100644 index 0000000000..fe6f5cea10 --- /dev/null +++ b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php @@ -0,0 +1,23 @@ +poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + ]); + $record->age = 11; + $this->assertTrue($record->save()); + } + + public function testFind(): void + { + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $record = $model::find('1-a'); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + } + + public function testSelect(): void + { + $expected = [ + [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ], + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $list = $model::select('1-a', '2-b'); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + $list = $model::select([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + } + + public function testDelete(): void + { + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $record = $model::find('1-a'); + $this->assertNotNull($record); + $this->assertTrue($record->delete()); + $this->assertNull($model::find('1-a')); + } + + public function testSafeDelete(): void + { + // --更新-- + // 原始记录 + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 114514, + 'name' => __METHOD__, + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'id' => 114514, + 'name' => __METHOD__, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + $record2 = $model::find([ + 'id' => 114514, + 'name' => __METHOD__, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $record1->age = 33; + $record1->save(); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + + // 安全删除成功 + $this->assertTrue($record1->safeDelete()); + + // --删除-- + // 原始记录 + $record = $model::newInstance([ + 'id' => 114514, + 'name' => __METHOD__, + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'id' => 114514, + 'name' => __METHOD__, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + $record2 = $model::find([ + 'id' => 114514, + 'name' => __METHOD__, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $record1->delete(); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + } + + public function testDeleteBatch(): void + { + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]); + $this->assertTrue($record->save()); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $this->assertEquals(2, $model::deleteBatch([ + 'id' => 1, + 'name' => 'a', + ], '2-b')); + } + + /** + * @testdox ttl + */ + public function testTTL(): void + { + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $model = TestRedisModel2::fork(null, 'test_phpredis_standalone', $this->formatter); + $record = $model::newInstance($expected); + $this->assertTrue($record->save()); + + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertEquals($expected, $record->toArray()); + + usleep(1500000); + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNull($record); + } + + public function testFormatter(): void + { + $model = TestRedisWithFormatterModel::fork(null, 'test_phpredis_standalone', $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + ]); + $record->age = 11; + $this->assertTrue($record->save()); + + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $record = $model::find('formatter-1-a'); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + + $expected = [ + [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ], + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $list = $model::select('formatter-1-a', 'formatter-2-b'); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + $list = $model::select([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + } + + public function testSerialize(): void + { + $expected = [ + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + /** @var TestRedisModel $record */ + $record = unserialize(serialize($record)); + $this->assertTrue($record->save()); + $list = $model::select('2-b'); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + $list = $model::select([ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + + $record = $model::find([ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertNotNull($record); + $this->assertEquals(22, $record->age); + $record2 = unserialize(serialize($record)); + $this->assertEquals($record->toArray(), $record2->toArray()); + } + + public function testSerializable(): void + { + $data = [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]; + $model = TestRedisModelSerializable::fork(null, 'test_phpredis_standalone', $this->formatter); + $record = $model::newInstance($data); + $record->save(); + + $record2 = $model::find([ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertNotNull($record2); + foreach ($data as $name => $value) + { + $this->assertEquals($value, $record2->{$name}); + } + } + + public function testVirtual(): void + { + $model = TestRedisModelVirtual::fork(null, 'test_phpredis_standalone', $this->formatter); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $record->save(); + + $record2 = $model::find([ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertNotNull($record2); + foreach ([ + 'id' => 2, + 'name' => 'b', + 'age' => 0, + ] as $name => $value) + { + $this->assertEquals($value, $record2->{$name}); + } + } +} diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php new file mode 100644 index 0000000000..e51978b96f --- /dev/null +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php @@ -0,0 +1,224 @@ +poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + ]); + $record->age = 11; + $this->assertTrue($record->save()); + } + + public function testFind(): void + { + $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + } + + public function testSelect(): void + { + $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $expected = [ + [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ], + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $list = $model::select([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + } + + public function testDelete(): void + { + $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertTrue($record->delete()); + $this->assertNull($model::find([ + 'id' => 1, + 'name' => 'a', + ])); + } + + public function testSafeDelete(): void + { + $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + // --更新-- + // 原始记录 + $record = $model::newInstance([ + 'id' => 114514, + 'name' => __METHOD__, + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'name' => __METHOD__, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + $record2 = $model::find([ + 'name' => __METHOD__, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $record1->age = 33; + $record1->save(); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + + // 安全删除成功 + $this->assertTrue($record1->safeDelete()); + + // --删除-- + // 原始记录 + $record = $model::newInstance([ + 'id' => 114514, + 'name' => __METHOD__, + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'name' => __METHOD__, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + $record2 = $model::find([ + 'name' => __METHOD__, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $record1->delete(); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + } + + public function testDeleteBatch(): void + { + $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]); + $this->assertTrue($record->save()); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $this->assertEquals(2, $model::deleteBatch([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ])); + } + + public function testFormatter(): void + { + $model = TestRedisHashWithFormatterModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + ]); + $record->age = 11; + $this->assertTrue($record->save()); + + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + + $expected = [ + [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ], + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $list = $model::select([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + } +} diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php new file mode 100644 index 0000000000..5d0fa9f2d3 --- /dev/null +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php @@ -0,0 +1,206 @@ +poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + ]); + $record->age = 11; + $this->assertTrue($record->save()); + } + + public function testFind(): void + { + $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $expected = [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]; + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertEquals($expected, $record->toArray()); + } + + public function testSelect(): void + { + $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $expected = [ + [ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ], + [ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ], + ]; + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $list = $model::select([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ]); + $this->assertEquals($expected, json_decode(json_encode($list), true)); + } + + public function testDelete(): void + { + $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $record = $model::find([ + 'id' => 1, + 'name' => 'a', + ]); + $this->assertNotNull($record); + $this->assertTrue($record->delete()); + $this->assertNull($model::find([ + 'id' => 1, + 'name' => 'a', + ])); + } + + public function testSafeDelete(): void + { + $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + // --更新-- + // 原始记录 + $record = $model::newInstance([ + 'id' => 114514, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'id' => 114514, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + + $record2 = $model::find([ + 'id' => 114514, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $record1->age = 23; + $this->assertTrue($record1->save()); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + + // 安全删除成功 + $this->assertTrue($record1->safeDelete()); + + // --删除-- + // 原始记录 + $record = $model::newInstance([ + 'id' => 114514, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + + // 查出2个对象实例 + $record1 = $model::find([ + 'id' => 114514, + ]); + $this->assertNotNull($record1); + $this->assertEquals($record->toArray(), $record1->toArray()); + + $record2 = $model::find([ + 'id' => 114514, + ]); + $this->assertNotNull($record2); + $this->assertEquals($record->toArray(), $record2->toArray()); + + // 更新一个 + $this->assertTrue($record1->delete()); + + // 安全删除失败 + $this->assertFalse($record2->safeDelete()); + } + + public function testDeleteBatch(): void + { + $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance([ + 'id' => 1, + 'name' => 'a', + 'age' => 11, + ]); + $this->assertTrue($record->save()); + $record = $model::newInstance([ + 'id' => 2, + 'name' => 'b', + 'age' => 22, + ]); + $this->assertTrue($record->save()); + $this->assertEquals(2, $model::deleteBatch([ + 'id' => 1, + 'name' => 'a', + ], [ + 'id' => 2, + 'name' => 'b', + ])); + } + + public function testColumnType(): void + { + $model = TestRedisHashObjectColumnTypeModel::fork(null, $this->poolName, $this->formatter); + $record = $model::newInstance(); + $record->setJson([ + 'name' => 'imi', + ]); + $record->setJsonArray([ + [ + 'name' => '宇润', + ], + [ + 'name' => 'imi', + ], + ]); + $record->setList([1, 2, 3]); + $record->setSet(['a', 'b', 'c']); + $this->assertTrue($record->save()); + $this->assertEquals([ + 'name' => 'imi', + ], $record->getJson()); + $this->assertEquals('宇润', $record->getJsonArray()[0]['name']); + $this->assertEquals('imi', $record->getJsonArray()[1]['name']); + $this->assertEquals([1, 2, 3], $record->getList()); + $this->assertEquals(['a', 'b', 'c'], $record->getSet()); + + $record2 = $model::find(); + $this->assertEquals($record->toArray(), $record2->toArray()); + } +} diff --git a/src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelHashObjectTest.php b/src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelHashObjectTest.php new file mode 100644 index 0000000000..345d907e0c --- /dev/null +++ b/src/Components/redis/tests/Tests/Model/PhpRedis/PhpRedisModelHashObjectTest.php @@ -0,0 +1,14 @@ + + */ +#[TestDox('Redis/PhpRedis/Cluster')] +class PhpRedisClusterTest extends PhpRedisTest +{ + public string $driveName = 'test_phpredis_cluster'; + + public function testGetDrive(): IRedisHandler + { + $redisClient = RedisManager::getInstance($this->driveName); + self::assertInstanceOf(PhpRedisClusterHandler::class, $redisClient); + self::assertInstanceOf(\RedisCluster::class, $redisClient->getInstance()); + + $this->flush($redisClient); + + return $redisClient; + } + + protected function flush(IRedisHandler $redis): void + { + // 清空数据 + foreach ($redis->getNodes() as $node) { + self::assertTrue($redis->flushdb($node, false)); + } + } +} diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php new file mode 100644 index 0000000000..20f7e2fe1f --- /dev/null +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -0,0 +1,186 @@ +driveName); + self::assertInstanceOf(PhpRedisHandler::class, $redisClient); + self::assertInstanceOf(\Redis::class, $redisClient->getInstance()); + + // 清空数据 + $this->flush($redisClient); + + return $redisClient; + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + protected function flush(IRedisHandler $redis): void + { + $redis->flushdb(false); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testGetAndSet(IRedisHandler $redis): void + { + $str = 'imi niubi!' . bin2hex(random_bytes(4)); + $redis->set('imi:test:a', $str); + self::assertEquals($str, $redis->get('imi:test:a')); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testEvalEx(IRedisHandler $redis): void + { + $value = $redis->evalEx(<<<'SCRIPT' + local key = KEYS[1] + local value = ARGV[1] + redis.call('set', key, value) + return redis.call('get', key) + SCRIPT + , ['imi:test:a', 'imi very 6'], 1); + self::assertEquals('imi very 6', $value); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testScanEach(IRedisHandler $redis): void + { + $excepted = $map = []; + for ($i = 0; $i < 100; ++$i) + { + $key = 'imi:scanEach:' . $i; + $excepted[$key] = 1; + $map[$key] = 0; + $redis->set($key, $i); + } + foreach ($redis->scanEach('imi:scanEach:*', 10) as $value) + { + $map[$value] = 1; + } + self::assertEquals($excepted, $map); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testHscanEach(IRedisHandler $redis): void + { + $excepted = $map = $values = $exceptedValues = []; + $key = 'imi:hscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $member = 'value:' . $i; + $excepted[$member] = 1; + $map[$member] = 0; + $values[$member] = -1; + $exceptedValues[$member] = $i; + $redis->hSet($key, $member, $i); + } + foreach ($redis->hscanEach($key, 'value:*', 10) as $k => $value) + { + $map[$k] = 1; + $values[$k] = $value; + } + self::assertEquals($excepted, $map); + self::assertEquals($exceptedValues, $values); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testSscanEach(IRedisHandler $redis): void + { + $excepted = $map = []; + $key = 'imi:sscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $value = 'value:' . $i; + $excepted[$value] = 1; + $map[$value] = 0; + $redis->sAdd($key, $value); + } + foreach ($redis->sscanEach($key, '*', 10) as $value) + { + $map[$value] = 1; + } + self::assertEquals($excepted, $map); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testZscanEach(IRedisHandler $redis): void + { + $excepted = $map = []; + $key = 'imi:zscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $value = 'value:' . $i; + $excepted[$i] = 1; + $map[$i] = 0; + $redis->zAdd($key, $i, $value); + } + foreach ($redis->zscanEach($key, '*', 10) as $score) + { + $map[$score] = 1; + } + self::assertEquals($excepted, $map); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testGeoAdd(IRedisHandler $redis): void + { + if (\PHP_OS_FAMILY === 'Windows') + { + self::markTestSkipped('Windows redis not support geo.'); + } + $oriOption = $redis->getOption(\Redis::OPT_SERIALIZER); + + self::assertTrue($redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP)); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + + self::assertTrue($redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE)); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + + $redis->setOption(\Redis::OPT_SERIALIZER, $oriOption); + } +} diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php new file mode 100644 index 0000000000..dfe0b5f384 --- /dev/null +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -0,0 +1,52 @@ + + */ +#[TestDox('Redis/Predis/Cluster')] +class PredisClusterTest extends PhpRedisTest +{ + public string $driveName = 'test_predis_cluster'; + + public function testGetDrive(): IRedisHandler + { + $redisClient = RedisManager::getInstance($this->driveName); + self::assertInstanceOf(PredisClusterHandler::class, $redisClient); + self::assertInstanceOf(Client::class, $redisClient->getInstance()); + + $this->flush($redisClient); + + return $redisClient; + } + + protected function flush(IRedisHandler $redis): void + { + // 清空数据 + foreach ($redis->getNodes() as $node) { + $client = $redis->getClientBy('id', "{$node[0]}:{$node[1]}"); + self::assertTrue($client->flushdb()); + } + } + + #[Depends('testGetDrive')] + public function testGeoAdd(IRedisHandler $redis): void + { + if (\PHP_OS_FAMILY === 'Windows') + { + self::markTestSkipped('Windows redis not support geo.'); + } + + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + } +} diff --git a/src/Components/redis/tests/Tests/PredisTest.php b/src/Components/redis/tests/Tests/PredisTest.php new file mode 100644 index 0000000000..8f7127aa55 --- /dev/null +++ b/src/Components/redis/tests/Tests/PredisTest.php @@ -0,0 +1,41 @@ + + */ +#[TestDox('Redis/Predis/Standalone')] +class PredisTest extends PhpRedisTest +{ + public string $driveName = 'test_predis_standalone'; + + public function testGetDrive(): IRedisHandler + { + $redisClient = RedisManager::getInstance($this->driveName); + self::assertInstanceOf(PredisHandler::class, $redisClient); + self::assertInstanceOf(Client::class, $redisClient->getInstance()); + + return $redisClient; + } + + #[Depends('testGetDrive')] + public function testGeoAdd(IRedisHandler $redis): void + { + if (\PHP_OS_FAMILY === 'Windows') + { + self::markTestSkipped('Windows redis not support geo.'); + } + + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + } +} diff --git a/tests/unit/Component/Tests/RedisManagerTest.php b/src/Components/redis/tests/Tests/RedisManagerTest.php similarity index 75% rename from tests/unit/Component/Tests/RedisManagerTest.php rename to src/Components/redis/tests/Tests/RedisManagerTest.php index a7f5261325..31842e667c 100644 --- a/tests/unit/Component/Tests/RedisManagerTest.php +++ b/src/Components/redis/tests/Tests/RedisManagerTest.php @@ -2,21 +2,27 @@ declare(strict_types=1); -namespace Imi\Test\Component\Tests; +namespace Imi\Redis\Test\Tests; use Imi\Pool\PoolManager; -use Imi\Redis\RedisHandler; +use Imi\Redis\Handler\IRedisHandler; use Imi\Redis\RedisManager; use Imi\Test\BaseTest; use PHPUnit\Framework\Assert; /** * @testdox RedisManager + * @deprecated */ class RedisManagerTest extends BaseTest { public const CONNECTION_NAME = 'tradition'; + protected function setUp(): void + { + $this->markTestSkipped('Deprecated Test'); + } + public function testDefaultPoolName(): void { Assert::assertEquals('redis_test', RedisManager::getDefaultPoolName()); @@ -27,8 +33,9 @@ public function testGetInstance(): void $a = RedisManager::getInstance(self::CONNECTION_NAME); $b = RedisManager::getInstance(self::CONNECTION_NAME); $this->assertEquals(spl_object_id($a), spl_object_id($b)); - $this->assertTrue($a->set('test', 'imi')); - $this->assertEquals('imi', $a->get('test')); + $value = 'imi' . bin2hex(random_bytes(4)); + $a->set('test', $value); + $this->assertEquals($value, $a->get('test')); } public function testGetNewInstance(): void @@ -36,8 +43,9 @@ public function testGetNewInstance(): void $a = RedisManager::getInstance(self::CONNECTION_NAME); $b = RedisManager::getNewInstance(self::CONNECTION_NAME); $this->assertNotEquals(spl_object_id($a), spl_object_id($b)); - $this->assertTrue($b->set('test', 'imi')); - $this->assertEquals('imi', $b->get('test')); + $value = 'imi' . bin2hex(random_bytes(4)); + $b->set('test', $value); + $this->assertEquals($value, $b->get('test')); } public function testNewInstance(): void @@ -85,11 +93,11 @@ public function testInstance(): void Assert::assertEquals(0, $pool->getFree()); } - private function assertRedisHandler(RedisHandler $redisHandler): void + private function assertRedisHandler(IRedisHandler $redisHandler): void { - Assert::assertInstanceOf(RedisHandler::class, $redisHandler); - $time = time(); - $redisHandler->set('imi:test:a', $time); - Assert::assertEquals($time, $redisHandler->get('imi:test:a')); + Assert::assertInstanceOf(IRedisHandler::class, $redisHandler); + $str = \bin2hex(random_bytes(8)); + $redisHandler->set('imi:test:a', $str); + Assert::assertEquals($str, $redisHandler->get('imi:test:a')); } } diff --git a/tests/unit/Component/Tests/RedisTest.php b/src/Components/redis/tests/Tests/RedisTest.php similarity index 92% rename from tests/unit/Component/Tests/RedisTest.php rename to src/Components/redis/tests/Tests/RedisTest.php index 67813db23c..091b6088c8 100644 --- a/tests/unit/Component/Tests/RedisTest.php +++ b/src/Components/redis/tests/Tests/RedisTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Imi\Test\Component\Tests; +namespace Imi\Redis\Test\Tests; use Imi\App; use Imi\Pool\Interfaces\IPoolResource; @@ -14,9 +14,15 @@ /** * @testdox Redis + * @deprecated */ class RedisTest extends BaseTest { + protected function setUp(): void + { + $this->markTestSkipped('Deprecated Test'); + } + public function testInject(): void { /** @var \Imi\Test\Component\Redis\Classes\TestInjectRedis $test */ @@ -24,14 +30,11 @@ public function testInject(): void $test->test(); } - public function testSet(): void - { - Assert::assertTrue(Redis::set('imi:test:a', 'imi niubi!')); - } - - public function testGet(): void + public function testGetAndSet(): void { - Assert::assertEquals('imi niubi!', Redis::get('imi:test:a')); + $str = 'imi niubi!' . bin2hex(random_bytes(4)); + Redis::set('imi:test:a', $str); + Assert::assertEquals($str, Redis::get('imi:test:a')); } public function testEvalEx(): void diff --git a/src/Components/redis/tests/bootstrap.php b/src/Components/redis/tests/bootstrap.php new file mode 100644 index 0000000000..b49daece6d --- /dev/null +++ b/src/Components/redis/tests/bootstrap.php @@ -0,0 +1,5 @@ + [ + 'model' => 'Imi\Redis', + ], + + // 日志配置 + 'logger' => [ + 'channels' => [ + 'imi' => [ + 'handlers' => [ + [ + 'class' => \Imi\Log\Handler\ConsoleHandler::class, + 'formatter' => [ + 'class' => \Imi\Log\Formatter\ConsoleLineFormatter::class, + 'construct' => [ + 'format' => null, + 'dateFormat' => 'Y-m-d H:i:s', + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], + [ + 'class' => \Monolog\Handler\RotatingFileHandler::class, + 'construct' => [ + 'filename' => \dirname(__DIR__) . '/logs/log.log', + ], + 'formatter' => [ + 'class' => \Monolog\Formatter\LineFormatter::class, + 'construct' => [ + 'dateFormat' => 'Y-m-d H:i:s', + 'allowInlineLineBreaks' => true, + 'ignoreEmptyContextAndExtra' => true, + ], + ], + ], + ], + ], + ], + ], + + 'beans' => [ + 'ErrorLog' => [ + 'catchLevel' => \E_ALL, + 'exceptionLevel' => \E_ALL, + 'errorEventHandlers' => [ + \Imi\Test\Component\ErrorEventHandler::class, + ], + ], + ], + + 'connectionCenter' => [ + 'test_phpredis_standalone' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + 'test_phpredis_cluster' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'password' => env('REDIS_SERVER_CLUSTER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, + + 'seeds' => [ + '192.168.32.2:6379', + '192.168.32.3:6379', + '192.168.32.4:6379', + '192.168.32.5:6379', + '192.168.32.6:6379', + '192.168.32.7:6379', + ], + ], + ], + ], + ], + 'test_predis_standalone' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'predis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + 'test_predis_cluster' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'password' => env('REDIS_SERVER_CLUSTER_PASSWORD'), + + 'client' => 'predis', + 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, + + 'seeds' => [ + '192.168.32.2:6379', + '192.168.32.3:6379', + '192.168.32.4:6379', + '192.168.32.5:6379', + '192.168.32.6:6379', + '192.168.32.7:6379', + ], + ], + ], + ], + ], + ], + + // redis 配置 + 'redis' => [ + // 默认连接池名 + 'defaultPool' => 'test_phpredis_standalone', + 'quickFromRequestContext' => true, + ], + // 缓存配置 + 'cache' => [ + 'default' => 'redis', + ], + // 缓存 + 'caches' => [ + 'redis' => [ + 'handlerClass' => \Imi\Cache\Handler\Redis::class, + 'option' => [ + 'poolName' => 'test_phpredis_standalone', + 'formatHandlerClass' => \Imi\Util\Format\Json::class, + ], + ], + 'redisHash' => [ + 'handlerClass' => \Imi\Cache\Handler\RedisHash::class, + 'option' => [ + 'poolName' => 'test_phpredis_standalone', + 'separator' => '->', + 'formatHandlerClass' => \Imi\Util\Format\Json::class, + ], + ], + ], +]; diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml new file mode 100644 index 0000000000..f6ac1eca48 --- /dev/null +++ b/src/Components/redis/tests/phpunit.xml @@ -0,0 +1,24 @@ + + + + + ./ + + + + + + + + ../src + + + + + + + + \ No newline at end of file diff --git a/src/Components/swoole/src/Redis/Pool/CoroutineRedisPool.php b/src/Components/swoole/src/Redis/Pool/CoroutineRedisPool.php deleted file mode 100644 index c6264b594b..0000000000 --- a/src/Components/swoole/src/Redis/Pool/CoroutineRedisPool.php +++ /dev/null @@ -1,26 +0,0 @@ -initUriResourceConfig(); - } -} diff --git a/src/Redis/Enum/RedisMode.php b/src/Redis/Enum/RedisMode.php deleted file mode 100644 index 40d8e11e14..0000000000 --- a/src/Redis/Enum/RedisMode.php +++ /dev/null @@ -1,25 +0,0 @@ -isCluster() && $redis->isConnected()) - { - $this->host = $redis->getHost(); - $this->port = $redis->getPort(); - $this->timeout = $redis->getTimeout(); - $this->auth = $redis->getAuth(); - } - } - - public function __call(string $name, array $arguments): mixed - { - $redis = $this->redis; - $result = $redis->{$name}(...$arguments); - if (!$this->isCluster()) - { - switch ($name) - { - case 'connect': - case 'open': - if ($redis->isConnected()) - { - $this->host = $redis->getHost(); - $this->isUnix = str_contains($this->host, '/'); - $this->port = $redis->getPort(); - $this->timeout = $redis->getTimeout(); - } - // no break - case 'auth': - $this->auth = $redis->getAuth(); - break; - } - } - - return $result; - } - - /** - * 获取 Redis 对象实例. - * - * @return \Redis|\RedisCluster - */ - public function getInstance(): mixed - { - return $this->redis; - } - - /** - * 重新连接. - */ - public function reconnect(): bool - { - $redis = $this->redis; - $redis->close(); - if (!$this->isCluster()) - { - if ($this->isUnix) - { - $result = $redis->connect($this->host); - } - else - { - $result = $redis->connect($this->host, $this->port, $this->timeout); - } - if ($result) - { - $auth = $this->auth; - if (null !== $auth && !$redis->auth($auth)) - { - throw new \RedisException($redis->getLastError()); - } - } - else - { - throw new \RedisException($redis->getLastError()); - } - } - - return true; - } - - /** - * eval扩展方法,结合了 eval、evalSha. - * - * 优先使用 evalSha 尝试,失败则使用 eval 方法 - */ - public function evalEx(string $script, ?array $args = null, ?int $numKeys = null): mixed - { - $sha1 = sha1($script); - $this->clearLastError(); - // @phpstan-ignore-next-line - $result = $this->evalSha($sha1, $args, $numKeys); - $error = $this->getLastError(); - if ($error) - { - if ('NOSCRIPT No matching script. Please use EVAL.' === $error) - { - $this->clearLastError(); - $result = $this->eval($script, $args, $numKeys); - $error = $this->getLastError(); - if ($error) - { - throw new \RedisException($error); - } - } - else - { - throw new \RedisException($error); - } - } - - return $result; - } - - /** - * scan. - */ - public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, mixed $strNode = null): mixed - { - if (null === $strNode) - { - return $this->redis->scan($iterator, $pattern, $count); - } - else - { - // @phpstan-ignore-next-line - return $this->redis->scan($iterator, $strNode, $pattern, $count); - } - } - - /** - * scan 方法的扩展简易遍历方法. - */ - public function scanEach(?string $pattern = null, int $count = 0): mixed - { - $redis = $this->redis; - if ($this->isCluster()) - { - // @phpstan-ignore-next-line - foreach ($redis->_masters() as $master) - { - $it = null; - // @phpstan-ignore-next-line - while (false !== ($keys = $redis->scan($it, $master, $pattern, $count))) - { - if ($keys) - { - foreach ($keys as $key) - { - yield $key; - } - } - } - } - } - else - { - $it = null; - while (false !== ($keys = $redis->scan($it, $pattern, $count))) - { - if ($keys) - { - foreach ($keys as $key) - { - yield $key; - } - } - } - } - } - - /** - * hscan. - */ - public function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed - { - return $this->redis->hscan($key, $iterator, $pattern, $count); - } - - /** - * hscan 方法的扩展简易遍历方法. - */ - public function hscanEach(string $key, ?string $pattern = null, int $count = 0): mixed - { - $it = null; - while (false !== ($result = $this->hscan($key, $it, $pattern, $count))) - { - if ($result) - { - foreach ($result as $key => $value) - { - yield $key => $value; - } - } - } - } - - /** - * sscan. - */ - public function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed - { - return $this->redis->sscan($key, $iterator, $pattern, $count); - } - - /** - * sscan 方法的扩展简易遍历方法. - */ - public function sscanEach(string $key, ?string $pattern = null, int $count = 0): mixed - { - $it = null; - while (false !== ($result = $this->sscan($key, $it, $pattern, $count))) - { - if ($result) - { - foreach ($result as $value) - { - yield $value; - } - } - } - } - - /** - * zscan. - */ - public function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed - { - return $this->redis->zscan($key, $iterator, $pattern, $count); - } - - /** - * zscan 方法的扩展简易遍历方法. - */ - public function zscanEach(string $key, ?string $pattern = null, int $count = 0): mixed - { - $it = null; - while (false !== ($result = $this->zscan($key, $it, $pattern, $count))) - { - if ($result) - { - foreach ($result as $value) - { - yield $value; - } - } - } - } - - /** - * geoadd. - * - * 当开启序列化后,经纬度会被序列化,并返回错误:ERR value is not a valid float - * - * 如下链接,官方认为这不算 BUG,所以这里做了一个兼容处理 - * - * @see https://github.com/phpredis/phpredis/issues/1549 - */ - public function geoadd(string $key, float|string $lng, float|string $lat, string $member, mixed ...$other_triples_and_options): mixed - { - $redis = $this->redis; - $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); - $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE); - try - { - return $redis->geoadd($key, $lng, $lat, $member, ...$other_triples_and_options); - } - finally - { - $redis->setOption(\Redis::OPT_SERIALIZER, $serializer); - } - } - - /** - * 是否为集群. - */ - public function isCluster(): bool - { - return $this->redis instanceof \RedisCluster; - } -} diff --git a/src/Redis/RedisManager.php b/src/Redis/RedisManager.php deleted file mode 100644 index c6f4e959dc..0000000000 --- a/src/Redis/RedisManager.php +++ /dev/null @@ -1,210 +0,0 @@ -getInstance(); - } - else - { - $config = Config::get('@app.redis.connections.' . $poolName); - if (null === $config) - { - throw new \RuntimeException(sprintf('Not found redis config %s', $poolName)); - } - - $class = $config['handlerClass'] ?? \Redis::class; - /** @var RedisHandler $redis */ - $redis = BeanFactory::newInstance(RedisHandler::class, new $class()); - self::initRedisConnection($redis, $config); - - return $redis; - } - } - - /** - * 获取 Redis 连接实例,每个RequestContext中共用一个. - * - * @param string|null $poolName 连接池名称 - */ - public static function getInstance(?string $poolName = null): ?RedisHandler - { - $poolName = static::parsePoolName($poolName); - if (PoolManager::exists($poolName)) - { - return PoolManager::getRequestContextResource($poolName)->getInstance(); - } - else - { - if (null === self::$connections) - { - self::$connections = Config::get('@app.redis.connections'); - } - $config = self::$connections[$poolName] ?? null; - if (null === $config) - { - throw new \RuntimeException(sprintf('Not found redis config %s', $poolName)); - } - $requestContextKey = '__redis.' . $poolName; - $requestContext = RequestContext::getContext(); - if (isset($requestContext[$requestContextKey])) - { - $redis = $requestContext[$requestContextKey]; - } - else - { - /** @var RedisHandler|null $redis */ - $redis = App::get($requestContextKey); - } - if (null === $redis) - { - $class = $config['handlerClass'] ?? \Redis::class; - /** @var RedisHandler $redis */ - $redis = BeanFactory::newInstance(RedisHandler::class, new $class()); - self::initRedisConnection($redis, $config); - App::set($requestContextKey, $redis); - if (($heartbeatInterval = $config['heartbeatInterval'] ?? 0) > 0) - { - Timer::tick((int) ($heartbeatInterval * 1000), static function () use ($requestContextKey): void { - /** @var RedisHandler|null $redis */ - $redis = App::get($requestContextKey); - if (!$redis) - { - return; - } - self::heartbeat($redis); - }); - } - } - elseif ($config['checkStateWhenGetResource'] ?? true) - { - self::heartbeat($redis); - } - - return $requestContext[$requestContextKey] = $redis; - } - } - - /** - * 心跳. - */ - public static function heartbeat(RedisHandler $redis): void - { - try - { - $result = $redis->ping(); - // PHPRedis 扩展,5.0.0 版本开始,ping() 返回为 true,旧版本为 +PONG - if (true !== $result && '+PONG' !== $result) - { - $redis->reconnect(); - } - } - catch (\Throwable) - { - $redis->reconnect(); - } - } - - /** - * 释放 Redis 连接实例. - */ - public static function release(RedisHandler $redis): void - { - $resource = RequestContext::get('poolResources')[spl_object_id($redis)] ?? null; - if (null !== $resource) - { - PoolManager::releaseResource($resource); - } - } - - /** - * 处理连接池 名称. - */ - public static function parsePoolName(?string $poolName = null): string - { - if (null === $poolName || '' === $poolName) - { - $poolName = static::getDefaultPoolName(); - } - - return $poolName; - } - - /** - * 获取默认池子名称. - */ - public static function getDefaultPoolName(): string - { - return Config::get('@currentServer.redis.defaultPool'); - } - - /** - * 初始化 Redis 连接. - */ - public static function initRedisConnection(RedisHandler $redis, array $config): void - { - if (!$redis->isCluster()) - { - $host = $config['host'] ?? '127.0.0.1'; - if (str_contains((string) $host, '/')) - { - // unix socket - $redis->connect($host); - } - else - { - $redis->connect($host, (int) ($config['port'] ?? 6379), (float) ($config['timeout'] ?? 0)); - } - if (('' !== ($config['password'] ?? '')) && !$redis->auth($config['password'])) - { - throw new \RedisException($redis->getLastError()); - } - if (isset($config['db']) && !$redis->select((int) $config['db'])) - { - throw new \RedisException($redis->getLastError()); - } - } - $options = $config['options'] ?? []; - if (($config['serialize'] ?? true) && !isset($options[\Redis::OPT_SERIALIZER])) - { - $options[\Redis::OPT_SERIALIZER] = \Redis::SERIALIZER_PHP; - } - if ($options) - { - foreach ($options as $key => $value) - { - if (!$redis->setOption($key, $value)) - { - throw new \RuntimeException(sprintf('Redis setOption %s=%s failed', $key, $value)); - } - } - } - } -} diff --git a/src/Redis/RedisResource.php b/src/Redis/RedisResource.php index 4d342af04e..375d4c1315 100644 --- a/src/Redis/RedisResource.php +++ b/src/Redis/RedisResource.php @@ -4,9 +4,16 @@ namespace Imi\Redis; -use Imi\Log\Log; use Imi\Pool\BasePoolResource; - +use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisClusterHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; + +/** + * @deprecated + */ class RedisResource extends BasePoolResource { /** @@ -14,12 +21,16 @@ class RedisResource extends BasePoolResource */ private array $config = []; - public function __construct(\Imi\Pool\Interfaces\IPool $pool, + public function __construct( + \Imi\Pool\Interfaces\IPool $pool, /** * Redis 对象 + * + * @var IRedisHandler|PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler|null */ - private ?RedisHandler $redis, array $config) - { + private ?IRedisHandler $redis, + array $config + ) { parent::__construct($pool); if (isset($config['timeout'])) @@ -66,14 +77,9 @@ public function reset(): void { $config = $this->config; $redis = $this->redis; - if (!$redis->isCluster() && $redis->isConnected() && ($db = $config['db'] ?? 0) !== $redis->getDBNum() && !$redis->select($db)) - { - throw new \RedisException($redis->getLastError()); - } - $optScan = $config['options'][\Redis::OPT_SCAN] ?? \Redis::SCAN_RETRY; - if (!$redis->setOption(\Redis::OPT_SCAN, $optScan)) + if (!$redis->isCluster() && $redis->isConnected() && ($db = $config['db'] ?? 0) !== $redis->getDBNum()) { - throw new \RuntimeException(sprintf('Redis setOption %s=%s failed', \Redis::OPT_SCAN, $optScan)); + $redis->select($db); } } @@ -82,27 +88,7 @@ public function reset(): void */ public function checkState(): bool { - $redis = $this->redis; - if ($redis->isCluster()) - { - return true; - } - else - { - try - { - $result = $redis->ping(); - - // PHPRedis 扩展,5.0.0 版本开始,ping() 返回为 true,旧版本为 +PONG - return true === $result || '+PONG' === $result; - } - catch (\Throwable $th) - { - Log::error($th); - - return false; - } - } + return $this->redis->isConnected(); } /** @@ -112,6 +98,6 @@ public function isOpened(): bool { $redis = $this->redis; - return $redis->isCluster() || $redis->isConnected(); + return $redis->isConnected(); } } diff --git a/src/Redis/SyncRedisPool.php b/src/Redis/SyncRedisPool.php index ebe7399ec0..07a64e9717 100644 --- a/src/Redis/SyncRedisPool.php +++ b/src/Redis/SyncRedisPool.php @@ -8,6 +8,9 @@ use Imi\Pool\TUriResourceConfig; use Imi\Redis\Traits\TRedisPool; +/** + * @deprecated + */ class SyncRedisPool extends BaseSyncPool { use TRedisPool; diff --git a/src/Redis/Traits/TRedisPool.php b/src/Redis/Traits/TRedisPool.php index 8bb886ec73..f43134645c 100644 --- a/src/Redis/Traits/TRedisPool.php +++ b/src/Redis/Traits/TRedisPool.php @@ -4,11 +4,13 @@ namespace Imi\Redis\Traits; -use Imi\Bean\BeanFactory; use Imi\Redis\Enum\RedisMode; -use Imi\Redis\RedisHandler; +use Imi\Redis\RedisManager; use Imi\Redis\RedisResource; +/** + * @deprecated + */ trait TRedisPool { /** @@ -19,50 +21,9 @@ trait TRedisPool public function createNewResource(): \Imi\Pool\Interfaces\IPoolResource { $config = $this->getNextResourceConfig(); - $mode = $config['mode'] ?? RedisMode::STANDALONE; - $class = $config['handlerClass'] ?? \Redis::class; - switch ($mode) - { - case RedisMode::STANDALONE: - $redis = new $class(); - break; - case RedisMode::SENTINEL: - $master = $config['master'] ?? ''; - $nodes = $config['nodes'] ?? []; - shuffle($nodes); - foreach ($nodes as $node) - { - if (\is_array($node)) - { - $host = $node['host'] ?? '127.0.0.1'; - $port = $node['port'] ?? 6379; - } - else - { - [$host, $port] = explode(':', (string) $node); - } - $redisSentinel = new \RedisSentinel($host, $port, (float) ($config['timeout'] ?? 0), $config['persistent'] ?? false, (int) ($config['retryInterval'] ?? 0), (float) ($config['readTimeout'] ?? 0)); - $masterArray = $redisSentinel->master($master); - if (\is_array($masterArray) && isset($masterArray['ip'], $masterArray['port'])) - { - $config['host'] = $masterArray['ip']; - $config['port'] = $masterArray['port']; - $redis = new $class(); - break; - } - } - if (!isset($redis)) - { - throw new \RedisException('None of redis slave nodes are alive'); - } - break; - case RedisMode::CLUSTER: - $redis = new \RedisCluster($config['name'] ?? null, $config['seeds'] ?? [], $config['timeout'] ?? 0, $config['readTimeout'] ?? 0, $config['persistent'] ?? false, $config['password'] ?? null); - break; - default: - throw new \InvalidArgumentException(sprintf('Invalid mode %s', $mode)); - } - return new RedisResource($this, BeanFactory::newInstance(RedisHandler::class, $redis), $config); + $redis = RedisManager::resolveRedisConnection($config); + + return new RedisResource($this, $redis, $config); } } From dadee4b0058c8ec659669e0466e80e50726f6820 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 11:44:54 +0800 Subject: [PATCH 02/97] =?UTF-8?q?Update:=20=E6=9B=B4=E6=96=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/amqp/example/config/config.php | 45 +-- src/Components/grpc/example/config/config.php | 38 +- .../kafka/example/config/config.php | 45 +-- src/Components/mqtt/example/config/config.php | 32 +- .../queue/example/config/config.php | 70 ++-- .../snowflake/tests/config/config.php | 34 +- .../example/TCPServer/config/config.php | 48 ++- .../example/WebSocketServer/config/config.php | 46 ++- .../unit/Component/Tests/RedisManagerTest.php | 5 + .../tests/unit/Component/config/config.php | 77 ++-- .../tests/unit/HttpServer/config/config.php | 32 +- .../unit/RedisSessionServer/config/config.php | 61 ++-- .../tests/unit/TCPServer/config/config.php | 31 +- .../tests/unit/UDPServer/config/config.php | 31 +- .../unit/WebSocketServer/config/config.php | 31 +- .../config/config.php | 37 +- .../config/config.php | 37 +- .../config/config.php | 36 +- src/Redis/Traits/TRedisPool.php | 1 - tests/unit/Component/ErrorEventHandler.php | 34 ++ .../Tests/RedisModelHashObjectTest.php | 199 ----------- .../Component/Tests/RedisModelHashTest.php | 217 ------------ tests/unit/Component/Tests/RedisModelTest.php | 332 ------------------ tests/unit/Component/config/config.php | 85 ++--- 24 files changed, 473 insertions(+), 1131 deletions(-) create mode 100644 tests/unit/Component/ErrorEventHandler.php delete mode 100644 tests/unit/Component/Tests/RedisModelHashObjectTest.php delete mode 100644 tests/unit/Component/Tests/RedisModelHashTest.php delete mode 100644 tests/unit/Component/Tests/RedisModelTest.php diff --git a/src/Components/amqp/example/config/config.php b/src/Components/amqp/example/config/config.php index 46c6ae7352..a6159cf265 100644 --- a/src/Components/amqp/example/config/config.php +++ b/src/Components/amqp/example/config/config.php @@ -68,20 +68,6 @@ // 连接池配置 'pools' => Imi::checkAppType('swoole') ? [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], - ], 'rabbit' => [ 'pool' => [ 'class' => \Imi\AMQP\Pool\AMQPCoroutinePool::class, @@ -100,17 +86,34 @@ ], ] : [], + // 连接中心配置 + 'connectionCenter' => Imi::checkAppType('swoole') ? [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ] : [], + // redis 配置 'redis' => [ // 数默认连接池名 'defaultPool' => 'redis', - 'connections' => [ - 'redis' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], - ], ], 'amqp' => [ 'connections' => [ diff --git a/src/Components/grpc/example/config/config.php b/src/Components/grpc/example/config/config.php index 68fae73ae9..1f958a0a61 100644 --- a/src/Components/grpc/example/config/config.php +++ b/src/Components/grpc/example/config/config.php @@ -52,20 +52,6 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], - ], 'grpc' => [ 'pool' => [ 'class' => \Imi\Rpc\Client\Pool\RpcClientCoroutinePool::class, @@ -82,6 +68,30 @@ ], ], + // 连接中心配置 + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // 数据库配置 'db' => [ // 数默认连接池名 diff --git a/src/Components/kafka/example/config/config.php b/src/Components/kafka/example/config/config.php index ee22407db4..baaa5111d6 100644 --- a/src/Components/kafka/example/config/config.php +++ b/src/Components/kafka/example/config/config.php @@ -66,20 +66,6 @@ // 连接池配置 'pools' => Imi::checkAppType('swoole') ? [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], - ], 'kafka' => [ 'pool' => [ 'class' => \Imi\Kafka\Pool\KafkaCoroutinePool::class, @@ -95,17 +81,34 @@ ], ] : [], + // 连接中心配置 + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // redis 配置 'redis' => [ // 数默认连接池名 'defaultPool' => 'redis', - 'connections' => [ - 'redis' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], - ], ], 'kafka' => [ 'connections' => [ diff --git a/src/Components/mqtt/example/config/config.php b/src/Components/mqtt/example/config/config.php index 13738a1946..1c5f7f4c9c 100644 --- a/src/Components/mqtt/example/config/config.php +++ b/src/Components/mqtt/example/config/config.php @@ -54,18 +54,28 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], + ], + + // 连接中心配置 + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/queue/example/config/config.php b/src/Components/queue/example/config/config.php index d1476723e6..480d1476c7 100644 --- a/src/Components/queue/example/config/config.php +++ b/src/Components/queue/example/config/config.php @@ -56,44 +56,30 @@ ], // 连接池配置 - 'pools' => Imi::checkAppType('swoole') ? [ - 'redis' => [ - 'pool' => [ - // 协程池类名 - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - // 池子中最多资源数 - 'maxResources' => 10, - // 池子中最少资源数 - 'minResources' => 0, - // 资源回收时间间隔,单位:秒 - // 'gcInterval' => 60, - // 获取资源最大存活时间,单位:秒 - // 'maxActiveTime' => 3600, - // 等待资源最大超时时间,单位:毫秒 - // 'waitTimeout' => 3000, - // 心跳时间间隔,单位:秒 - // 'heartbeatInterval' => null, - // 当获取资源时,是否检查状态 - // 'checkStateWhenGetResource' => true, - // 负载均衡-轮询 - // 'resourceConfigMode' => ResourceConfigMode::ROUND_ROBIN, - // 负载均衡-随机 - // 'resourceConfigMode' => ResourceConfigMode::RANDOM, - ], + 'pools' => [], + + // 连接中心配置 + 'connectionCenter' => Imi::checkAppType('swoole') ? [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - // 数组资源配置 - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - // 是否自动序列化变量 - 'serialize' => false, - // 密码 - 'password' => null, - // 第几个库 - 'db' => 0, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + 'database' => 0, + ], + ], ], - // uri资源配置,以分号;分隔多个,参数使用query参数格式,特殊字符需要转码 ], ] : [], @@ -107,18 +93,6 @@ 'redis' => [ // 数默认连接池名 'defaultPool' => 'redis', - 'connections' => [ - 'redis' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - // 是否自动序列化变量 - 'serialize' => false, - // 密码 - 'password' => null, - // 第几个库 - 'db' => 0, - ], - ], ], // 锁 diff --git a/src/Components/snowflake/tests/config/config.php b/src/Components/snowflake/tests/config/config.php index 9358e09687..5a6ce7c145 100644 --- a/src/Components/snowflake/tests/config/config.php +++ b/src/Components/snowflake/tests/config/config.php @@ -31,24 +31,30 @@ ], ], ], - ], - // 连接池配置 - 'pools' => [ - 'redis_test' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 128, - 'minResources' => 1, - ], + 'redis_test' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], + // 连接池配置 + 'pools' => [ + ], // db 配置 'db' => [ // 默认连接池名 diff --git a/src/Components/swoole-tracker/example/TCPServer/config/config.php b/src/Components/swoole-tracker/example/TCPServer/config/config.php index aabcf760b3..0ba392aeac 100644 --- a/src/Components/swoole-tracker/example/TCPServer/config/config.php +++ b/src/Components/swoole-tracker/example/TCPServer/config/config.php @@ -65,34 +65,28 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'sync' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], + ], + + // 连接中心配置 + 'connectionCenter' => [ + 'redis_test' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'async' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, ], ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => 6379, - 'password' => null, - ], ], ], ], @@ -106,7 +100,7 @@ // redis 配置 'redis' => [ // 数默认连接池名 - 'defaultPool' => 'redis', + 'defaultPool' => 'redis_test', ], // 内存表配置 @@ -126,7 +120,7 @@ 'redis' => [ 'class' => 'RedisLock', 'options' => [ - 'poolName' => 'redis', + 'poolName' => 'redis_test', ], ], ], diff --git a/src/Components/swoole-tracker/example/WebSocketServer/config/config.php b/src/Components/swoole-tracker/example/WebSocketServer/config/config.php index 7fd35622c9..f6d9de9c41 100644 --- a/src/Components/swoole-tracker/example/WebSocketServer/config/config.php +++ b/src/Components/swoole-tracker/example/WebSocketServer/config/config.php @@ -38,34 +38,28 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'sync' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], + ], + + // 连接中心配置 + 'connectionCenter' => [ + 'redis_test' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'async' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, ], ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], ], ], ], @@ -73,7 +67,7 @@ // redis 配置 'redis' => [ // 数默认连接池名 - 'defaultPool' => 'redis', + 'defaultPool' => 'redis_test', ], // 内存表配置 diff --git a/src/Components/swoole/tests/unit/Component/Tests/RedisManagerTest.php b/src/Components/swoole/tests/unit/Component/Tests/RedisManagerTest.php index fff87b6a96..b51200d488 100644 --- a/src/Components/swoole/tests/unit/Component/Tests/RedisManagerTest.php +++ b/src/Components/swoole/tests/unit/Component/Tests/RedisManagerTest.php @@ -15,6 +15,11 @@ */ class RedisManagerTest extends BaseTestCase { + protected function setUp(): void + { + $this->markTestSkipped('Deprecated Test'); + } + public function testDefaultPoolName(): void { Assert::assertEquals('redis_test', RedisManager::getDefaultPoolName()); diff --git a/src/Components/swoole/tests/unit/Component/config/config.php b/src/Components/swoole/tests/unit/Component/config/config.php index 7e2aaabfc1..4895a67298 100644 --- a/src/Components/swoole/tests/unit/Component/config/config.php +++ b/src/Components/swoole/tests/unit/Component/config/config.php @@ -72,53 +72,54 @@ // 连接池配置 'pools' => [ + ], + // 连接中心配置 + 'connectionCenter' => [ 'redis_test' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], - ], - 'redis_cache' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + 'database' => 1, + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], ], ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, - 'db' => 1, - ], ], - 'redis_manager_test' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], + 'redis_cache' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, - 'db' => 1, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + 'database' => 1, + 'serialize' => false, + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], + // db 配置 'db' => [ // 默认连接池名 diff --git a/src/Components/swoole/tests/unit/HttpServer/config/config.php b/src/Components/swoole/tests/unit/HttpServer/config/config.php index 0fbfcda760..83117200ba 100644 --- a/src/Components/swoole/tests/unit/HttpServer/config/config.php +++ b/src/Components/swoole/tests/unit/HttpServer/config/config.php @@ -118,18 +118,28 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + 'database' => 1, + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php b/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php index 5d4266f055..822c2691f5 100644 --- a/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php +++ b/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php @@ -75,33 +75,48 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], - 'redisSession' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], + 'redisSession' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + 'serialize' => false, + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/swoole/tests/unit/TCPServer/config/config.php b/src/Components/swoole/tests/unit/TCPServer/config/config.php index eef02ff97d..45c45f79ea 100644 --- a/src/Components/swoole/tests/unit/TCPServer/config/config.php +++ b/src/Components/swoole/tests/unit/TCPServer/config/config.php @@ -80,18 +80,27 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/swoole/tests/unit/UDPServer/config/config.php b/src/Components/swoole/tests/unit/UDPServer/config/config.php index a7f0d0a0fc..86b736f8d6 100644 --- a/src/Components/swoole/tests/unit/UDPServer/config/config.php +++ b/src/Components/swoole/tests/unit/UDPServer/config/config.php @@ -77,18 +77,27 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php index e4b03d032a..d580221135 100644 --- a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php @@ -81,18 +81,27 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php index f285536379..1ccc6c7812 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php @@ -85,20 +85,6 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], - ], 'rabbit' => [ 'pool' => [ 'class' => \Imi\AMQP\Pool\AMQPCoroutinePool::class, @@ -116,6 +102,29 @@ ], ], + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // redis 配置 'redis' => [ // 默认连接池名 diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php index 47d60e7f86..8749f00985 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php @@ -85,20 +85,6 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], - ], 'rabbit' => [ 'pool' => [ 'class' => \Imi\AMQP\Pool\AMQPCoroutinePool::class, @@ -116,6 +102,29 @@ ], ], + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // redis 配置 'redis' => [ // 默认连接池名 diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php index 887b404708..729e8b106f 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php @@ -82,20 +82,30 @@ // 连接池配置 'pools' => [ - 'redis' => [ - 'pool' => [ - 'class' => \Imi\Swoole\Redis\Pool\CoroutineRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 0, - ], + ], + + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'options' => [ - \Redis::OPT_READ_TIMEOUT => -1, + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + + 'options' => [ + \Redis::OPT_READ_TIMEOUT => -1, + ], + ], ], ], ], diff --git a/src/Redis/Traits/TRedisPool.php b/src/Redis/Traits/TRedisPool.php index f43134645c..396f454a0a 100644 --- a/src/Redis/Traits/TRedisPool.php +++ b/src/Redis/Traits/TRedisPool.php @@ -4,7 +4,6 @@ namespace Imi\Redis\Traits; -use Imi\Redis\Enum\RedisMode; use Imi\Redis\RedisManager; use Imi\Redis\RedisResource; diff --git a/tests/unit/Component/ErrorEventHandler.php b/tests/unit/Component/ErrorEventHandler.php new file mode 100644 index 0000000000..0fa000eaf8 --- /dev/null +++ b/tests/unit/Component/ErrorEventHandler.php @@ -0,0 +1,34 @@ +stopPropagation(); + + $level = match ($errNo) + { + \E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR, \E_RECOVERABLE_ERROR => LogLevel::ERROR, + \E_WARNING, \E_CORE_WARNING, \E_COMPILE_WARNING, \E_USER_WARNING => LogLevel::WARNING, + \E_NOTICE, \E_USER_NOTICE => LogLevel::NOTICE, + default => LogLevel::INFO, + }; + Log::log($level, $errStr); + } + } + + public function handleException(\Throwable $throwable): void + { + } +} diff --git a/tests/unit/Component/Tests/RedisModelHashObjectTest.php b/tests/unit/Component/Tests/RedisModelHashObjectTest.php deleted file mode 100644 index f2366f0ca0..0000000000 --- a/tests/unit/Component/Tests/RedisModelHashObjectTest.php +++ /dev/null @@ -1,199 +0,0 @@ - 1, - 'name' => 'a', - ]); - $record->age = 11; - $this->assertTrue($record->save()); - } - - public function testFind(): void - { - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisHashObjectModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - } - - public function testSelect(): void - { - $expected = [ - [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ], - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisHashObjectModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $list = TestRedisHashObjectModel::select([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - } - - public function testDelete(): void - { - $record = TestRedisHashObjectModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertTrue($record->delete()); - $this->assertNull(TestRedisHashObjectModel::find([ - 'id' => 1, - 'name' => 'a', - ])); - } - - public function testSafeDelete(): void - { - // --更新-- - // 原始记录 - $record = TestRedisHashObjectModel::newInstance([ - 'id' => 114514, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisHashObjectModel::find([ - 'id' => 114514, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - - $record2 = TestRedisHashObjectModel::find([ - 'id' => 114514, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $record1->age = 23; - $this->assertTrue($record1->save()); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - - // 安全删除成功 - $this->assertTrue($record1->safeDelete()); - - // --删除-- - // 原始记录 - $record = TestRedisHashObjectModel::newInstance([ - 'id' => 114514, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisHashObjectModel::find([ - 'id' => 114514, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - - $record2 = TestRedisHashObjectModel::find([ - 'id' => 114514, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $this->assertTrue($record1->delete()); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - } - - public function testDeleteBatch(): void - { - $record = TestRedisHashObjectModel::newInstance([ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]); - $this->assertTrue($record->save()); - $record = TestRedisHashObjectModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $this->assertEquals(2, TestRedisHashObjectModel::deleteBatch([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ])); - } - - public function testColumnType(): void - { - $record = TestRedisHashObjectColumnTypeModel::newInstance(); - $record->setJson([ - 'name' => 'imi', - ]); - $record->setJsonArray([ - [ - 'name' => '宇润', - ], - [ - 'name' => 'imi', - ], - ]); - $record->setList([1, 2, 3]); - $record->setSet(['a', 'b', 'c']); - $this->assertTrue($record->save()); - $this->assertEquals([ - 'name' => 'imi', - ], $record->getJson()); - $this->assertEquals('宇润', $record->getJsonArray()[0]['name']); - $this->assertEquals('imi', $record->getJsonArray()[1]['name']); - $this->assertEquals([1, 2, 3], $record->getList()); - $this->assertEquals(['a', 'b', 'c'], $record->getSet()); - - $record2 = TestRedisHashObjectColumnTypeModel::find(); - $this->assertEquals($record->toArray(), $record2->toArray()); - } -} diff --git a/tests/unit/Component/Tests/RedisModelHashTest.php b/tests/unit/Component/Tests/RedisModelHashTest.php deleted file mode 100644 index 9719453ba4..0000000000 --- a/tests/unit/Component/Tests/RedisModelHashTest.php +++ /dev/null @@ -1,217 +0,0 @@ - 1, - 'name' => 'a', - ]); - $record->age = 11; - $this->assertTrue($record->save()); - } - - public function testFind(): void - { - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisHashModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - } - - public function testSelect(): void - { - $expected = [ - [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ], - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisHashModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $list = TestRedisHashModel::select([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - } - - public function testDelete(): void - { - $record = TestRedisHashModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertTrue($record->delete()); - $this->assertNull(TestRedisHashModel::find([ - 'id' => 1, - 'name' => 'a', - ])); - } - - public function testSafeDelete(): void - { - // --更新-- - // 原始记录 - $record = TestRedisHashModel::newInstance([ - 'id' => 114514, - 'name' => __METHOD__, - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisHashModel::find([ - 'name' => __METHOD__, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - $record2 = TestRedisHashModel::find([ - 'name' => __METHOD__, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $record1->age = 33; - $record1->save(); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - - // 安全删除成功 - $this->assertTrue($record1->safeDelete()); - - // --删除-- - // 原始记录 - $record = TestRedisHashModel::newInstance([ - 'id' => 114514, - 'name' => __METHOD__, - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisHashModel::find([ - 'name' => __METHOD__, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - $record2 = TestRedisHashModel::find([ - 'name' => __METHOD__, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $record1->delete(); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - } - - public function testDeleteBatch(): void - { - $record = TestRedisHashModel::newInstance([ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]); - $this->assertTrue($record->save()); - $record = TestRedisHashModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $this->assertEquals(2, TestRedisHashModel::deleteBatch([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ])); - } - - public function testFormatter(): void - { - $record = TestRedisHashWithFormatterModel::newInstance([ - 'id' => 1, - 'name' => 'a', - ]); - $record->age = 11; - $this->assertTrue($record->save()); - - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisHashWithFormatterModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - - $expected = [ - [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ], - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisHashWithFormatterModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $list = TestRedisHashWithFormatterModel::select([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - } -} diff --git a/tests/unit/Component/Tests/RedisModelTest.php b/tests/unit/Component/Tests/RedisModelTest.php deleted file mode 100644 index 72ed88bef1..0000000000 --- a/tests/unit/Component/Tests/RedisModelTest.php +++ /dev/null @@ -1,332 +0,0 @@ - 1, - 'name' => 'a', - ]); - $record->age = 11; - $this->assertTrue($record->save()); - } - - public function testFind(): void - { - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisModel::find('1-a'); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - $record = TestRedisModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - } - - public function testSelect(): void - { - $expected = [ - [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ], - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $list = TestRedisModel::select('1-a', '2-b'); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - $list = TestRedisModel::select([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - } - - public function testDelete(): void - { - $record = TestRedisModel::find('1-a'); - $this->assertNotNull($record); - $this->assertTrue($record->delete()); - $this->assertNull(TestRedisModel::find('1-a')); - } - - public function testSafeDelete(): void - { - // --更新-- - // 原始记录 - $record = TestRedisModel::newInstance([ - 'id' => 114514, - 'name' => __METHOD__, - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisModel::find([ - 'id' => 114514, - 'name' => __METHOD__, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - $record2 = TestRedisModel::find([ - 'id' => 114514, - 'name' => __METHOD__, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $record1->age = 33; - $record1->save(); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - - // 安全删除成功 - $this->assertTrue($record1->safeDelete()); - - // --删除-- - // 原始记录 - $record = TestRedisModel::newInstance([ - 'id' => 114514, - 'name' => __METHOD__, - 'age' => 22, - ]); - $this->assertTrue($record->save()); - - // 查出2个对象实例 - $record1 = TestRedisModel::find([ - 'id' => 114514, - 'name' => __METHOD__, - ]); - $this->assertNotNull($record1); - $this->assertEquals($record->toArray(), $record1->toArray()); - $record2 = TestRedisModel::find([ - 'id' => 114514, - 'name' => __METHOD__, - ]); - $this->assertNotNull($record2); - $this->assertEquals($record->toArray(), $record2->toArray()); - - // 更新一个 - $record1->delete(); - - // 安全删除失败 - $this->assertFalse($record2->safeDelete()); - } - - public function testDeleteBatch(): void - { - $record = TestRedisModel::newInstance([ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]); - $this->assertTrue($record->save()); - $record = TestRedisModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $this->assertEquals(2, TestRedisModel::deleteBatch([ - 'id' => 1, - 'name' => 'a', - ], '2-b')); - } - - /** - * @testdox ttl - */ - public function testTTL(): void - { - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisModel2::newInstance($expected); - $this->assertTrue($record->save()); - - $record = TestRedisModel2::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertEquals($expected, $record->toArray()); - - usleep(1500000); - $record = TestRedisModel2::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNull($record); - } - - public function testFormatter(): void - { - $record = TestRedisWithFormatterModel::newInstance([ - 'id' => 1, - 'name' => 'a', - ]); - $record->age = 11; - $this->assertTrue($record->save()); - - $expected = [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ]; - $record = TestRedisWithFormatterModel::find('formatter-1-a'); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - $record = TestRedisWithFormatterModel::find([ - 'id' => 1, - 'name' => 'a', - ]); - $this->assertNotNull($record); - $this->assertEquals($expected, $record->toArray()); - - $expected = [ - [ - 'id' => 1, - 'name' => 'a', - 'age' => 11, - ], - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisWithFormatterModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $this->assertTrue($record->save()); - $list = TestRedisWithFormatterModel::select('formatter-1-a', 'formatter-2-b'); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - $list = TestRedisWithFormatterModel::select([ - 'id' => 1, - 'name' => 'a', - ], [ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - } - - public function testSerialize(): void - { - $expected = [ - [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ], - ]; - $record = TestRedisModel::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - /** @var TestRedisModel $record */ - $record = unserialize(serialize($record)); - $this->assertTrue($record->save()); - $list = TestRedisModel::select('2-b'); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - $list = TestRedisModel::select([ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertEquals($expected, json_decode(json_encode($list), true)); - - $record = TestRedisModel::find([ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertNotNull($record); - $this->assertEquals(22, $record->age); - $record2 = unserialize(serialize($record)); - $this->assertEquals($record->toArray(), $record2->toArray()); - } - - public function testSerializable(): void - { - $data = [ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]; - $record = TestRedisModelSerializable::newInstance($data); - $record->save(); - - $record2 = TestRedisModelSerializable::find([ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertNotNull($record2); - foreach ($data as $name => $value) - { - $this->assertEquals($value, $record2->{$name}); - } - } - - public function testVirtual(): void - { - $record = TestRedisModelVirtual::newInstance([ - 'id' => 2, - 'name' => 'b', - 'age' => 22, - ]); - $record->save(); - - $record2 = TestRedisModelVirtual::find([ - 'id' => 2, - 'name' => 'b', - ]); - $this->assertNotNull($record2); - foreach ([ - 'id' => 2, - 'name' => 'b', - 'age' => 0, - ] as $name => $value) - { - $this->assertEquals($value, $record2->{$name}); - } - } -} diff --git a/tests/unit/Component/config/config.php b/tests/unit/Component/config/config.php index a2a06400d9..d0c8ebf0de 100644 --- a/tests/unit/Component/config/config.php +++ b/tests/unit/Component/config/config.php @@ -83,7 +83,11 @@ 'b' => 'bbb', ], 'ErrorLog' => [ - 'exceptionLevel' => \E_ALL, + 'catchLevel' => \E_ALL, + 'exceptionLevel' => \E_ALL, + 'errorEventHandlers' => [ + \Imi\Test\Component\ErrorEventHandler::class, + ], ], 'DbQueryLog' => [ 'enable' => true, @@ -103,52 +107,6 @@ // 连接池配置 'pools' => [ - 'redis_test' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], - ], - 'redis_cache' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, - 'db' => 1, - ], - ], - 'redis_manager_test' => [ - 'pool' => [ - 'class' => \Imi\Redis\SyncRedisPool::class, - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - ], - ], - 'resource' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, - 'db' => 1, - ], - ], ], // db 配置 'db' => [ @@ -174,14 +132,33 @@ // 默认连接池名 'defaultPool' => 'redis_test', 'connections' => [ - 'tradition' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'serialize' => false, + ], + ], + + // 连接中心配置 + 'connectionCenter' => [ + 'redis_test' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], ], ], ], + // 缓存配置 'cache' => [ 'default' => 'file1', @@ -215,14 +192,14 @@ 'redis' => [ 'handlerClass' => \Imi\Cache\Handler\Redis::class, 'option' => [ - 'poolName' => 'redis_cache', + 'poolName' => 'redis_test', 'formatHandlerClass' => \Imi\Util\Format\Json::class, ], ], 'redisHash' => [ 'handlerClass' => \Imi\Cache\Handler\RedisHash::class, 'option' => [ - 'poolName' => 'redis_cache', + 'poolName' => 'redis_test', 'separator' => '->', 'formatHandlerClass' => \Imi\Util\Format\Json::class, ], From 231d105099dd0efa24e1a8bc35ecfefc17c5f3bf Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 11:49:59 +0800 Subject: [PATCH 03/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/amqp/example/config/config.php | 2 +- src/Components/grpc/example/config/config.php | 2 +- .../kafka/example/config/config.php | 2 +- src/Components/model/src/RedisModel.php | 19 ++++++++------- src/Components/mqtt/example/config/config.php | 2 +- .../queue/example/config/config.php | 6 ++--- src/Components/redis/helper.php | 1 + .../redis/src/Connector/PhpRedisConnector.php | 3 +-- .../redis/src/Connector/PredisConnector.php | 17 ++++++++------ .../src/Connector/RedisConnectionDriver.php | 5 ++-- .../src/Handler/PredisClusterHandler.php | 5 ++-- src/Components/redis/src/RedisManager.php | 23 ++++++++----------- .../redis/src/Traits/TPredisMethod.php | 14 +++++++---- src/Components/redis/tests/PHPUnitHook.php | 2 -- .../tests/Tests/AbstractRedisTestCase.php | 5 +--- .../tests/Tests/Model/AbstractRedisModel.php | 8 +++---- .../redis/tests/Tests/PhpRedisClusterTest.php | 3 ++- .../redis/tests/Tests/PhpRedisTest.php | 4 ++-- .../redis/tests/Tests/PredisClusterTest.php | 5 ++-- .../redis/tests/Tests/PredisTest.php | 2 +- .../redis/tests/Tests/RedisManagerTest.php | 3 ++- .../redis/tests/Tests/RedisTest.php | 1 + src/Components/redis/tests/config/config.php | 10 ++++---- .../snowflake/tests/config/config.php | 2 +- .../example/TCPServer/config/config.php | 2 +- .../example/WebSocketServer/config/config.php | 2 +- .../tests/unit/Component/config/config.php | 4 ++-- .../tests/unit/HttpServer/config/config.php | 2 +- .../unit/RedisSessionServer/config/config.php | 4 ++-- .../tests/unit/TCPServer/config/config.php | 2 +- .../tests/unit/UDPServer/config/config.php | 2 +- .../unit/WebSocketServer/config/config.php | 2 +- .../config/config.php | 2 +- .../config/config.php | 2 +- .../config/config.php | 2 +- 35 files changed, 91 insertions(+), 81 deletions(-) diff --git a/src/Components/amqp/example/config/config.php b/src/Components/amqp/example/config/config.php index a6159cf265..510ae29559 100644 --- a/src/Components/amqp/example/config/config.php +++ b/src/Components/amqp/example/config/config.php @@ -90,7 +90,7 @@ 'connectionCenter' => Imi::checkAppType('swoole') ? [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/grpc/example/config/config.php b/src/Components/grpc/example/config/config.php index 1f958a0a61..ca14538c62 100644 --- a/src/Components/grpc/example/config/config.php +++ b/src/Components/grpc/example/config/config.php @@ -72,7 +72,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/kafka/example/config/config.php b/src/Components/kafka/example/config/config.php index baaa5111d6..0aff0d9af3 100644 --- a/src/Components/kafka/example/config/config.php +++ b/src/Components/kafka/example/config/config.php @@ -85,7 +85,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index 552e59a291..7be292d252 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -18,7 +18,6 @@ use Imi\Redis\RedisManager; use Imi\Util\Format\IFormat; use Imi\Util\Imi; -use function Imi\dump; /** * Redis 模型. @@ -478,7 +477,8 @@ public function safeDelete(): bool $data = $formatter->encode($data); } $redis = static::__getRedis($this); - if ($redis->isSupportSerialize()) { + if ($redis->isSupportSerialize()) + { $data = $redis->_serialize($data); } @@ -497,7 +497,8 @@ public function safeDelete(): bool $data = $formatter->encode($data); } $redis = static::__getRedis($this); - if ($redis->isSupportSerialize()) { + if ($redis->isSupportSerialize()) + { $data = $redis->_serialize($data); } @@ -514,7 +515,8 @@ public function safeDelete(): bool foreach ($data as $key => $value) { $argv[] = $key; - if ($redis->isSupportSerialize()) { + if ($redis->isSupportSerialize()) + { $argv[] = $redis->_serialize($value); } } @@ -846,6 +848,7 @@ protected function parseSaveData(array &$data): void * Fork 模型. * * @param class-string|null $formatter + * * @return class-string */ public static function fork(?int $db = null, ?string $poolName = null, ?string $formatter = null): string @@ -867,10 +870,11 @@ public static function fork(?int $db = null, ?string $poolName = null, ?string $ { $entity->poolName = $poolName; } - if (null !== $formatter) { + if (null !== $formatter) + { $entity->formatter = $formatter; } - $entityData = \var_export(\serialize($entity), true); + $entityData = var_export(serialize($entity), true); $class = str_replace('\\', '__', static::class . '\\' . md5($db . '\\' . $poolName . '\\' . $formatter)); $extendsClass = static::class; @@ -888,7 +892,7 @@ class {$class} extends \\{$extendsClass} public static function __getRedisEntity(string|RedisModel|null \$object = null): ?RedisEntity { if (null === self::\$forkEntity) { - self::\$forkEntity = unserialize($entityData); + self::\$forkEntity = unserialize({$entityData}); } return self::\$forkEntity; @@ -900,4 +904,3 @@ public static function __getRedisEntity(string|RedisModel|null \$object = null): return $forks[static::class][$db][$poolName] = $namespace . '\\' . $class; } } - diff --git a/src/Components/mqtt/example/config/config.php b/src/Components/mqtt/example/config/config.php index 1c5f7f4c9c..f5ff3e6e3a 100644 --- a/src/Components/mqtt/example/config/config.php +++ b/src/Components/mqtt/example/config/config.php @@ -60,7 +60,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/queue/example/config/config.php b/src/Components/queue/example/config/config.php index 480d1476c7..223d78e1b3 100644 --- a/src/Components/queue/example/config/config.php +++ b/src/Components/queue/example/config/config.php @@ -62,7 +62,7 @@ 'connectionCenter' => Imi::checkAppType('swoole') ? [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -74,8 +74,8 @@ 'port' => env('REDIS_SERVER_PORT', 6379), 'password' => env('REDIS_SERVER_PASSWORD'), - 'client' => 'phpredis', - 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, 'database' => 0, ], ], diff --git a/src/Components/redis/helper.php b/src/Components/redis/helper.php index 23d72b4634..acfd016e64 100644 --- a/src/Components/redis/helper.php +++ b/src/Components/redis/helper.php @@ -1,4 +1,5 @@ connect($host, $config->port, $config->timeout); } - if (('' !== ($config->password)) && !$redis->auth($config->password)) + if (('' !== $config->password) && !$redis->auth($config->password)) { throw new \RedisException($redis->getLastError()); } diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index b144b8b607..bb0b7293c8 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -6,7 +6,6 @@ use Imi\Redis\Handler\PredisClusterHandler; use Imi\Redis\Handler\PredisHandler; -use Imi\Util\ArrayUtil; class PredisConnector implements IRedisConnector { @@ -17,16 +16,19 @@ public static function connect(RedisDriverConfig $config): PredisHandler { $params = [ 'scheme' => 'tcp', - 'host' => $config->host, - 'port' => $config->port, + 'host' => $config->host, + 'port' => $config->port, ]; - if ($config->password) { + if ($config->password) + { $params['password'] = $config->password; } - if (null !== $config->database) { + if (null !== $config->database) + { $params['database'] = $config->database; } - if ($config->prefix) { + if ($config->prefix) + { $params['prefix'] = $config->prefix; } $client = new \Predis\Client($params); @@ -48,7 +50,8 @@ public static function connectCluster(RedisDriverConfig $config): PredisClusterH { $options['parameters']['database'] = $config->database; } - if ($config->prefix) { + if ($config->prefix) + { $options['prefix'] = $config->prefix; } diff --git a/src/Components/redis/src/Connector/RedisConnectionDriver.php b/src/Components/redis/src/Connector/RedisConnectionDriver.php index b9159065ff..af5cdfa825 100644 --- a/src/Components/redis/src/Connector/RedisConnectionDriver.php +++ b/src/Components/redis/src/Connector/RedisConnectionDriver.php @@ -1,4 +1,5 @@ $connector::connect($config), RedisMode::Cluster => $connector::connectCluster($config), - RedisMode::Sentinel => throw new \RuntimeException('To be implemented'), + RedisMode::Sentinel => throw new \RuntimeException('To be implemented'), }; } diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php index cfebfe073d..6622bacbc9 100644 --- a/src/Components/redis/src/Handler/PredisClusterHandler.php +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -32,9 +32,10 @@ public function getNodes(): array $connection = $this->client->getConnection(); $nodes = $connection->getSlotMap()->getNodes(); - return \array_map(function ($node) { - $arr = \explode(':', $node); + return array_map(static function ($node) { + $arr = explode(':', $node); $arr[1] = (int) $arr[1]; + return $arr; }, $nodes); } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index c56b918ad6..f2813262a5 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -4,20 +4,11 @@ namespace Imi\Redis; -use Imi\App; use Imi\Config; use Imi\ConnectionCenter\Contract\IConnection; -use Imi\ConnectionCenter\Contract\IConnectionManager; use Imi\ConnectionCenter\Enum\ConnectionStatus; use Imi\ConnectionCenter\Facade\ConnectionCenter; -use Imi\Pool\PoolManager; -use Imi\Redis\Connector\IRedisConnector; -use Imi\Redis\Connector\PhpRedisConnector; -use Imi\Redis\Connector\PredisConnector; -use Imi\Redis\Enum\RedisMode; use Imi\Redis\Handler\IRedisHandler; -use Imi\RequestContext; -use Imi\Timer\Timer; class RedisManager { @@ -37,6 +28,7 @@ public static function getNewInstance(?string $poolName = null): IRedisHandler /** @var IRedisHandler $instance */ $instance = $connection->getInstance(); self::recordInstanceLinkPool($instance, $connection); + return $instance; } @@ -52,6 +44,7 @@ public static function getInstance(?string $poolName = null): IRedisHandler /** @var IRedisHandler $instance */ $instance = $connection->getInstance(); self::recordInstanceLinkPool($instance, $connection); + return $instance; } @@ -66,6 +59,7 @@ public static function use(string $name, callable $callback): mixed try { $connection = self::getConnectionByInstance($resource); + return $callback($connection, $resource); } finally @@ -76,7 +70,8 @@ public static function use(string $name, callable $callback): mixed protected static function recordInstanceLinkPool(IRedisHandler $handler, IConnection $connection): void { - if (!isset(self::$instanceLinkConnectionMap)) { + if (!isset(self::$instanceLinkConnectionMap)) + { self::$instanceLinkConnectionMap = new \WeakMap(); } @@ -99,10 +94,12 @@ protected static function unsetConnectionInstance(IRedisHandler $handler): void public static function release(IRedisHandler $redis): void { $connection = self::getConnectionByInstance($redis); - if (null === $connection) { + if (null === $connection) + { throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); } - if ($connection->getStatus() === ConnectionStatus::WaitRelease) { + if (ConnectionStatus::WaitRelease === $connection->getStatus()) + { $connection->getManager()->releaseConnection($connection); } self::unsetConnectionInstance($redis); @@ -130,7 +127,7 @@ public static function getDefaultPoolName(): string } /** - * 从当前上下文中获取公用连接 + * 从当前上下文中获取公用连接. */ public static function isQuickFromRequestContext(): bool { diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php index 21ed10cce3..0251f5dfb4 100644 --- a/src/Components/redis/src/Traits/TPredisMethod.php +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -40,12 +40,18 @@ public function evalEx(string $script, ?array $args = null, ?int $numKeys = null $sha1 = sha1($script); $client = $this->client; - try { + try + { return $client->evalSha($sha1, $numKeys, ...$args); - } catch (PredisException $exception) { - if ('NOSCRIPT No matching script. Please use EVAL.' === $exception->getMessage()) { + } + catch (PredisException $exception) + { + if ('NOSCRIPT No matching script. Please use EVAL.' === $exception->getMessage()) + { return $client->eval($script, $numKeys, ...$args); - } else { + } + else + { throw $exception; } } diff --git a/src/Components/redis/tests/PHPUnitHook.php b/src/Components/redis/tests/PHPUnitHook.php index 434f7c9d3d..782f6c241a 100644 --- a/src/Components/redis/tests/PHPUnitHook.php +++ b/src/Components/redis/tests/PHPUnitHook.php @@ -7,8 +7,6 @@ use Imi\App; use Imi\Cli\CliApp; use Imi\Core\CoreEvents; -use Imi\Db\Db; -use Imi\Db\Interfaces\IDb; use Imi\Event\Contract\IEvent; use Imi\Event\Event; use PHPUnit\Runner\Extension\Extension; diff --git a/src/Components/redis/tests/Tests/AbstractRedisTestCase.php b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php index fe6f5cea10..9e29a0eed6 100644 --- a/src/Components/redis/tests/Tests/AbstractRedisTestCase.php +++ b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php @@ -1,4 +1,5 @@ assertNotNull($record2); foreach ([ - 'id' => 2, - 'name' => 'b', - 'age' => 0, - ] as $name => $value) + 'id' => 2, + 'name' => 'b', + 'age' => 0, + ] as $name => $value) { $this->assertEquals($value, $record2->{$name}); } diff --git a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php index 653d907502..d747e8289a 100644 --- a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php @@ -31,7 +31,8 @@ public function testGetDrive(): IRedisHandler protected function flush(IRedisHandler $redis): void { // 清空数据 - foreach ($redis->getNodes() as $node) { + foreach ($redis->getNodes() as $node) + { self::assertTrue($redis->flushdb($node, false)); } } diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php index 20f7e2fe1f..a3e6468462 100644 --- a/src/Components/redis/tests/Tests/PhpRedisTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -176,10 +176,10 @@ public function testGeoAdd(IRedisHandler $redis): void $oriOption = $redis->getOption(\Redis::OPT_SERIALIZER); self::assertTrue($redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP)); - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); self::assertTrue($redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE)); - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); $redis->setOption(\Redis::OPT_SERIALIZER, $oriOption); } diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index dfe0b5f384..5e8560fb04 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -33,7 +33,8 @@ public function testGetDrive(): IRedisHandler protected function flush(IRedisHandler $redis): void { // 清空数据 - foreach ($redis->getNodes() as $node) { + foreach ($redis->getNodes() as $node) + { $client = $redis->getClientBy('id', "{$node[0]}:{$node[1]}"); self::assertTrue($client->flushdb()); } @@ -47,6 +48,6 @@ public function testGeoAdd(IRedisHandler $redis): void self::markTestSkipped('Windows redis not support geo.'); } - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); } } diff --git a/src/Components/redis/tests/Tests/PredisTest.php b/src/Components/redis/tests/Tests/PredisTest.php index 8f7127aa55..d4428f79aa 100644 --- a/src/Components/redis/tests/Tests/PredisTest.php +++ b/src/Components/redis/tests/Tests/PredisTest.php @@ -36,6 +36,6 @@ public function testGeoAdd(IRedisHandler $redis): void self::markTestSkipped('Windows redis not support geo.'); } - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . \bin2hex(\random_bytes(4)))); + self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); } } diff --git a/src/Components/redis/tests/Tests/RedisManagerTest.php b/src/Components/redis/tests/Tests/RedisManagerTest.php index 31842e667c..89532736d6 100644 --- a/src/Components/redis/tests/Tests/RedisManagerTest.php +++ b/src/Components/redis/tests/Tests/RedisManagerTest.php @@ -12,6 +12,7 @@ /** * @testdox RedisManager + * * @deprecated */ class RedisManagerTest extends BaseTest @@ -96,7 +97,7 @@ public function testInstance(): void private function assertRedisHandler(IRedisHandler $redisHandler): void { Assert::assertInstanceOf(IRedisHandler::class, $redisHandler); - $str = \bin2hex(random_bytes(8)); + $str = bin2hex(random_bytes(8)); $redisHandler->set('imi:test:a', $str); Assert::assertEquals($str, $redisHandler->get('imi:test:a')); } diff --git a/src/Components/redis/tests/Tests/RedisTest.php b/src/Components/redis/tests/Tests/RedisTest.php index 091b6088c8..9048d99f50 100644 --- a/src/Components/redis/tests/Tests/RedisTest.php +++ b/src/Components/redis/tests/Tests/RedisTest.php @@ -14,6 +14,7 @@ /** * @testdox Redis + * * @deprecated */ class RedisTest extends BaseTest diff --git a/src/Components/redis/tests/config/config.php b/src/Components/redis/tests/config/config.php index a2ee6e3ca1..320dbeca80 100644 --- a/src/Components/redis/tests/config/config.php +++ b/src/Components/redis/tests/config/config.php @@ -59,7 +59,7 @@ 'connectionCenter' => [ 'test_phpredis_standalone' => [ 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -79,7 +79,7 @@ ], 'test_phpredis_cluster' => [ 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -106,7 +106,7 @@ ], 'test_predis_standalone' => [ 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -126,7 +126,7 @@ ], 'test_predis_cluster' => [ 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -156,7 +156,7 @@ // redis 配置 'redis' => [ // 默认连接池名 - 'defaultPool' => 'test_phpredis_standalone', + 'defaultPool' => 'test_phpredis_standalone', 'quickFromRequestContext' => true, ], // 缓存配置 diff --git a/src/Components/snowflake/tests/config/config.php b/src/Components/snowflake/tests/config/config.php index 5a6ce7c145..a664e9166c 100644 --- a/src/Components/snowflake/tests/config/config.php +++ b/src/Components/snowflake/tests/config/config.php @@ -33,7 +33,7 @@ ], 'redis_test' => [ 'manager' => \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole-tracker/example/TCPServer/config/config.php b/src/Components/swoole-tracker/example/TCPServer/config/config.php index 0ba392aeac..c910486b43 100644 --- a/src/Components/swoole-tracker/example/TCPServer/config/config.php +++ b/src/Components/swoole-tracker/example/TCPServer/config/config.php @@ -71,7 +71,7 @@ 'connectionCenter' => [ 'redis_test' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole-tracker/example/WebSocketServer/config/config.php b/src/Components/swoole-tracker/example/WebSocketServer/config/config.php index f6d9de9c41..8c429d5abf 100644 --- a/src/Components/swoole-tracker/example/WebSocketServer/config/config.php +++ b/src/Components/swoole-tracker/example/WebSocketServer/config/config.php @@ -44,7 +44,7 @@ 'connectionCenter' => [ 'redis_test' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/Component/config/config.php b/src/Components/swoole/tests/unit/Component/config/config.php index 4895a67298..4031e4bb7a 100644 --- a/src/Components/swoole/tests/unit/Component/config/config.php +++ b/src/Components/swoole/tests/unit/Component/config/config.php @@ -77,7 +77,7 @@ 'connectionCenter' => [ 'redis_test' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -98,7 +98,7 @@ ], 'redis_cache' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/HttpServer/config/config.php b/src/Components/swoole/tests/unit/HttpServer/config/config.php index 83117200ba..ca1b5cd1c0 100644 --- a/src/Components/swoole/tests/unit/HttpServer/config/config.php +++ b/src/Components/swoole/tests/unit/HttpServer/config/config.php @@ -123,7 +123,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php b/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php index 822c2691f5..b902f480b6 100644 --- a/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php +++ b/src/Components/swoole/tests/unit/RedisSessionServer/config/config.php @@ -80,7 +80,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], @@ -100,7 +100,7 @@ ], 'redisSession' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/TCPServer/config/config.php b/src/Components/swoole/tests/unit/TCPServer/config/config.php index 45c45f79ea..8759b167ea 100644 --- a/src/Components/swoole/tests/unit/TCPServer/config/config.php +++ b/src/Components/swoole/tests/unit/TCPServer/config/config.php @@ -85,7 +85,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/UDPServer/config/config.php b/src/Components/swoole/tests/unit/UDPServer/config/config.php index 86b736f8d6..a8f09225f4 100644 --- a/src/Components/swoole/tests/unit/UDPServer/config/config.php +++ b/src/Components/swoole/tests/unit/UDPServer/config/config.php @@ -82,7 +82,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php index d580221135..04bfe30bae 100644 --- a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php @@ -86,7 +86,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php index 1ccc6c7812..cc0a588038 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpRouteServerUtil/config/config.php @@ -105,7 +105,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php index 8749f00985..bf9ee82d6a 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithAmqpServerUtil/config/config.php @@ -105,7 +105,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], diff --git a/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php b/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php index 729e8b106f..b1720d60ea 100644 --- a/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServerWithRedisServerUtil/config/config.php @@ -87,7 +87,7 @@ 'connectionCenter' => [ 'redis' => [ 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, - 'pool' => [ + 'pool' => [ 'maxResources' => 10, 'minResources' => 0, ], From 08159b4314c348c5cb0ae6f0c7612c0e7db87b0e Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 11:54:01 +0800 Subject: [PATCH 04/97] =?UTF-8?q?Update:=20=E9=80=82=E9=85=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=B4=A8=E9=87=8F=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev/phpstan.sh | 1 + dev/rector.sh | 1 + src/Components/redis/rector.php | 5 +++++ 3 files changed, 7 insertions(+) create mode 100644 src/Components/redis/rector.php diff --git a/dev/phpstan.sh b/dev/phpstan.sh index 0c5ad795dc..2457b8c75c 100755 --- a/dev/phpstan.sh +++ b/dev/phpstan.sh @@ -28,6 +28,7 @@ components=( "connection-center" "database" "model" + "redis" ) analyze_component() { diff --git a/dev/rector.sh b/dev/rector.sh index e1f9d88a02..1f83a71f6b 100644 --- a/dev/rector.sh +++ b/dev/rector.sh @@ -28,6 +28,7 @@ components=( "connection-center" "database" "model" + "redis" ) analyze_component() { diff --git a/src/Components/redis/rector.php b/src/Components/redis/rector.php new file mode 100644 index 0000000000..5e23e0976d --- /dev/null +++ b/src/Components/redis/rector.php @@ -0,0 +1,5 @@ + Date: Fri, 16 Feb 2024 11:57:11 +0800 Subject: [PATCH 05/97] =?UTF-8?q?Update:=20=E5=B1=8F=E8=94=BD=E9=83=A8?= =?UTF-8?q?=E5=88=86=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 690 +++++++++++++++++----------------- .github/workflows/codecov.yml | 1 + 2 files changed, 346 insertions(+), 345 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2545a4dcce..28bb08d0e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,99 +117,99 @@ jobs: if: failure() run: docker exec ${ENV_SERVICE} php .github/print-logs.php - ci-unix: - name: Linux Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} With Redis UnixSocket - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swoole: - - version: php8.2-swoole-5.1 - roadrunner: [2.7.*] - env: - ENV_SERVICE: swoole - REPOSITORY_OWNER: ${{ github.repository_owner }} - IMAGE_VERSION: ${{ matrix.swoole.version }} - MYSQL_DOCKER_VERSION: "8.0" - REDIS_SERVER_HOST: /tmp/docker/redis.sock - ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Prepare1 - run: | - echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} - mkdir -p /tmp/base_cache/composer - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: /tmp/base_cache/composer - key: ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} - restore-keys: | - ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}- - ${{ runner.os }}-composer- - - name: Prepare2 - uses: ./.github/actions/ci-prepare - with: - env: ${{ env.ENV_SERVICE }} - - name: Test - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test - - name: Test swoole - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-swoole - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-workerman-gateway - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-roadrunner - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-fpm - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-jwt - - name: Test queue - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-queue - - name: Test amqp - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-amqp - - name: Test kafka - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-kafka - - name: Test grpc - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-grpc - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-snowflake - - name: Test mqtt - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-mqtt - - name: Test smarty - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-smarty - - name: Test pgsql - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-pgsql - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-connection-center - - name: Test database - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-model - - name: Print logs - if: failure() - run: docker exec ${ENV_SERVICE} php .github/print-logs.php +# ci-unix: +# name: Linux Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} With Redis UnixSocket +# runs-on: ubuntu-latest +# strategy: +# fail-fast: false +# matrix: +# swoole: +# - version: php8.2-swoole-5.1 +# roadrunner: [2.7.*] +# env: +# ENV_SERVICE: swoole +# REPOSITORY_OWNER: ${{ github.repository_owner }} +# IMAGE_VERSION: ${{ matrix.swoole.version }} +# MYSQL_DOCKER_VERSION: "8.0" +# REDIS_SERVER_HOST: /tmp/docker/redis.sock +# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# steps: +# - name: Checkout +# uses: actions/checkout@v4 +# - name: Prepare1 +# run: | +# echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} +# mkdir -p /tmp/base_cache/composer +# - name: Cache dependencies +# uses: actions/cache@v3 +# with: +# path: /tmp/base_cache/composer +# key: ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} +# restore-keys: | +# ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}- +# ${{ runner.os }}-composer- +# - name: Prepare2 +# uses: ./.github/actions/ci-prepare +# with: +# env: ${{ env.ENV_SERVICE }} +# - name: Test +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test +# - name: Test swoole +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-swoole +# - name: Test workerman +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-workerman +# - name: Test workerman-gateway +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-workerman-gateway +# - name: Test roadrunner +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-roadrunner +# - name: Test fpm +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-fpm +# - name: Test jwt +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-jwt +# - name: Test queue +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-queue +# - name: Test amqp +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-amqp +# - name: Test kafka +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-kafka +# - name: Test grpc +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-grpc +# - name: Test snowflake +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-snowflake +# - name: Test mqtt +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-mqtt +# - name: Test smarty +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-smarty +# - name: Test pgsql +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-pgsql +# - name: Test connection-center +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-connection-center +# - name: Test database +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-database +# - name: Test model +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-model +# - name: Print logs +# if: failure() +# run: docker exec ${ENV_SERVICE} php .github/print-logs.php ci-swoole-cli: name: Swoole-cli-${{ matrix.swoole-cli }} @@ -322,255 +322,255 @@ jobs: if: failure() run: php .github/print-logs.php - ci-macos: - name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} - runs-on: macos-latest - strategy: - fail-fast: false - matrix: - php: ["8.1", "8.2"] - swoole: [v5.1.0, v5.0.3] - roadrunner: [2.7.*] - env: - MYSQL_SERVER_PASSWORD: "root" - PHP_VERSION: ${{ matrix.php }} - IMI_TEST_AMQP_SERVER_UTIL: 0 - IMI_ROADRUNNER_BINARY: ${{ github.workspace }}/rr - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup MySQL - uses: shogo82148/actions-setup-mysql@v1 - with: - mysql-version: "8.0" - root-password: root - my-cnf: | - socket=/tmp/mysql.sock - - name: Setup Redis - uses: shogo82148/actions-setup-redis@v1 - with: - redis-version: "6.x" - - name: Get Openssl Dir - id: opecssl-dir - run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl - extensions: > - apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, zip, :opcache, - swoole-swoole/swoole-src@${{ matrix.swoole }} - env: - SWOOLE_CONFIGURE_OPTS: > - --enable-openssl - --with-openssl-dir=${{ steps.opecssl-dir.outputs.path }} - --enable-http2 - --enable-mysqlnd - --enable-swoole-json - --enable-swoole-curl - - name: Check Version - run: | - php -v - php -m - composer -V - php --ri swoole - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ env.php-versions }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} - restore-keys: | - ${{ runner.os }}-composer-${{ env.php-versions }}- - ${{ runner.os }}-composer- - - name: Prepare - run: | - echo "::group::Env prepare" - mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' - echo "::endgroup::" - echo "::group::Composer install" - composer update --prefer-dist --no-progress - echo "::endgroup::" - echo "::group::Table Init" - tests/db/install-db.sh - echo "::endgroup::" - - - name: Install RoadRunner - run: | - echo no | src/Components/roadrunner/vendor/bin/rr get-binary -f $ROADRUNNER_DOCKER_VERSION - ./rr -v - - - name: Prepared - run: | - echo "test_prepared=1" >> $GITHUB_ENV - - - name: Test - if: ${{ env.test_prepared && always() }} - run: composer test - - name: Test swoole - if: ${{ env.test_prepared && always() }} - run: composer test-swoole - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: composer test-workerman-gateway - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: composer test-roadrunner - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: composer test-fpm - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: composer test-jwt - - name: Test queue - if: ${{ env.test_prepared && always() }} - run: composer test-queue - - name: Test grpc - if: ${{ env.test_prepared && always() }} - run: composer test-grpc - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: composer test-snowflake - - name: Test mqtt - if: ${{ env.test_prepared && always() }} - run: composer test-mqtt - - name: Test smarty - if: ${{ env.test_prepared && always() }} - run: composer test-smarty - - name: Test phar - if: ${{ env.test_prepared && always() }} - run: composer test-phar - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: composer test-connection-center - - name: Test database - if: ${{ env.test_prepared && always() }} - run: composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: composer test-model - - name: Print logs - if: failure() - run: php .github/print-logs.php - - ci-windows: - name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - php: ["8.1"] # 部分扩展还未在 pecl 发布 PHP 8.2 Windows 版扩展,所以无法测试 - roadrunner: [2.7.*] - extensions: - [ - "apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, :opcache", - ] - env: - IMI_ROADRUNNER_BINARY: ${{ github.workspace }}\rr.exe - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} - - steps: - - uses: actions/checkout@v4 - - - name: Setup MySQL - uses: shogo82148/actions-setup-mysql@v1 - with: - mysql-version: "8.0" - root-password: root - - - name: Setup Redis-server - run: | - nuget install redis-64 -excludeversion - redis-64\tools\redis-server.exe --service-install - redis-64\tools\redis-server.exe --service-start - '@ECHO Redis Started' - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - ini-values: session.save_path=C:\temp - tools: pecl - extensions: ${{ matrix.extensions }} - env: - fail-fast: true - - - name: Get composer cache directory - id: composer-cache - shell: pwsh - run: | - Set-Variable -Name CacheDir -Value (composer config cache-files-dir) - "dir=$CacheDir" >> $env:GITHUB_OUTPUT - - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} - restore-keys: | - ${{ runner.os }}-composer-${{ matrix.php }}- - ${{ runner.os }}-composer- - - - name: Prepare - run: | - Write-Output "::group::Env prepare" - mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' - Write-Output "::endgroup::" - Write-Output "::group::Composer install" - composer update --prefer-dist --no-progress - Write-Output "::endgroup::" - Write-Output "::group::Table Init" - php src\Cli\bin\imi-cli generate/table --app-namespace "Imi\Model\Test" - Write-Output "::endgroup::" - - - name: Install RoadRunner - run: | - echo no | src\Components\roadrunner\vendor\bin\rr get-binary -f $env:ROADRUNNER_DOCKER_VERSION - .\rr -v - - - name: Prepared - run: | - echo "test_prepared=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - - name: Test - if: ${{ env.test_prepared && always() }} - run: composer test - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: composer test-fpm - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: composer test-workerman-gateway-w - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: composer test-roadrunner - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: composer test-jwt - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: composer test-snowflake - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: composer test-connection-center-common - - name: Test database - if: ${{ env.test_prepared && always() }} - run: composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: composer test-model - - name: Print logs - if: failure() - run: php .github\print-logs.php +# ci-macos: +# name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} +# runs-on: macos-latest +# strategy: +# fail-fast: false +# matrix: +# php: ["8.1", "8.2"] +# swoole: [v5.1.0, v5.0.3] +# roadrunner: [2.7.*] +# env: +# MYSQL_SERVER_PASSWORD: "root" +# PHP_VERSION: ${{ matrix.php }} +# IMI_TEST_AMQP_SERVER_UTIL: 0 +# IMI_ROADRUNNER_BINARY: ${{ github.workspace }}/rr +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} +# steps: +# - name: Checkout +# uses: actions/checkout@v4 +# - name: Setup MySQL +# uses: shogo82148/actions-setup-mysql@v1 +# with: +# mysql-version: "8.0" +# root-password: root +# my-cnf: | +# socket=/tmp/mysql.sock +# - name: Setup Redis +# uses: shogo82148/actions-setup-redis@v1 +# with: +# redis-version: "6.x" +# - name: Get Openssl Dir +# id: opecssl-dir +# run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT +# - name: Setup PHP +# uses: shivammathur/setup-php@v2 +# with: +# php-version: ${{ matrix.php }} +# tools: pecl +# extensions: > +# apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, zip, :opcache, +# swoole-swoole/swoole-src@${{ matrix.swoole }} +# env: +# SWOOLE_CONFIGURE_OPTS: > +# --enable-openssl +# --with-openssl-dir=${{ steps.opecssl-dir.outputs.path }} +# --enable-http2 +# --enable-mysqlnd +# --enable-swoole-json +# --enable-swoole-curl +# - name: Check Version +# run: | +# php -v +# php -m +# composer -V +# php --ri swoole +# - name: Get composer cache directory +# id: composer-cache +# run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT +# - name: Cache dependencies +# uses: actions/cache@v3 +# with: +# path: ${{ steps.composer-cache.outputs.dir }} +# key: ${{ runner.os }}-composer-${{ env.php-versions }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} +# restore-keys: | +# ${{ runner.os }}-composer-${{ env.php-versions }}- +# ${{ runner.os }}-composer- +# - name: Prepare +# run: | +# echo "::group::Env prepare" +# mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' +# echo "::endgroup::" +# echo "::group::Composer install" +# composer update --prefer-dist --no-progress +# echo "::endgroup::" +# echo "::group::Table Init" +# tests/db/install-db.sh +# echo "::endgroup::" +# +# - name: Install RoadRunner +# run: | +# echo no | src/Components/roadrunner/vendor/bin/rr get-binary -f $ROADRUNNER_DOCKER_VERSION +# ./rr -v +# +# - name: Prepared +# run: | +# echo "test_prepared=1" >> $GITHUB_ENV +# +# - name: Test +# if: ${{ env.test_prepared && always() }} +# run: composer test +# - name: Test swoole +# if: ${{ env.test_prepared && always() }} +# run: composer test-swoole +# - name: Test workerman +# if: ${{ env.test_prepared && always() }} +# run: composer test-workerman +# - name: Test workerman-gateway +# if: ${{ env.test_prepared && always() }} +# run: composer test-workerman-gateway +# - name: Test roadrunner +# if: ${{ env.test_prepared && always() }} +# run: composer test-roadrunner +# - name: Test fpm +# if: ${{ env.test_prepared && always() }} +# run: composer test-fpm +# - name: Test jwt +# if: ${{ env.test_prepared && always() }} +# run: composer test-jwt +# - name: Test queue +# if: ${{ env.test_prepared && always() }} +# run: composer test-queue +# - name: Test grpc +# if: ${{ env.test_prepared && always() }} +# run: composer test-grpc +# - name: Test snowflake +# if: ${{ env.test_prepared && always() }} +# run: composer test-snowflake +# - name: Test mqtt +# if: ${{ env.test_prepared && always() }} +# run: composer test-mqtt +# - name: Test smarty +# if: ${{ env.test_prepared && always() }} +# run: composer test-smarty +# - name: Test phar +# if: ${{ env.test_prepared && always() }} +# run: composer test-phar +# - name: Test connection-center +# if: ${{ env.test_prepared && always() }} +# run: composer test-connection-center +# - name: Test database +# if: ${{ env.test_prepared && always() }} +# run: composer test-database +# - name: Test model +# if: ${{ env.test_prepared && always() }} +# run: composer test-model +# - name: Print logs +# if: failure() +# run: php .github/print-logs.php +# +# ci-windows: +# name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} +# runs-on: windows-latest +# strategy: +# fail-fast: false +# matrix: +# php: ["8.1"] # 部分扩展还未在 pecl 发布 PHP 8.2 Windows 版扩展,所以无法测试 +# roadrunner: [2.7.*] +# extensions: +# [ +# "apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, :opcache", +# ] +# env: +# IMI_ROADRUNNER_BINARY: ${{ github.workspace }}\rr.exe +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} +# +# steps: +# - uses: actions/checkout@v4 +# +# - name: Setup MySQL +# uses: shogo82148/actions-setup-mysql@v1 +# with: +# mysql-version: "8.0" +# root-password: root +# +# - name: Setup Redis-server +# run: | +# nuget install redis-64 -excludeversion +# redis-64\tools\redis-server.exe --service-install +# redis-64\tools\redis-server.exe --service-start +# '@ECHO Redis Started' +# +# - name: Setup PHP +# uses: shivammathur/setup-php@v2 +# with: +# php-version: ${{ matrix.php }} +# ini-values: session.save_path=C:\temp +# tools: pecl +# extensions: ${{ matrix.extensions }} +# env: +# fail-fast: true +# +# - name: Get composer cache directory +# id: composer-cache +# shell: pwsh +# run: | +# Set-Variable -Name CacheDir -Value (composer config cache-files-dir) +# "dir=$CacheDir" >> $env:GITHUB_OUTPUT +# +# - name: Cache dependencies +# uses: actions/cache@v3 +# with: +# path: ${{ steps.composer-cache.outputs.dir }} +# key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} +# restore-keys: | +# ${{ runner.os }}-composer-${{ matrix.php }}- +# ${{ runner.os }}-composer- +# +# - name: Prepare +# run: | +# Write-Output "::group::Env prepare" +# mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' +# Write-Output "::endgroup::" +# Write-Output "::group::Composer install" +# composer update --prefer-dist --no-progress +# Write-Output "::endgroup::" +# Write-Output "::group::Table Init" +# php src\Cli\bin\imi-cli generate/table --app-namespace "Imi\Model\Test" +# Write-Output "::endgroup::" +# +# - name: Install RoadRunner +# run: | +# echo no | src\Components\roadrunner\vendor\bin\rr get-binary -f $env:ROADRUNNER_DOCKER_VERSION +# .\rr -v +# +# - name: Prepared +# run: | +# echo "test_prepared=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append +# +# - name: Test +# if: ${{ env.test_prepared && always() }} +# run: composer test +# - name: Test fpm +# if: ${{ env.test_prepared && always() }} +# run: composer test-fpm +# - name: Test workerman +# if: ${{ env.test_prepared && always() }} +# run: composer test-workerman +# - name: Test workerman-gateway +# if: ${{ env.test_prepared && always() }} +# run: composer test-workerman-gateway-w +# - name: Test roadrunner +# if: ${{ env.test_prepared && always() }} +# run: composer test-roadrunner +# - name: Test jwt +# if: ${{ env.test_prepared && always() }} +# run: composer test-jwt +# - name: Test snowflake +# if: ${{ env.test_prepared && always() }} +# run: composer test-snowflake +# - name: Test connection-center +# if: ${{ env.test_prepared && always() }} +# run: composer test-connection-center-common +# - name: Test database +# if: ${{ env.test_prepared && always() }} +# run: composer test-database +# - name: Test model +# if: ${{ env.test_prepared && always() }} +# run: composer test-model +# - name: Print logs +# if: failure() +# run: php .github\print-logs.php diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index eb035c96a6..6098445054 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,6 +22,7 @@ env: jobs: test: runs-on: ubuntu-latest + if: false strategy: matrix: testType: [core, swoole, components] From 0ae42c3ae7852f8f1b8c5c25b008db72d5630361 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 12:57:27 +0800 Subject: [PATCH 06/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/amqp/composer.json | 1 + src/Components/grpc/composer.json | 1 + src/Components/kafka/composer.json | 1 + src/Components/mqtt/composer.json | 3 ++- src/Components/queue/composer.json | 1 + src/Components/snowflake/composer.json | 3 ++- src/Components/swoole/composer.json | 1 + 7 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Components/amqp/composer.json b/src/Components/amqp/composer.json index 32442fc534..798d91ac7e 100644 --- a/src/Components/amqp/composer.json +++ b/src/Components/amqp/composer.json @@ -23,6 +23,7 @@ "files": [ "../../../vendor/autoload.php", "../../../dev/try-include-swoole.php", + "../redis/vendor/autoload.php", "../workerman/vendor/autoload.php", "../queue/vendor/autoload.php" ] diff --git a/src/Components/grpc/composer.json b/src/Components/grpc/composer.json index 0cb4c0548e..a8fa30cd35 100644 --- a/src/Components/grpc/composer.json +++ b/src/Components/grpc/composer.json @@ -25,6 +25,7 @@ "files": [ "../../../vendor/autoload.php", "../../../dev/try-include-swoole.php", + "../redis/vendor/autoload.php", "../rpc/vendor/autoload.php" ] }, diff --git a/src/Components/kafka/composer.json b/src/Components/kafka/composer.json index 4780a43b94..3014e94c69 100644 --- a/src/Components/kafka/composer.json +++ b/src/Components/kafka/composer.json @@ -23,6 +23,7 @@ "files": [ "../../../vendor/autoload.php", "../../../dev/try-include-swoole.php", + "../redis/vendor/autoload.php", "../workerman/vendor/autoload.php", "../queue/vendor/autoload.php" ] diff --git a/src/Components/mqtt/composer.json b/src/Components/mqtt/composer.json index 183a107bca..c15b68d6fc 100644 --- a/src/Components/mqtt/composer.json +++ b/src/Components/mqtt/composer.json @@ -22,7 +22,8 @@ }, "files": [ "../../../vendor/autoload.php", - "../../../dev/try-include-swoole.php" + "../../../dev/try-include-swoole.php", + "../redis/vendor/autoload.php" ] }, "scripts": { diff --git a/src/Components/queue/composer.json b/src/Components/queue/composer.json index 265eeb422a..288767f358 100644 --- a/src/Components/queue/composer.json +++ b/src/Components/queue/composer.json @@ -20,6 +20,7 @@ "files": [ "../../../vendor/autoload.php", "../../../dev/try-include-swoole.php", + "../redis/vendor/autoload.php", "../workerman/vendor/autoload.php" ] }, diff --git a/src/Components/snowflake/composer.json b/src/Components/snowflake/composer.json index ee1d2912db..f613ed29c2 100644 --- a/src/Components/snowflake/composer.json +++ b/src/Components/snowflake/composer.json @@ -18,7 +18,8 @@ }, "files": [ "../../../vendor/autoload.php", - "../database/vendor/autoload.php" + "../database/vendor/autoload.php", + "../redis/vendor/autoload.php" ] }, "scripts": {}, diff --git a/src/Components/swoole/composer.json b/src/Components/swoole/composer.json index 368152be07..6202731667 100644 --- a/src/Components/swoole/composer.json +++ b/src/Components/swoole/composer.json @@ -25,6 +25,7 @@ }, "files": [ "../../../vendor/autoload.php", + "../redis/vendor/autoload.php", "../amqp/vendor/autoload.php" ] }, From b819a9fdb379587216ba7dc158a36c48d0202cc7 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 16 Feb 2024 13:01:53 +0800 Subject: [PATCH 07/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D&=E6=94=B9?= =?UTF-8?q?=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/model/src/RedisModel.php | 2 +- src/Components/redis/src/Connector/PhpRedisConnector.php | 4 ++-- src/Components/redis/src/RedisManager.php | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index 7be292d252..ce6788cc86 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -674,7 +674,7 @@ public function __getMember(): string */ public static function __getRedis(?self $redisModel = null): RedisHandler { - $annotation = static::__getRedisEntity($redisModel ?? static::class, false); + $annotation = static::__getRedisEntity($redisModel ?? static::class); $redis = RedisManager::getInstance($annotation->poolName); if (null !== $annotation->db) { diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index 92431020c0..a55072c08c 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -26,11 +26,11 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler { $redis->connect($host, $config->port, $config->timeout); } - if (('' !== $config->password) && !$redis->auth($config->password)) + if (('' !== $config->password) && !$redis->auth($config->password) && null !== $redis->getLastError()) { throw new \RedisException($redis->getLastError()); } - if (null !== $config->database && !$redis->select($config->database)) + if (null !== $config->database && !$redis->select($config->database) && null !== $redis->getLastError()) { throw new \RedisException($redis->getLastError()); } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index f2813262a5..9c30e16d7b 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -98,10 +98,7 @@ public static function release(IRedisHandler $redis): void { throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); } - if (ConnectionStatus::WaitRelease === $connection->getStatus()) - { - $connection->getManager()->releaseConnection($connection); - } + $connection->release(); self::unsetConnectionInstance($redis); } From a2217a74f9fd9365d0327d9c20386f0cedc893af Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 16:03:27 +0800 Subject: [PATCH 08/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=20reset=20?= =?UTF-8?q?=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PhpRedisConnector.php | 6 +++--- .../redis/src/Connector/PredisConnector.php | 15 ++++++--------- .../redis/src/Connector/RedisConnectionDriver.php | 7 +++++++ .../redis/src/Connector/RedisDriverConfig.php | 4 ++-- .../redis/src/Handler/AbstractRedisHandler.php | 9 +++++++++ .../redis/src/Handler/IRedisHandler.php | 2 ++ .../redis/src/Handler/PhpRedisClusterHandler.php | 7 +++---- .../redis/src/Handler/PhpRedisHandler.php | 2 ++ .../redis/src/Handler/PredisClusterHandler.php | 4 +++- .../redis/src/Handler/PredisHandler.php | 4 +++- src/Components/redis/src/RedisManager.php | 1 - src/Components/redis/src/Traits/TPredisMethod.php | 2 +- 12 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index a55072c08c..7fec833398 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -30,14 +30,14 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler { throw new \RedisException($redis->getLastError()); } - if (null !== $config->database && !$redis->select($config->database) && null !== $redis->getLastError()) + if (!$redis->select($config->database) && null !== $redis->getLastError()) { throw new \RedisException($redis->getLastError()); } self::applyOptions($redis, $config); - return new PhpRedisHandler($redis); + return new PhpRedisHandler($redis, $config); } public static function connectCluster(RedisDriverConfig $config): PhpRedisClusterHandler @@ -51,7 +51,7 @@ public static function connectCluster(RedisDriverConfig $config): PhpRedisCluste self::applyOptions($redis, $config); - return new PhpRedisClusterHandler($redis); + return new PhpRedisClusterHandler($redis, $config); } protected static function applyOptions(\Redis|\RedisCluster $redis, RedisDriverConfig $config): void diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index bb0b7293c8..4603eca083 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -15,18 +15,15 @@ class PredisConnector implements IRedisConnector public static function connect(RedisDriverConfig $config): PredisHandler { $params = [ - 'scheme' => 'tcp', - 'host' => $config->host, - 'port' => $config->port, + 'scheme' => 'tcp', + 'host' => $config->host, + 'port' => $config->port, + 'database' => $config->database, ]; if ($config->password) { $params['password'] = $config->password; } - if (null !== $config->database) - { - $params['database'] = $config->database; - } if ($config->prefix) { $params['prefix'] = $config->prefix; @@ -34,7 +31,7 @@ public static function connect(RedisDriverConfig $config): PredisHandler $client = new \Predis\Client($params); $client->connect(); - return new PredisHandler($client); + return new PredisHandler($client, $config); } public static function connectCluster(RedisDriverConfig $config): PredisClusterHandler @@ -58,6 +55,6 @@ public static function connectCluster(RedisDriverConfig $config): PredisClusterH $client = new \Predis\Client($seeds, $options); $client->connect(); - return new PredisClusterHandler($client); + return new PredisClusterHandler($client, $config); } } diff --git a/src/Components/redis/src/Connector/RedisConnectionDriver.php b/src/Components/redis/src/Connector/RedisConnectionDriver.php index af5cdfa825..83545f4a51 100644 --- a/src/Components/redis/src/Connector/RedisConnectionDriver.php +++ b/src/Components/redis/src/Connector/RedisConnectionDriver.php @@ -58,6 +58,13 @@ public function close(object $instance): void */ public function reset(object $instance): void { + if ( + !$instance->isCluster() + && $instance->isConnected() + && ($db = $instance->getConnectionConfig()->database) !== $instance->getDBNum() + ) { + $instance->select($db); + } } /** diff --git a/src/Components/redis/src/Connector/RedisDriverConfig.php b/src/Components/redis/src/Connector/RedisDriverConfig.php index ec07fbd45b..f5308ab131 100644 --- a/src/Components/redis/src/Connector/RedisDriverConfig.php +++ b/src/Components/redis/src/Connector/RedisDriverConfig.php @@ -16,7 +16,7 @@ public function __construct( public readonly ?int $port, public readonly ?array $seeds, public readonly ?string $password, - public readonly ?int $database, + public readonly int $database, public readonly string $prefix, public readonly float $timeout, public readonly float $readTimeout, @@ -36,7 +36,7 @@ protected static function __create(array $config): self port: (int) ($config['port'] ?? 6379), seeds: $config['seeds'] ?? null, password: $config['password'] ?? null, - database: \array_key_exists('database', $config) ? $config['database'] : 0, + database: $config['database'] ?? 0, prefix: $config['prefix'] ?? '', timeout: (float) ($config['timeout'] ?? 3.0), readTimeout: (float) ($config['readTimeout'] ?? 3.0), diff --git a/src/Components/redis/src/Handler/AbstractRedisHandler.php b/src/Components/redis/src/Handler/AbstractRedisHandler.php index e8f61c89f7..55802bd020 100644 --- a/src/Components/redis/src/Handler/AbstractRedisHandler.php +++ b/src/Components/redis/src/Handler/AbstractRedisHandler.php @@ -4,12 +4,21 @@ namespace Imi\Redis\Handler; +use Imi\Redis\Connector\RedisDriverConfig; + abstract class AbstractRedisHandler implements IRedisScanExMethod { + protected RedisDriverConfig $config; + abstract public function isConnected(): bool; public function isCluster(): bool { return $this instanceof IRedisClusterHandler; } + + public function getConnectionConfig(): RedisDriverConfig + { + return $this->config; + } } diff --git a/src/Components/redis/src/Handler/IRedisHandler.php b/src/Components/redis/src/Handler/IRedisHandler.php index 40fcb94699..624c35984b 100644 --- a/src/Components/redis/src/Handler/IRedisHandler.php +++ b/src/Components/redis/src/Handler/IRedisHandler.php @@ -8,5 +8,7 @@ interface IRedisHandler { public function getInstance(): object; + public function isCluster(): bool; + public function isSupportSerialize(): bool; } diff --git a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php index ab9ded278b..875c905b51 100644 --- a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php @@ -4,6 +4,7 @@ namespace Imi\Redis\Handler; +use Imi\Redis\Connector\RedisDriverConfig; use Imi\Redis\Traits\TPhpRedisMethod; use RedisCluster; @@ -14,12 +15,10 @@ class PhpRedisClusterHandler extends AbstractRedisHandler implements IRedisClust { use TPhpRedisMethod; - protected \RedisCluster $client; - public function __construct( - \RedisCluster $client, + protected \RedisCluster $client, + protected RedisDriverConfig $config, ) { - $this->client = $client; } public function getInstance(): \RedisCluster diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php index 0680a27327..a670641980 100644 --- a/src/Components/redis/src/Handler/PhpRedisHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -4,6 +4,7 @@ namespace Imi\Redis\Handler; +use Imi\Redis\Connector\RedisDriverConfig; use Imi\Redis\Traits\TPhpRedisMethod; use Redis; @@ -16,6 +17,7 @@ class PhpRedisHandler extends AbstractRedisHandler implements IRedisHandler public function __construct( protected \Redis $client, + protected RedisDriverConfig $config, ) { } diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php index 6622bacbc9..281430a15c 100644 --- a/src/Components/redis/src/Handler/PredisClusterHandler.php +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -4,6 +4,7 @@ namespace Imi\Redis\Handler; +use Imi\Redis\Connector\RedisDriverConfig; use Imi\Redis\Traits\TPredisMethod; use Predis\Client; use Predis\Connection\Cluster\RedisCluster; @@ -16,7 +17,8 @@ class PredisClusterHandler extends AbstractRedisHandler implements IRedisCluster use TPredisMethod; public function __construct( - private Client $client, + protected Client $client, + protected RedisDriverConfig $config, ) { } diff --git a/src/Components/redis/src/Handler/PredisHandler.php b/src/Components/redis/src/Handler/PredisHandler.php index 77b2d7e29b..2b57bdddf1 100644 --- a/src/Components/redis/src/Handler/PredisHandler.php +++ b/src/Components/redis/src/Handler/PredisHandler.php @@ -4,6 +4,7 @@ namespace Imi\Redis\Handler; +use Imi\Redis\Connector\RedisDriverConfig; use Imi\Redis\Traits\TPredisMethod; use Predis\Client; @@ -15,7 +16,8 @@ class PredisHandler extends AbstractRedisHandler implements IRedisHandler use TPredisMethod; public function __construct( - private Client $client, + protected Client $client, + protected RedisDriverConfig $config, ) { } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index 9c30e16d7b..7ddc73cc4f 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -6,7 +6,6 @@ use Imi\Config; use Imi\ConnectionCenter\Contract\IConnection; -use Imi\ConnectionCenter\Enum\ConnectionStatus; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Redis\Handler\IRedisHandler; diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php index 0251f5dfb4..ada546c1e2 100644 --- a/src/Components/redis/src/Traits/TPredisMethod.php +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -8,7 +8,7 @@ trait TPredisMethod { - public function getDBNum() + public function getDBNum(): int { // 不建议使用,性能差 if ($this->isCluster()) From 9186239336fc842075debef987c5ac6639cbcd8d Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 16:13:04 +0800 Subject: [PATCH 09/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/amqp/example/config/config.php | 6 ++-- .../kafka/example/config/config.php | 2 +- .../tests/unit/AppServer/config/config.php | 31 ++++++++++++++----- .../ChannelServerUtilServer/config/config.php | 30 +++++++++++++----- tests/unit/Component/config/config.php | 2 -- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/Components/amqp/example/config/config.php b/src/Components/amqp/example/config/config.php index 510ae29559..a1cd5ee2c9 100644 --- a/src/Components/amqp/example/config/config.php +++ b/src/Components/amqp/example/config/config.php @@ -87,9 +87,9 @@ ] : [], // 连接中心配置 - 'connectionCenter' => Imi::checkAppType('swoole') ? [ + 'connectionCenter' => [ 'redis' => [ - 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, 'pool' => [ 'maxResources' => 10, 'minResources' => 0, @@ -108,7 +108,7 @@ ], ], ], - ] : [], + ], // redis 配置 'redis' => [ diff --git a/src/Components/kafka/example/config/config.php b/src/Components/kafka/example/config/config.php index 0aff0d9af3..9670f29cab 100644 --- a/src/Components/kafka/example/config/config.php +++ b/src/Components/kafka/example/config/config.php @@ -84,7 +84,7 @@ // 连接中心配置 'connectionCenter' => [ 'redis' => [ - 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, 'pool' => [ 'maxResources' => 10, 'minResources' => 0, diff --git a/src/Components/workerman/tests/unit/AppServer/config/config.php b/src/Components/workerman/tests/unit/AppServer/config/config.php index ebbd5ccc97..e22e7e275d 100644 --- a/src/Components/workerman/tests/unit/AppServer/config/config.php +++ b/src/Components/workerman/tests/unit/AppServer/config/config.php @@ -135,18 +135,33 @@ ], ], + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // redis 配置 'redis' => [ // 默认连接池名 'defaultPool' => 'redis', - 'connections' => [ - 'redis' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - 'heartbeatInterval' => 30, - ], - ], ], // 锁 diff --git a/src/Components/workerman/tests/unit/ChannelServerUtilServer/config/config.php b/src/Components/workerman/tests/unit/ChannelServerUtilServer/config/config.php index 6717197e9d..24f7027904 100644 --- a/src/Components/workerman/tests/unit/ChannelServerUtilServer/config/config.php +++ b/src/Components/workerman/tests/unit/ChannelServerUtilServer/config/config.php @@ -103,17 +103,33 @@ 'defaultPool' => 'maindb', ], + 'connectionCenter' => [ + 'redis' => [ + 'manager' => \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class, + 'pool' => [ + 'maxResources' => 10, + 'minResources' => 0, + ], + 'config' => [ + 'driver' => \Imi\Redis\Connector\RedisConnectionDriver::class, + 'resources' => [ + [ + 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), + 'port' => env('REDIS_SERVER_PORT', 6379), + 'password' => env('REDIS_SERVER_PASSWORD'), + + 'client' => 'phpredis', + 'mode' => \Imi\Redis\Enum\RedisMode::Standalone, + ], + ], + ], + ], + ], + // redis 配置 'redis' => [ // 默认连接池名 'defaultPool' => 'redis', - 'connections' => [ - 'redis' => [ - 'host' => env('REDIS_SERVER_HOST', '127.0.0.1'), - 'port' => env('REDIS_SERVER_PORT', 6379), - 'password' => env('REDIS_SERVER_PASSWORD'), - ], - ], ], // 锁 diff --git a/tests/unit/Component/config/config.php b/tests/unit/Component/config/config.php index d0c8ebf0de..e5ea161ba8 100644 --- a/tests/unit/Component/config/config.php +++ b/tests/unit/Component/config/config.php @@ -131,8 +131,6 @@ 'redis' => [ // 默认连接池名 'defaultPool' => 'redis_test', - 'connections' => [ - ], ], // 连接中心配置 From 6dc094557581608d306a27c9840ebaa25dd3acde Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 17:14:39 +0800 Subject: [PATCH 10/97] =?UTF-8?q?Update:=20=E5=B0=9D=E8=AF=95=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=B5=8C=E5=A5=97=E9=87=8A=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/RedisManager.php | 29 ++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index 7ddc73cc4f..a9d8af80f1 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -6,6 +6,7 @@ use Imi\Config; use Imi\ConnectionCenter\Contract\IConnection; +use Imi\ConnectionCenter\Enum\ConnectionStatus; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Redis\Handler\IRedisHandler; @@ -74,17 +75,32 @@ protected static function recordInstanceLinkPool(IRedisHandler $handler, IConnec self::$instanceLinkConnectionMap = new \WeakMap(); } - self::$instanceLinkConnectionMap[$handler] = $connection; + $ref = self::$instanceLinkConnectionMap[$handler] ?? new \stdClass(); + $ref->connection = $connection; + $ref->count = ($ref->count ?? 0) + 1; + + self::$instanceLinkConnectionMap[$handler] = $ref; } protected static function getConnectionByInstance(IRedisHandler $handler): ?IConnection { - return self::$instanceLinkConnectionMap[$handler] ?? null; + return (self::$instanceLinkConnectionMap[$handler] ?? null)?->connection; } - protected static function unsetConnectionInstance(IRedisHandler $handler): void + protected static function unsetConnectionInstance(IRedisHandler $handler): bool { - unset(self::$instanceLinkConnectionMap[$handler]); + /** @var null|object $ref */ + $ref = self::$instanceLinkConnectionMap[$handler] ?? null; + if (null !== $ref) { + return true; + } + if ($ref->count > 1) { + $ref->count--; + return false; + } else { + unset(self::$instanceLinkConnectionMap[$handler]); + return true; + } } /** @@ -97,8 +113,9 @@ public static function release(IRedisHandler $redis): void { throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); } - $connection->release(); - self::unsetConnectionInstance($redis); + if (self::unsetConnectionInstance($redis)) { + ConnectionStatus::Available === $connection->getStatus() && $connection->release(); + } } /** From 2c7a3a1c06d495bd2575ac1c907a39fe3a5149d1 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 17:16:49 +0800 Subject: [PATCH 11/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/amqp/example/config/config.php | 2 +- .../kafka/example/config/config.php | 2 +- src/Components/redis/src/RedisManager.php | 19 +++++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Components/amqp/example/config/config.php b/src/Components/amqp/example/config/config.php index a1cd5ee2c9..db3e7e6cc6 100644 --- a/src/Components/amqp/example/config/config.php +++ b/src/Components/amqp/example/config/config.php @@ -89,7 +89,7 @@ // 连接中心配置 'connectionCenter' => [ 'redis' => [ - 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, 'pool' => [ 'maxResources' => 10, 'minResources' => 0, diff --git a/src/Components/kafka/example/config/config.php b/src/Components/kafka/example/config/config.php index 9670f29cab..25b9c5e302 100644 --- a/src/Components/kafka/example/config/config.php +++ b/src/Components/kafka/example/config/config.php @@ -84,7 +84,7 @@ // 连接中心配置 'connectionCenter' => [ 'redis' => [ - 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, + 'manager' => Imi::checkAppType('swoole') ? \Imi\ConnectionCenter\Handler\Pool\PoolConnectionManager::class : \Imi\ConnectionCenter\Handler\Singleton\SingletonConnectionManager::class, 'pool' => [ 'maxResources' => 10, 'minResources' => 0, diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index a9d8af80f1..ec93fa9d22 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -89,16 +89,22 @@ protected static function getConnectionByInstance(IRedisHandler $handler): ?ICon protected static function unsetConnectionInstance(IRedisHandler $handler): bool { - /** @var null|object $ref */ + /** @var object|null $ref */ $ref = self::$instanceLinkConnectionMap[$handler] ?? null; - if (null !== $ref) { + if (null !== $ref) + { return true; } - if ($ref->count > 1) { - $ref->count--; + if ($ref->count > 1) + { + --$ref->count; + return false; - } else { + } + else + { unset(self::$instanceLinkConnectionMap[$handler]); + return true; } } @@ -113,7 +119,8 @@ public static function release(IRedisHandler $redis): void { throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); } - if (self::unsetConnectionInstance($redis)) { + if (self::unsetConnectionInstance($redis)) + { ConnectionStatus::Available === $connection->getStatus() && $connection->release(); } } From 0fcb6d03015aab3ea0f14f3dc921ab56b15a03c7 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 17:28:23 +0800 Subject: [PATCH 12/97] =?UTF-8?q?Update:=20=E6=81=A2=E5=A4=8D=E6=9B=B4?= =?UTF-8?q?=E5=A4=9A=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 504 +++++++++++++++++++-------------------- 1 file changed, 252 insertions(+), 252 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28bb08d0e6..a5daec1c73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -322,255 +322,255 @@ jobs: if: failure() run: php .github/print-logs.php -# ci-macos: -# name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} -# runs-on: macos-latest -# strategy: -# fail-fast: false -# matrix: -# php: ["8.1", "8.2"] -# swoole: [v5.1.0, v5.0.3] -# roadrunner: [2.7.*] -# env: -# MYSQL_SERVER_PASSWORD: "root" -# PHP_VERSION: ${{ matrix.php }} -# IMI_TEST_AMQP_SERVER_UTIL: 0 -# IMI_ROADRUNNER_BINARY: ${{ github.workspace }}/rr -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} -# steps: -# - name: Checkout -# uses: actions/checkout@v4 -# - name: Setup MySQL -# uses: shogo82148/actions-setup-mysql@v1 -# with: -# mysql-version: "8.0" -# root-password: root -# my-cnf: | -# socket=/tmp/mysql.sock -# - name: Setup Redis -# uses: shogo82148/actions-setup-redis@v1 -# with: -# redis-version: "6.x" -# - name: Get Openssl Dir -# id: opecssl-dir -# run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT -# - name: Setup PHP -# uses: shivammathur/setup-php@v2 -# with: -# php-version: ${{ matrix.php }} -# tools: pecl -# extensions: > -# apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, zip, :opcache, -# swoole-swoole/swoole-src@${{ matrix.swoole }} -# env: -# SWOOLE_CONFIGURE_OPTS: > -# --enable-openssl -# --with-openssl-dir=${{ steps.opecssl-dir.outputs.path }} -# --enable-http2 -# --enable-mysqlnd -# --enable-swoole-json -# --enable-swoole-curl -# - name: Check Version -# run: | -# php -v -# php -m -# composer -V -# php --ri swoole -# - name: Get composer cache directory -# id: composer-cache -# run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT -# - name: Cache dependencies -# uses: actions/cache@v3 -# with: -# path: ${{ steps.composer-cache.outputs.dir }} -# key: ${{ runner.os }}-composer-${{ env.php-versions }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} -# restore-keys: | -# ${{ runner.os }}-composer-${{ env.php-versions }}- -# ${{ runner.os }}-composer- -# - name: Prepare -# run: | -# echo "::group::Env prepare" -# mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' -# echo "::endgroup::" -# echo "::group::Composer install" -# composer update --prefer-dist --no-progress -# echo "::endgroup::" -# echo "::group::Table Init" -# tests/db/install-db.sh -# echo "::endgroup::" -# -# - name: Install RoadRunner -# run: | -# echo no | src/Components/roadrunner/vendor/bin/rr get-binary -f $ROADRUNNER_DOCKER_VERSION -# ./rr -v -# -# - name: Prepared -# run: | -# echo "test_prepared=1" >> $GITHUB_ENV -# -# - name: Test -# if: ${{ env.test_prepared && always() }} -# run: composer test -# - name: Test swoole -# if: ${{ env.test_prepared && always() }} -# run: composer test-swoole -# - name: Test workerman -# if: ${{ env.test_prepared && always() }} -# run: composer test-workerman -# - name: Test workerman-gateway -# if: ${{ env.test_prepared && always() }} -# run: composer test-workerman-gateway -# - name: Test roadrunner -# if: ${{ env.test_prepared && always() }} -# run: composer test-roadrunner -# - name: Test fpm -# if: ${{ env.test_prepared && always() }} -# run: composer test-fpm -# - name: Test jwt -# if: ${{ env.test_prepared && always() }} -# run: composer test-jwt -# - name: Test queue -# if: ${{ env.test_prepared && always() }} -# run: composer test-queue -# - name: Test grpc -# if: ${{ env.test_prepared && always() }} -# run: composer test-grpc -# - name: Test snowflake -# if: ${{ env.test_prepared && always() }} -# run: composer test-snowflake -# - name: Test mqtt -# if: ${{ env.test_prepared && always() }} -# run: composer test-mqtt -# - name: Test smarty -# if: ${{ env.test_prepared && always() }} -# run: composer test-smarty -# - name: Test phar -# if: ${{ env.test_prepared && always() }} -# run: composer test-phar -# - name: Test connection-center -# if: ${{ env.test_prepared && always() }} -# run: composer test-connection-center -# - name: Test database -# if: ${{ env.test_prepared && always() }} -# run: composer test-database -# - name: Test model -# if: ${{ env.test_prepared && always() }} -# run: composer test-model -# - name: Print logs -# if: failure() -# run: php .github/print-logs.php -# -# ci-windows: -# name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} -# runs-on: windows-latest -# strategy: -# fail-fast: false -# matrix: -# php: ["8.1"] # 部分扩展还未在 pecl 发布 PHP 8.2 Windows 版扩展,所以无法测试 -# roadrunner: [2.7.*] -# extensions: -# [ -# "apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, :opcache", -# ] -# env: -# IMI_ROADRUNNER_BINARY: ${{ github.workspace }}\rr.exe -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} -# -# steps: -# - uses: actions/checkout@v4 -# -# - name: Setup MySQL -# uses: shogo82148/actions-setup-mysql@v1 -# with: -# mysql-version: "8.0" -# root-password: root -# -# - name: Setup Redis-server -# run: | -# nuget install redis-64 -excludeversion -# redis-64\tools\redis-server.exe --service-install -# redis-64\tools\redis-server.exe --service-start -# '@ECHO Redis Started' -# -# - name: Setup PHP -# uses: shivammathur/setup-php@v2 -# with: -# php-version: ${{ matrix.php }} -# ini-values: session.save_path=C:\temp -# tools: pecl -# extensions: ${{ matrix.extensions }} -# env: -# fail-fast: true -# -# - name: Get composer cache directory -# id: composer-cache -# shell: pwsh -# run: | -# Set-Variable -Name CacheDir -Value (composer config cache-files-dir) -# "dir=$CacheDir" >> $env:GITHUB_OUTPUT -# -# - name: Cache dependencies -# uses: actions/cache@v3 -# with: -# path: ${{ steps.composer-cache.outputs.dir }} -# key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} -# restore-keys: | -# ${{ runner.os }}-composer-${{ matrix.php }}- -# ${{ runner.os }}-composer- -# -# - name: Prepare -# run: | -# Write-Output "::group::Env prepare" -# mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' -# Write-Output "::endgroup::" -# Write-Output "::group::Composer install" -# composer update --prefer-dist --no-progress -# Write-Output "::endgroup::" -# Write-Output "::group::Table Init" -# php src\Cli\bin\imi-cli generate/table --app-namespace "Imi\Model\Test" -# Write-Output "::endgroup::" -# -# - name: Install RoadRunner -# run: | -# echo no | src\Components\roadrunner\vendor\bin\rr get-binary -f $env:ROADRUNNER_DOCKER_VERSION -# .\rr -v -# -# - name: Prepared -# run: | -# echo "test_prepared=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append -# -# - name: Test -# if: ${{ env.test_prepared && always() }} -# run: composer test -# - name: Test fpm -# if: ${{ env.test_prepared && always() }} -# run: composer test-fpm -# - name: Test workerman -# if: ${{ env.test_prepared && always() }} -# run: composer test-workerman -# - name: Test workerman-gateway -# if: ${{ env.test_prepared && always() }} -# run: composer test-workerman-gateway-w -# - name: Test roadrunner -# if: ${{ env.test_prepared && always() }} -# run: composer test-roadrunner -# - name: Test jwt -# if: ${{ env.test_prepared && always() }} -# run: composer test-jwt -# - name: Test snowflake -# if: ${{ env.test_prepared && always() }} -# run: composer test-snowflake -# - name: Test connection-center -# if: ${{ env.test_prepared && always() }} -# run: composer test-connection-center-common -# - name: Test database -# if: ${{ env.test_prepared && always() }} -# run: composer test-database -# - name: Test model -# if: ${{ env.test_prepared && always() }} -# run: composer test-model -# - name: Print logs -# if: failure() -# run: php .github\print-logs.php + ci-macos: + name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + php: ["8.1", "8.2"] + swoole: [v5.1.0, v5.0.3] + roadrunner: [2.7.*] + env: + MYSQL_SERVER_PASSWORD: "root" + PHP_VERSION: ${{ matrix.php }} + IMI_TEST_AMQP_SERVER_UTIL: 0 + IMI_ROADRUNNER_BINARY: ${{ github.workspace }}/rr + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup MySQL + uses: shogo82148/actions-setup-mysql@v1 + with: + mysql-version: "8.0" + root-password: root + my-cnf: | + socket=/tmp/mysql.sock + - name: Setup Redis + uses: shogo82148/actions-setup-redis@v1 + with: + redis-version: "6.x" + - name: Get Openssl Dir + id: opecssl-dir + run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: pecl + extensions: > + apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, zip, :opcache, + swoole-swoole/swoole-src@${{ matrix.swoole }} + env: + SWOOLE_CONFIGURE_OPTS: > + --enable-openssl + --with-openssl-dir=${{ steps.opecssl-dir.outputs.path }} + --enable-http2 + --enable-mysqlnd + --enable-swoole-json + --enable-swoole-curl + - name: Check Version + run: | + php -v + php -m + composer -V + php --ri swoole + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ env.php-versions }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} + restore-keys: | + ${{ runner.os }}-composer-${{ env.php-versions }}- + ${{ runner.os }}-composer- + - name: Prepare + run: | + echo "::group::Env prepare" + mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' + echo "::endgroup::" + echo "::group::Composer install" + composer update --prefer-dist --no-progress + echo "::endgroup::" + echo "::group::Table Init" + tests/db/install-db.sh + echo "::endgroup::" + + - name: Install RoadRunner + run: | + echo no | src/Components/roadrunner/vendor/bin/rr get-binary -f $ROADRUNNER_DOCKER_VERSION + ./rr -v + + - name: Prepared + run: | + echo "test_prepared=1" >> $GITHUB_ENV + + - name: Test + if: ${{ env.test_prepared && always() }} + run: composer test + - name: Test swoole + if: ${{ env.test_prepared && always() }} + run: composer test-swoole + - name: Test workerman + if: ${{ env.test_prepared && always() }} + run: composer test-workerman + - name: Test workerman-gateway + if: ${{ env.test_prepared && always() }} + run: composer test-workerman-gateway + - name: Test roadrunner + if: ${{ env.test_prepared && always() }} + run: composer test-roadrunner + - name: Test fpm + if: ${{ env.test_prepared && always() }} + run: composer test-fpm + - name: Test jwt + if: ${{ env.test_prepared && always() }} + run: composer test-jwt + - name: Test queue + if: ${{ env.test_prepared && always() }} + run: composer test-queue + - name: Test grpc + if: ${{ env.test_prepared && always() }} + run: composer test-grpc + - name: Test snowflake + if: ${{ env.test_prepared && always() }} + run: composer test-snowflake + - name: Test mqtt + if: ${{ env.test_prepared && always() }} + run: composer test-mqtt + - name: Test smarty + if: ${{ env.test_prepared && always() }} + run: composer test-smarty + - name: Test phar + if: ${{ env.test_prepared && always() }} + run: composer test-phar + - name: Test connection-center + if: ${{ env.test_prepared && always() }} + run: composer test-connection-center + - name: Test database + if: ${{ env.test_prepared && always() }} + run: composer test-database + - name: Test model + if: ${{ env.test_prepared && always() }} + run: composer test-model + - name: Print logs + if: failure() + run: php .github/print-logs.php + + ci-windows: + name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + php: ["8.1"] # 部分扩展还未在 pecl 发布 PHP 8.2 Windows 版扩展,所以无法测试 + roadrunner: [2.7.*] + extensions: + [ + "apcu, bcmath, curl, openssl, mbstring, intl, json, redis, mysqli, pdo, pdo_mysql, sockets, :opcache", + ] + env: + IMI_ROADRUNNER_BINARY: ${{ github.workspace }}\rr.exe + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} + + steps: + - uses: actions/checkout@v4 + + - name: Setup MySQL + uses: shogo82148/actions-setup-mysql@v1 + with: + mysql-version: "8.0" + root-password: root + + - name: Setup Redis-server + run: | + nuget install redis-64 -excludeversion + redis-64\tools\redis-server.exe --service-install + redis-64\tools\redis-server.exe --service-start + '@ECHO Redis Started' + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: session.save_path=C:\temp + tools: pecl + extensions: ${{ matrix.extensions }} + env: + fail-fast: true + + - name: Get composer cache directory + id: composer-cache + shell: pwsh + run: | + Set-Variable -Name CacheDir -Value (composer config cache-files-dir) + "dir=$CacheDir" >> $env:GITHUB_OUTPUT + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.php }}- + ${{ runner.os }}-composer- + + - name: Prepare + run: | + Write-Output "::group::Env prepare" + mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS db_imi_test;' + Write-Output "::endgroup::" + Write-Output "::group::Composer install" + composer update --prefer-dist --no-progress + Write-Output "::endgroup::" + Write-Output "::group::Table Init" + php src\Cli\bin\imi-cli generate/table --app-namespace "Imi\Model\Test" + Write-Output "::endgroup::" + + - name: Install RoadRunner + run: | + echo no | src\Components\roadrunner\vendor\bin\rr get-binary -f $env:ROADRUNNER_DOCKER_VERSION + .\rr -v + + - name: Prepared + run: | + echo "test_prepared=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Test + if: ${{ env.test_prepared && always() }} + run: composer test + - name: Test fpm + if: ${{ env.test_prepared && always() }} + run: composer test-fpm + - name: Test workerman + if: ${{ env.test_prepared && always() }} + run: composer test-workerman + - name: Test workerman-gateway + if: ${{ env.test_prepared && always() }} + run: composer test-workerman-gateway-w + - name: Test roadrunner + if: ${{ env.test_prepared && always() }} + run: composer test-roadrunner + - name: Test jwt + if: ${{ env.test_prepared && always() }} + run: composer test-jwt + - name: Test snowflake + if: ${{ env.test_prepared && always() }} + run: composer test-snowflake + - name: Test connection-center + if: ${{ env.test_prepared && always() }} + run: composer test-connection-center-common + - name: Test database + if: ${{ env.test_prepared && always() }} + run: composer test-database + - name: Test model + if: ${{ env.test_prepared && always() }} + run: composer test-model + - name: Print logs + if: failure() + run: php .github\print-logs.php From 99a2be503e2d7a9e441b56703b24c8ed39f8b0a4 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 17:32:13 +0800 Subject: [PATCH 13/97] =?UTF-8?q?Update:=20=E6=9A=82=E6=97=B6=E5=87=8F?= =?UTF-8?q?=E5=B0=91=E6=B5=8B=E8=AF=95=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5daec1c73..23e1b46872 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -328,8 +328,10 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.1", "8.2"] - swoole: [v5.1.0, v5.0.3] +# php: ["8.1", "8.2"] +# swoole: [v5.1.0, v5.0.3] + php: ["8.2"] + swoole: [v5.1.0] roadrunner: [2.7.*] env: MYSQL_SERVER_PASSWORD: "root" From 8800c96ed8ecad4df56b389b4505a15d8a79dd6b Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 17:42:36 +0800 Subject: [PATCH 14/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 04f2356c58..c853291e0d 100644 --- a/composer.json +++ b/composer.json @@ -53,14 +53,16 @@ "files": [ "dev/bootstrap.php", "tests/helper.php", - "src/Components/model/vendor/autoload.php" + "src/Components/model/vendor/autoload.php", + "src/Components/redis/vendor/autoload.php" ] }, "suggest": { "ext-inotify": "高性能热更新支持", "ext-pdo": "数据库操作支持", "symfony/polyfill-uuid": "模型 uuid 发号器依赖", - "ext-uuid": "模型 uuid 发号器依赖" + "ext-uuid": "模型 uuid 发号器依赖", + "ext-redis": "phpredis 客户端依赖" }, "minimum-stability": "dev", "prefer-stable": true, @@ -120,6 +122,7 @@ ], "test-database": "@php vendor/bin/phpunit -c src/Components/database/tests/phpunit.xml", "test-model": "@php vendor/bin/phpunit -c src/Components/model/tests/phpunit.xml", + "test-redis": "@php vendor/bin/phpunit -c src/Components/redis/tests/phpunit.xml", "test-components": [ "@composer test-swoole", "@composer test-workerman", From c01e8898aa5db5cf7f7af784e4b6e62ad47577af Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 18:29:05 +0800 Subject: [PATCH 15/97] =?UTF-8?q?Update:=20=E5=90=AF=E7=94=A8=20redis-clus?= =?UTF-8?q?ter=20=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/docker-compose.yml | 31 ++++++++++++++++++++ src/Components/redis/tests/config/config.php | 18 ++---------- src/Components/redis/tests/phpunit.xml | 5 ++-- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 3890391a9d..0900a23154 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -1,6 +1,13 @@ version: "3.4" volumes: shared-volume: + driver: local + redis-cluster_data-0: + driver: local + redis-cluster_data-1: + driver: local + redis-cluster_data-2: + driver: local services: shared-tmp: image: busybox @@ -88,6 +95,30 @@ services: ports: - "9092:9092" + redis-node-0: + image: bitnami/redis-cluster:7.2 + volumes: + - redis-cluster_data-0:/bitnami/redis/data + environment: + - 'REDIS_PASSWORD=l83aa26' + - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + + redis-node-1: + image: bitnami/redis-cluster:7.2 + volumes: + - redis-cluster_data-1:/bitnami/redis/data + environment: + - 'REDIS_PASSWORD=l83aa26' + - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + + redis-node-2: + image: bitnami/redis-cluster:7.2 + volumes: + - redis-cluster_data-2:/bitnami/redis/data + environment: + - 'REDIS_PASSWORD=l83aa26' + - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + swoole: container_name: "swoole" image: ghcr.io/${REPOSITORY_OWNER}/imi-swoole-test:${IMAGE_VERSION} diff --git a/src/Components/redis/tests/config/config.php b/src/Components/redis/tests/config/config.php index 320dbeca80..21dd06367d 100644 --- a/src/Components/redis/tests/config/config.php +++ b/src/Components/redis/tests/config/config.php @@ -92,14 +92,7 @@ 'client' => 'phpredis', 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, - 'seeds' => [ - '192.168.32.2:6379', - '192.168.32.3:6379', - '192.168.32.4:6379', - '192.168.32.5:6379', - '192.168.32.6:6379', - '192.168.32.7:6379', - ], + 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS')), ], ], ], @@ -139,14 +132,7 @@ 'client' => 'predis', 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, - 'seeds' => [ - '192.168.32.2:6379', - '192.168.32.3:6379', - '192.168.32.4:6379', - '192.168.32.5:6379', - '192.168.32.6:6379', - '192.168.32.7:6379', - ], + 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS')), ], ], ], diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index f6ac1eca48..e49d2e88c9 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -18,7 +18,8 @@ - - + + + \ No newline at end of file From 4bde8c64f22aef77680741b4a6296a60a52eb016 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 18:30:57 +0800 Subject: [PATCH 16/97] =?UTF-8?q?Update:=20=E5=B0=9D=E8=AF=95=E5=90=AF?= =?UTF-8?q?=E7=94=A8=20redis=20=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 108 +++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23e1b46872..2445fa91a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,60 +59,63 @@ jobs: - name: Test if: ${{ env.test_prepared && always() }} run: docker exec ${ENV_SERVICE} composer test + - name: Test redis + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} run: docker exec ${ENV_SERVICE} composer test-swoole - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-workerman-gateway - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-roadrunner - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-fpm - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-jwt - - name: Test queue - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-queue - - name: Test amqp - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-amqp - - name: Test kafka - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-kafka - - name: Test grpc - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-grpc - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-snowflake - - name: Test mqtt - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-mqtt - - name: Test smarty - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-smarty - - name: Test pgsql - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-pgsql - - name: Test phar - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-phar - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-connection-center - - name: Test database - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-model +# - name: Test workerman +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-workerman +# - name: Test workerman-gateway +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-workerman-gateway +# - name: Test roadrunner +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-roadrunner +# - name: Test fpm +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-fpm +# - name: Test jwt +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-jwt +# - name: Test queue +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-queue +# - name: Test amqp +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-amqp +# - name: Test kafka +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-kafka +# - name: Test grpc +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-grpc +# - name: Test snowflake +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-snowflake +# - name: Test mqtt +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-mqtt +# - name: Test smarty +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-smarty +# - name: Test pgsql +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-pgsql +# - name: Test phar +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-phar +# - name: Test connection-center +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-connection-center +# - name: Test database +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-database +# - name: Test model +# if: ${{ env.test_prepared && always() }} +# run: docker exec ${ENV_SERVICE} composer test-model - name: Print logs if: failure() run: docker exec ${ENV_SERVICE} php .github/print-logs.php @@ -212,6 +215,7 @@ jobs: # run: docker exec ${ENV_SERVICE} php .github/print-logs.php ci-swoole-cli: + if: false name: Swoole-cli-${{ matrix.swoole-cli }} runs-on: ubuntu-latest strategy: @@ -323,6 +327,7 @@ jobs: run: php .github/print-logs.php ci-macos: + if: false name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} runs-on: macos-latest strategy: @@ -464,6 +469,7 @@ jobs: run: php .github/print-logs.php ci-windows: + if: false name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} runs-on: windows-latest strategy: From fd22ff84d1608fc0fa48e674d06a5425c8c28424 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 17 Feb 2024 18:38:02 +0800 Subject: [PATCH 17/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/ci-prepare/action.yml | 3 +- .github/docker-compose.yml | 88 ++++-- .github/workflows/ci.yml | 254 ++++++++++-------- .github/workflows/phpstan.yml | 1 + .../redis/tests/Tests/PhpRedisClusterTest.php | 8 + .../redis/tests/Tests/PredisClusterTest.php | 8 + src/Components/redis/tests/phpunit.xml | 2 +- 7 files changed, 225 insertions(+), 139 deletions(-) diff --git a/.github/actions/ci-prepare/action.yml b/.github/actions/ci-prepare/action.yml index 2e694ebfe7..8a086cf4ec 100644 --- a/.github/actions/ci-prepare/action.yml +++ b/.github/actions/ci-prepare/action.yml @@ -12,6 +12,7 @@ runs: - name: Setup Services shell: bash run: | + docker-compose -f ./.github/docker-compose.yml up -d redis-cluster-node-0 docker-compose -f ./.github/docker-compose.yml up -d ${{ inputs.env }} docker exec ${{ inputs.env }} php -v docker exec ${{ inputs.env }} php -m @@ -21,7 +22,7 @@ runs: - name: Prepare shell: bash run: | - docker exec ${{ inputs.env }} apt install -y rsync + docker exec ${{ inputs.env }} apt install -y rsync netcat-openbsd docker exec ${{ inputs.env }} composer config --global cache-files-dir /tmp/base_cache/composer docker exec ${{ inputs.env }} composer config -g process-timeout 600 docker exec ${{ inputs.env }} composer update --no-interaction --prefer-dist --no-progress ${COMPOSER_ENV} diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 0900a23154..02f8bf19b8 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -2,12 +2,6 @@ version: "3.4" volumes: shared-volume: driver: local - redis-cluster_data-0: - driver: local - redis-cluster_data-1: - driver: local - redis-cluster_data-2: - driver: local services: shared-tmp: image: busybox @@ -95,29 +89,79 @@ services: ports: - "9092:9092" - redis-node-0: + redis-cluster-node-1: + container_name: redis-cluster-node-1 image: bitnami/redis-cluster:7.2 - volumes: - - redis-cluster_data-0:/bitnami/redis/data environment: - - 'REDIS_PASSWORD=l83aa26' - - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + REDIS_PORT_NUMBER: 6480 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + ports: + - "6480:6480" - redis-node-1: + redis-cluster-node-2: + container_name: redis-cluster-node-2 image: bitnami/redis-cluster:7.2 - volumes: - - redis-cluster_data-1:/bitnami/redis/data environment: - - 'REDIS_PASSWORD=l83aa26' - - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + REDIS_PORT_NUMBER: 6481 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + ports: + - "6481:6481" - redis-node-2: + redis-cluster-node-3: + container_name: redis-cluster-node-3 + image: bitnami/redis-cluster:7.2 + environment: + REDIS_PORT_NUMBER: 6482 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + ports: + - "6482:6482" + + redis-cluster-node-4: + container_name: redis-cluster-node-4 image: bitnami/redis-cluster:7.2 - volumes: - - redis-cluster_data-2:/bitnami/redis/data environment: - - 'REDIS_PASSWORD=l83aa26' - - 'REDIS_NODES=redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5' + REDIS_PORT_NUMBER: 6483 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + ports: + - "6483:6483" + + redis-cluster-node-5: + container_name: redis-cluster-node-5 + image: bitnami/redis-cluster:7.2 + environment: + REDIS_PORT_NUMBER: 6484 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + ports: + - "6484:6484" + + redis-cluster-node-0: + container_name: redis-cluster-node-0 + image: bitnami/redis-cluster:7.2 + depends_on: + - redis-cluster-node-1 + - redis-cluster-node-2 + - redis-cluster-node-3 + - redis-cluster-node-4 + - redis-cluster-node-5 + environment: + REDIS_PORT_NUMBER: 6479 + REDIS_PASSWORD: "l83aa26" + REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" + REDISCLI_AUTH: "l83aa26" + REDIS_CLUSTER_REPLICAS: "1" + REDIS_CLUSTER_CREATOR: "yes" + healthcheck: + test: ["CMD-SHELL", "redis-cli -h 127.0.0.1 -p 6479 -a l83aa26 CLUSTER INFO | grep 'cluster_state:ok'"] + interval: 3s + timeout: 60s + retries: 30 + ports: + - "6479:6479" swoole: container_name: "swoole" @@ -129,6 +173,7 @@ services: - rabbitmq - kafka1 - postgres + - redis-cluster-node-0 environment: MYSQL_SERVER_HOST: mysql REDIS_SERVER_HOST: ${REDIS_SERVER_HOST} @@ -153,6 +198,7 @@ services: - rabbitmq - kafka1 - postgres + - redis-cluster-node-0 environment: MYSQL_SERVER_HOST: mysql REDIS_SERVER_HOST: ${REDIS_SERVER_HOST} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2445fa91a9..26a368153a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,12 +56,20 @@ jobs: uses: ./.github/actions/ci-prepare with: env: ${{ env.ENV_SERVICE }} + - name: Test Env + if: ${{ env.test_prepared && always() }} + run: | + docker ps + echo ">>> redis-cluster-node-0" + docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ninfo server' | nc redis-cluster-node-0 6479 -w 1" + docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc redis-cluster-node-0 6479 -w 1" - name: Test if: ${{ env.test_prepared && always() }} run: docker exec ${ENV_SERVICE} composer test - name: Test redis if: ${{ env.test_prepared && always() }} - run: docker exec ${ENV_SERVICE} composer test-redis + run: | + docker exec ${ENV_SERVICE} composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} run: docker exec ${ENV_SERVICE} composer test-swoole @@ -215,7 +223,6 @@ jobs: # run: docker exec ${ENV_SERVICE} php .github/print-logs.php ci-swoole-cli: - if: false name: Swoole-cli-${{ matrix.swoole-cli }} runs-on: ubuntu-latest strategy: @@ -231,8 +238,8 @@ jobs: - name: Setup Services shell: bash run: | - sudo apt update && sudo apt install -y rsync - docker-compose -f ./.github/docker-compose.yml up -d mysql postgres redis rabbitmq kafka1 + sudo apt update && sudo apt install -y rsync netcat-openbsd + docker-compose -f ./.github/docker-compose.yml up -d redis-cluster-node-0 mysql postgres redis rabbitmq kafka1 echo "127.0.0.1 kafka1" | sudo tee -a /etc/hosts - name: Setup swoole-cli run: .github/script/install-swoole-cli.sh ${{ matrix.swoole-cli }} @@ -270,58 +277,68 @@ jobs: docker exec postgres psql -d db_imi_test -U root -f /imi/.github/pgsql.sql echo "::endgroup::" echo "test_prepared=1" >> $GITHUB_ENV - + - name: Test Env + if: ${{ env.test_prepared && always() }} + run: | + docker ps + echo -e 'auth l83aa26\r\ninfo server' | nc 127.0.0.1 6479 -w 1 + echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc 127.0.0.1 6479 -w 1 - name: Test if: ${{ env.test_prepared && always() }} run: composer test + - name: Test redis + if: ${{ env.test_prepared && always() }} + env: + REDIS_SERVER_CLUSTER_SEEDS: "127.0.0.1:6479,127.0.0.1:6480,127.0.0.1:6481,127.0.0.1:6482,127.0.0.1:6483,127.0.0.1:6484" + run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} run: composer test-swoole - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: composer test-workerman-gateway - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: composer test-jwt - - name: Test queue - if: ${{ env.test_prepared && always() }} - run: composer test-queue - - name: Test amqp - if: ${{ env.test_prepared && always() }} - run: composer test-amqp - - name: Test kafka - if: ${{ env.test_prepared && always() }} - run: composer test-kafka - - name: Test grpc - if: ${{ env.test_prepared && always() }} - run: composer test-grpc - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: composer test-snowflake - - name: Test mqtt - if: ${{ env.test_prepared && always() }} - run: composer test-mqtt - - name: Test smarty - if: ${{ env.test_prepared && always() }} - run: composer test-smarty + # - name: Test workerman + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman + # - name: Test workerman-gateway + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman-gateway + # - name: Test jwt + # if: ${{ env.test_prepared && always() }} + # run: composer test-jwt + # - name: Test queue + # if: ${{ env.test_prepared && always() }} + # run: composer test-queue + # - name: Test amqp + # if: ${{ env.test_prepared && always() }} + # run: composer test-amqp + # - name: Test kafka + # if: ${{ env.test_prepared && always() }} + # run: composer test-kafka + # - name: Test grpc + # if: ${{ env.test_prepared && always() }} + # run: composer test-grpc + # - name: Test snowflake + # if: ${{ env.test_prepared && always() }} + # run: composer test-snowflake + # - name: Test mqtt + # if: ${{ env.test_prepared && always() }} + # run: composer test-mqtt + # - name: Test smarty + # if: ${{ env.test_prepared && always() }} + # run: composer test-smarty # - name: Test pgsql # if: ${{ matrix.swoole-cli == 'v5.0.3' && env.test_prepared && always() }} # run: composer test-pgsql - - name: Test phar - if: ${{ env.test_prepared && always() }} - run: composer test-phar - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: composer test-connection-center - - name: Test database - if: ${{ env.test_prepared && always() }} - run: composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: composer test-model + # - name: Test phar + # if: ${{ env.test_prepared && always() }} + # run: composer test-phar + # - name: Test connection-center + # if: ${{ env.test_prepared && always() }} + # run: composer test-connection-center + # - name: Test database + # if: ${{ env.test_prepared && always() }} + # run: composer test-database + # - name: Test model + # if: ${{ env.test_prepared && always() }} + # run: composer test-model - name: Print logs if: failure() run: php .github/print-logs.php @@ -419,57 +436,59 @@ jobs: - name: Test if: ${{ env.test_prepared && always() }} run: composer test + - name: Test redis + if: ${{ env.test_prepared && always() }} + run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} run: composer test-swoole - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: composer test-workerman-gateway - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: composer test-roadrunner - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: composer test-fpm - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: composer test-jwt - - name: Test queue - if: ${{ env.test_prepared && always() }} - run: composer test-queue - - name: Test grpc - if: ${{ env.test_prepared && always() }} - run: composer test-grpc - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: composer test-snowflake - - name: Test mqtt - if: ${{ env.test_prepared && always() }} - run: composer test-mqtt - - name: Test smarty - if: ${{ env.test_prepared && always() }} - run: composer test-smarty - - name: Test phar - if: ${{ env.test_prepared && always() }} - run: composer test-phar - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: composer test-connection-center - - name: Test database - if: ${{ env.test_prepared && always() }} - run: composer test-database - - name: Test model - if: ${{ env.test_prepared && always() }} - run: composer test-model + # - name: Test workerman + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman + # - name: Test workerman-gateway + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman-gateway + # - name: Test roadrunner + # if: ${{ env.test_prepared && always() }} + # run: composer test-roadrunner + # - name: Test fpm + # if: ${{ env.test_prepared && always() }} + # run: composer test-fpm + # - name: Test jwt + # if: ${{ env.test_prepared && always() }} + # run: composer test-jwt + # - name: Test queue + # if: ${{ env.test_prepared && always() }} + # run: composer test-queue + # - name: Test grpc + # if: ${{ env.test_prepared && always() }} + # run: composer test-grpc + # - name: Test snowflake + # if: ${{ env.test_prepared && always() }} + # run: composer test-snowflake + # - name: Test mqtt + # if: ${{ env.test_prepared && always() }} + # run: composer test-mqtt + # - name: Test smarty + # if: ${{ env.test_prepared && always() }} + # run: composer test-smarty + # - name: Test phar + # if: ${{ env.test_prepared && always() }} + # run: composer test-phar + # - name: Test connection-center + # if: ${{ env.test_prepared && always() }} + # run: composer test-connection-center + # - name: Test database + # if: ${{ env.test_prepared && always() }} + # run: composer test-database + # - name: Test model + # if: ${{ env.test_prepared && always() }} + # run: composer test-model - name: Print logs if: failure() run: php .github/print-logs.php ci-windows: - if: false name: Windows PHP-${{ matrix.php }} RoadRunner-${{ matrix.roadrunner }} runs-on: windows-latest strategy: @@ -552,33 +571,36 @@ jobs: - name: Test if: ${{ env.test_prepared && always() }} run: composer test - - name: Test fpm - if: ${{ env.test_prepared && always() }} - run: composer test-fpm - - name: Test workerman - if: ${{ env.test_prepared && always() }} - run: composer test-workerman - - name: Test workerman-gateway - if: ${{ env.test_prepared && always() }} - run: composer test-workerman-gateway-w - - name: Test roadrunner - if: ${{ env.test_prepared && always() }} - run: composer test-roadrunner - - name: Test jwt - if: ${{ env.test_prepared && always() }} - run: composer test-jwt - - name: Test snowflake - if: ${{ env.test_prepared && always() }} - run: composer test-snowflake - - name: Test connection-center - if: ${{ env.test_prepared && always() }} - run: composer test-connection-center-common - - name: Test database - if: ${{ env.test_prepared && always() }} - run: composer test-database - - name: Test model + - name: Test redis if: ${{ env.test_prepared && always() }} - run: composer test-model + run: composer test-redis + # - name: Test fpm + # if: ${{ env.test_prepared && always() }} + # run: composer test-fpm + # - name: Test workerman + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman + # - name: Test workerman-gateway + # if: ${{ env.test_prepared && always() }} + # run: composer test-workerman-gateway-w + # - name: Test roadrunner + # if: ${{ env.test_prepared && always() }} + # run: composer test-roadrunner + # - name: Test jwt + # if: ${{ env.test_prepared && always() }} + # run: composer test-jwt + # - name: Test snowflake + # if: ${{ env.test_prepared && always() }} + # run: composer test-snowflake + # - name: Test connection-center + # if: ${{ env.test_prepared && always() }} + # run: composer test-connection-center-common + # - name: Test database + # if: ${{ env.test_prepared && always() }} + # run: composer test-database + # - name: Test model + # if: ${{ env.test_prepared && always() }} + # run: composer test-model - name: Print logs if: failure() run: php .github\print-logs.php diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 854b497b41..d48973e082 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -18,6 +18,7 @@ concurrency: jobs: phpstan: runs-on: ubuntu-latest + if: false strategy: fail-fast: false matrix: diff --git a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php index d747e8289a..6b7789b9cb 100644 --- a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php @@ -17,6 +17,14 @@ class PhpRedisClusterTest extends PhpRedisTest { public string $driveName = 'test_phpredis_cluster'; + public static function setUpBeforeClass(): void + { + if (\PHP_OS_FAMILY === 'Windows') + { + self::markTestSkipped('not support redis cluster'); + } + } + public function testGetDrive(): IRedisHandler { $redisClient = RedisManager::getInstance($this->driveName); diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index 5e8560fb04..dbe9384873 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -19,6 +19,14 @@ class PredisClusterTest extends PhpRedisTest { public string $driveName = 'test_predis_cluster'; + public static function setUpBeforeClass(): void + { + if (\PHP_OS_FAMILY === 'Windows') + { + self::markTestSkipped('not support redis cluster'); + } + } + public function testGetDrive(): IRedisHandler { $redisClient = RedisManager::getInstance($this->driveName); diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index e49d2e88c9..c06c50bf53 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -20,6 +20,6 @@ - + \ No newline at end of file From f8016d15d74243543e54d7e1406b5b73fd110d77 Mon Sep 17 00:00:00 2001 From: auooru Date: Sun, 18 Feb 2024 15:08:05 +0800 Subject: [PATCH 18/97] =?UTF-8?q?Update:=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php | 8 ++++++++ .../Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php | 8 ++++++++ .../Tests/Model/PhpRedisCluster/PhpRedisModelTest.php | 8 ++++++++ src/Components/redis/tests/Tests/PhpRedisClusterTest.php | 2 +- src/Components/redis/tests/Tests/PredisClusterTest.php | 2 +- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php index 20422913d2..1084ea51ed 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php @@ -11,4 +11,12 @@ class PhpRedisModelHashObjectTest extends AbstractRedisModelHashObject { protected string $poolName = 'test_phpredis_cluster'; + + public static function setUpBeforeClass(): void + { + if (\PHP_OS_FAMILY !== 'Linux') + { + self::markTestSkipped('not support redis cluster'); + } + } } diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php index bfa21bda49..181d2133ba 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php @@ -11,4 +11,12 @@ class PhpRedisModelHashTest extends AbstractRedisModelHash { protected string $poolName = 'test_phpredis_cluster'; + + public static function setUpBeforeClass(): void + { + if (\PHP_OS_FAMILY !== 'Linux') + { + self::markTestSkipped('not support redis cluster'); + } + } } diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php index 5493999231..d6ec462d59 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php @@ -11,4 +11,12 @@ class PhpRedisModelTest extends AbstractRedisModel { protected string $poolName = 'test_phpredis_cluster'; + + public static function setUpBeforeClass(): void + { + if (\PHP_OS_FAMILY !== 'Linux') + { + self::markTestSkipped('not support redis cluster'); + } + } } diff --git a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php index 6b7789b9cb..a6d4593ff1 100644 --- a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php @@ -19,7 +19,7 @@ class PhpRedisClusterTest extends PhpRedisTest public static function setUpBeforeClass(): void { - if (\PHP_OS_FAMILY === 'Windows') + if (\PHP_OS_FAMILY !== 'Linux') { self::markTestSkipped('not support redis cluster'); } diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index dbe9384873..79ea5dcf95 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -21,7 +21,7 @@ class PredisClusterTest extends PhpRedisTest public static function setUpBeforeClass(): void { - if (\PHP_OS_FAMILY === 'Windows') + if (\PHP_OS_FAMILY !== 'Linux') { self::markTestSkipped('not support redis cluster'); } From 5b7668de9bba949cd289cd3e6ad22ef3c2eb997f Mon Sep 17 00:00:00 2001 From: auooru Date: Sun, 18 Feb 2024 16:03:04 +0800 Subject: [PATCH 19/97] =?UTF-8?q?Update:=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26a368153a..1a312b4a4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -344,7 +344,6 @@ jobs: run: php .github/print-logs.php ci-macos: - if: false name: MacOS PHP-${{ matrix.php }} Swoole-${{ matrix.swoole }} RoadRunner-${{ matrix.roadrunner }} runs-on: macos-latest strategy: From e61cf50bc44976611013d35401c7dfa78514c242 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 10:59:30 +0800 Subject: [PATCH 20/97] =?UTF-8?q?Update:=20=E5=AE=8C=E5=96=84=20Redis=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/model/src/RedisModel.php | 129 ++++++++++++------ .../redis/src/Handler/IRedisHandler.php | 11 ++ .../src/Handler/PhpRedisClusterHandler.php | 10 ++ .../redis/src/Handler/PhpRedisHandler.php | 10 ++ .../src/Handler/PredisClusterHandler.php | 47 ++++++- .../redis/src/Handler/PredisHandler.php | 10 ++ .../Model/AbstractRedisModelHashObject.php | 4 + .../PhpRedisModelHashObjectTest.php | 2 +- .../PhpRedisCluster/PhpRedisModelHashTest.php | 2 +- .../PhpRedisCluster/PhpRedisModelTest.php | 2 +- ...ject.php => PredisModelHashObjectTest.php} | 2 +- ...sModelHash.php => PredisModelHashTest.php} | 4 +- .../{PredisModel.php => PredisModelTest.php} | 4 +- .../PredisModelHashObjectTest.php | 24 ++++ .../PredisCluster/PredisModelHashTest.php | 24 ++++ .../Model/PredisCluster/PredisModelTest.php | 24 ++++ .../redis/tests/Tests/PhpRedisClusterTest.php | 37 +++++ .../redis/tests/Tests/PredisClusterTest.php | 77 ++++++++++- 18 files changed, 365 insertions(+), 58 deletions(-) rename src/Components/redis/tests/Tests/Model/Predis/{PredisModelHashObject.php => PredisModelHashObjectTest.php} (84%) rename src/Components/redis/tests/Tests/Model/Predis/{PredisModelHash.php => PredisModelHashTest.php} (76%) rename src/Components/redis/tests/Tests/Model/Predis/{PredisModel.php => PredisModelTest.php} (77%) create mode 100644 src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelHashObjectTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelHashTest.php create mode 100644 src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelTest.php diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index ce6788cc86..0e0a85ec65 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -14,6 +14,10 @@ use Imi\Model\Event\ModelEvents; use Imi\Model\Event\Param\InitEventParam; use Imi\Model\Key\KeyRule; +use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; use Imi\Redis\RedisHandler; use Imi\Redis\RedisManager; use Imi\Util\Format\IFormat; @@ -236,29 +240,37 @@ public static function find(string|array $condition = []): ?self /** @var \Imi\Model\Annotation\RedisEntity $redisEntity */ $redisEntity = static::__getRedisEntity(static::__getRealClassName()); $key = static::generateKey($condition); + + /** @var IFormat|null $formatter */ + $formatter = null !== $redisEntity->formatter ? App::getBean($redisEntity->formatter) : null; + switch ($redisEntity->storage) { case RedisStorageMode::STRING: $data = static::__getRedis()->get($key); - if ($data && null !== $redisEntity->formatter) + if ($data && null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->decode($data); } break; case RedisStorageMode::HASH: $member = static::generateMember($condition); $data = static::__getRedis()->hGet($key, $member); - if ($data && null !== $redisEntity->formatter) + if ($data && null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->decode($data); } break; case RedisStorageMode::HASH_OBJECT: $data = static::__getRedis()->hGetAll($key); + if ($data && null !== $formatter) + { + foreach ($data as &$val) + { + $val = $formatter->decode($val); + } + unset($val); + } break; default: throw new \InvalidArgumentException(sprintf('Invalid RedisEntity->storage %s', $redisEntity->storage)); @@ -286,11 +298,8 @@ public static function select(mixed ...$conditions): array { /** @var \Imi\Model\Annotation\RedisEntity $redisEntity */ $redisEntity = static::__getRedisEntity(static::__getRealClassName()); - if (null !== $redisEntity->formatter) - { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); - } + /** @var IFormat|null $formatter */ + $formatter = null !== $redisEntity->formatter ? App::getBean($redisEntity->formatter) : null; $keys = []; if ($conditions) { @@ -302,7 +311,15 @@ public static function select(mixed ...$conditions): array switch ($redisEntity->storage) { case RedisStorageMode::STRING: - $datas = static::__getRedis()->mget($keys); + $redis = static::__getRedis(); + if ($redis instanceof PredisClusterHandler) { + $datas = []; + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { + \array_push($datas, ...$redis->mget($slotGroupByKey)); + } + } else { + $datas = $redis->mget($keys); + } if ($datas) { $list = []; @@ -310,7 +327,7 @@ public static function select(mixed ...$conditions): array { if (null !== $data && false !== $data) { - if (isset($formatter)) + if (null !== $formatter) { $data = $formatter->decode($data); } @@ -346,7 +363,7 @@ public static function select(mixed ...$conditions): array { if (null !== $data) { - if (isset($formatter)) + if (null !== $formatter) { $data = $formatter->decode($data); } @@ -374,6 +391,14 @@ public static function select(mixed ...$conditions): array foreach ($keys as $key) { $data = $redis->hGetAll($key); + if (null !== $formatter) + { + foreach ($data as &$val) + { + $val = $formatter->decode($val); + } + unset($val); + } $record = static::createFromRecord($data); $record->key = $key; $list[] = $record; @@ -398,13 +423,15 @@ public function save(): bool $redis = static::__getRedis($this); $data = iterator_to_array($this); $this->parseSaveData($data); + + /** @var IFormat|null $formatter */ + $formatter = null !== $redisEntity->formatter ? App::getBean($redisEntity->formatter) : null; + switch ($redisEntity->storage) { case RedisStorageMode::STRING: - if (null !== $redisEntity->formatter) + if (null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->encode($data); } if (null === $this->__ttl) @@ -417,16 +444,22 @@ public function save(): bool } // no break case RedisStorageMode::HASH: - if (null !== $redisEntity->formatter) + if (null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->encode($data); } return false !== $redis->hSet($this->__getKey(), $this->__getMember(), $data); case RedisStorageMode::HASH_OBJECT: $key = $this->__getKey(); + if (null !== $formatter) + { + foreach ($data as &$val) + { + $val = $formatter->encode($val); + } + unset($val); + } $result = $redis->hMset($key, $data); if ($result && null !== $this->__ttl) { @@ -467,20 +500,19 @@ public function safeDelete(): bool $redisEntity = static::__getRedisEntity(static::__getRealClassName()); $data = iterator_to_array($this); $this->parseSaveData($data); + + /** @var IFormat|null $formatter */ + $formatter = null !== $redisEntity->formatter ? App::getBean($redisEntity->formatter) : null; + switch ($redisEntity->storage) { case RedisStorageMode::STRING: - if (null !== $redisEntity->formatter) + if (null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->encode($data); } $redis = static::__getRedis($this); - if ($redis->isSupportSerialize()) - { - $data = $redis->_serialize($data); - } + $data = $redis->_serialize($data); return (bool) $redis->evalEx(<<<'LUA' if (ARGV[1] == redis.call('get', KEYS[1])) then @@ -490,17 +522,12 @@ public function safeDelete(): bool end LUA, [$this->__getKey(), $data], 1); case RedisStorageMode::HASH: - if (null !== $redisEntity->formatter) + if (null !== $formatter) { - /** @var IFormat $formatter */ - $formatter = App::getBean($redisEntity->formatter); $data = $formatter->encode($data); } $redis = static::__getRedis($this); - if ($redis->isSupportSerialize()) - { - $data = $redis->_serialize($data); - } + $data = $redis->_serialize($data); return (bool) $redis->evalEx(<<<'LUA' if (ARGV[2] == redis.call('hget', KEYS[1], ARGV[1])) then @@ -515,10 +542,9 @@ public function safeDelete(): bool foreach ($data as $key => $value) { $argv[] = $key; - if ($redis->isSupportSerialize()) - { - $argv[] = $redis->_serialize($value); - } + + $value = null === $formatter ? $value : $formatter->encode($value); + $argv[] = $redis->_serialize($value); } return (bool) $redis->evalEx(<<<'LUA' @@ -554,8 +580,16 @@ public static function deleteBatch(mixed ...$conditions): int { $keys[] = static::generateKey($condition); } - - return static::__getRedis()->del(...$keys) ?: 0; + $redis = static::__getRedis(); + if ($redis instanceof PredisClusterHandler) { + $result = 0; + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { + $result += $redis->del(...$slotGroupByKey) ?: 0; + } + return $result; + } else { + return $redis->del(...$keys) ?: 0; + } case RedisStorageMode::HASH: $result = 0; foreach ($conditions as $condition) @@ -573,7 +607,16 @@ public static function deleteBatch(mixed ...$conditions): int $keys[] = static::generateKey($condition); } - return static::__getRedis()->del(...$keys) ?: 0; + $redis = static::__getRedis(); + if ($redis instanceof PredisClusterHandler) { + $result = 0; + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { + $result += $redis->del(...$slotGroupByKey) ?: 0; + } + return $result; + } else { + return $redis->del(...$keys) ?: 0; + } default: throw new \InvalidArgumentException(sprintf('Invalid RedisEntity->storage %s', $redisEntity->storage)); } @@ -671,8 +714,10 @@ public function __getMember(): string /** * 获取Redis操作对象 + * + * @return PhpRedisHandler|PredisHandler */ - public static function __getRedis(?self $redisModel = null): RedisHandler + public static function __getRedis(?self $redisModel = null): IRedisHandler { $annotation = static::__getRedisEntity($redisModel ?? static::class); $redis = RedisManager::getInstance($annotation->poolName); diff --git a/src/Components/redis/src/Handler/IRedisHandler.php b/src/Components/redis/src/Handler/IRedisHandler.php index 624c35984b..d06cf46f79 100644 --- a/src/Components/redis/src/Handler/IRedisHandler.php +++ b/src/Components/redis/src/Handler/IRedisHandler.php @@ -11,4 +11,15 @@ public function getInstance(): object; public function isCluster(): bool; public function isSupportSerialize(): bool; + + /** + * @param mixed $value + * @return string + */ + public function _serialize(mixed $value); + + /** + * @param string $value + */ + public function _unserialize($value): mixed; } diff --git a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php index 875c905b51..0e82086c45 100644 --- a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php @@ -58,4 +58,14 @@ public function isSupportSerialize(): bool { return true; } + + public function _serialize(mixed $value) + { + return $this->client->_serialize($value); + } + + public function _unserialize($value): mixed + { + return $this->client->_unserialize($value); + } } diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php index a670641980..d4f88be984 100644 --- a/src/Components/redis/src/Handler/PhpRedisHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -48,4 +48,14 @@ public function isSupportSerialize(): bool { return true; } + + public function _serialize(mixed $value) + { + return $this->client->_serialize($value); + } + + public function _unserialize($value): mixed + { + return $this->client->_unserialize($value); + } } diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php index 281430a15c..0dc11b075a 100644 --- a/src/Components/redis/src/Handler/PredisClusterHandler.php +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -30,16 +30,19 @@ public function getInstance(): Client public function getNodes(): array { // 详细说明: https://github.com/predis/predis/issues/571#issuecomment-678300308 - /** @var RedisCluster $connection */ - $connection = $this->client->getConnection(); - $nodes = $connection->getSlotMap()->getNodes(); + /** @var RedisCluster $cluster */ + $cluster = $this->client->getConnection(); - return array_map(static function ($node) { - $arr = explode(':', $node); + $nodes = []; + foreach ($cluster as $node) { + /** @var \Predis\Connection\StreamConnection $node */ + $arr = explode(':', (string) $node); $arr[1] = (int) $arr[1]; - return $arr; - }, $nodes); + $nodes[] = $arr; + } + + return $nodes; } public function isConnected(): bool @@ -81,8 +84,38 @@ public function close(): void $this->client->disconnect(); } + public function getSlotGroupByKeys(array $keys): array + { + // https://gist.github.com/nrk/e07311af2316ea7e51719735274ded94 + + /** @var \Predis\Cluster\StrategyInterface $strategy */ + $strategy = $this->client->getConnection()->getClusterStrategy(); + $keysBySlot = []; + foreach ($keys as $key) { + $slot = $strategy->getSlotByKey($key); + + if (isset($keysBySlot[$slot])) { + $keysBySlot[$slot][] = $key; + } else { + $keysBySlot[$slot] = [$key]; + } + } + + return $keysBySlot; + } + public function isSupportSerialize(): bool { return false; } + + public function _serialize(mixed $value) + { + return $value; + } + + public function _unserialize($value): mixed + { + return $value; + } } diff --git a/src/Components/redis/src/Handler/PredisHandler.php b/src/Components/redis/src/Handler/PredisHandler.php index 2b57bdddf1..32e895c949 100644 --- a/src/Components/redis/src/Handler/PredisHandler.php +++ b/src/Components/redis/src/Handler/PredisHandler.php @@ -52,4 +52,14 @@ public function isSupportSerialize(): bool { return false; } + + public function _serialize(mixed $value) + { + return $value; + } + + public function _unserialize($value): mixed + { + return $value; + } } diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php index 5d0fa9f2d3..4486f8a70f 100644 --- a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php @@ -15,6 +15,7 @@ abstract class AbstractRedisModelHashObject extends TestCase public function testSave(): void { + /** @var class-string $model */ $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, @@ -26,6 +27,7 @@ public function testSave(): void public function testFind(): void { + /** @var class-string $model */ $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); $expected = [ 'id' => 1, @@ -42,6 +44,7 @@ public function testFind(): void public function testSelect(): void { + /** @var class-string $model */ $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); $expected = [ [ @@ -88,6 +91,7 @@ public function testDelete(): void public function testSafeDelete(): void { + /** @var class-string $model */ $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); // --更新-- // 原始记录 diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php index 1084ea51ed..62d0002c09 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashObjectTest.php @@ -7,7 +7,7 @@ use Imi\Redis\Test\Tests\Model\AbstractRedisModelHashObject; use PHPUnit\Framework\Attributes\TestDox; -#[TestDox('Redis/PhpRedis/Cluster/Model/HashObjectModel')] +#[TestDox('Redis/PhpRedisCluster/Model/HashObjectModel')] class PhpRedisModelHashObjectTest extends AbstractRedisModelHashObject { protected string $poolName = 'test_phpredis_cluster'; diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php index 181d2133ba..c2e197f7d5 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelHashTest.php @@ -7,7 +7,7 @@ use Imi\Redis\Test\Tests\Model\AbstractRedisModelHash; use PHPUnit\Framework\Attributes\TestDox; -#[TestDox('Redis/PhpRedis/Cluster/Model/HashModel')] +#[TestDox('Redis/PhpRedisCluster/Model/HashModel')] class PhpRedisModelHashTest extends AbstractRedisModelHash { protected string $poolName = 'test_phpredis_cluster'; diff --git a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php index d6ec462d59..5772f20cb1 100644 --- a/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php +++ b/src/Components/redis/tests/Tests/Model/PhpRedisCluster/PhpRedisModelTest.php @@ -7,7 +7,7 @@ use Imi\Redis\Test\Tests\Model\AbstractRedisModel; use PHPUnit\Framework\Attributes\TestDox; -#[TestDox('Redis/PhpRedis/Cluster/Model/BaseModel')] +#[TestDox('Redis/PhpRedisCluster/Model/BaseModel')] class PhpRedisModelTest extends AbstractRedisModel { protected string $poolName = 'test_phpredis_cluster'; diff --git a/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObject.php b/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObjectTest.php similarity index 84% rename from src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObject.php rename to src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObjectTest.php index 2d274ad10a..fbcb614a31 100644 --- a/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObject.php +++ b/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashObjectTest.php @@ -9,7 +9,7 @@ use PHPUnit\Framework\Attributes\TestDox; #[TestDox('Redis/Predis/Model/HashObjectModel')] -class PredisModelHashObject extends AbstractRedisModelHashObject +class PredisModelHashObjectTest extends AbstractRedisModelHashObject { protected string $poolName = 'test_predis_standalone'; protected ?string $formatter = PhpSerialize::class; diff --git a/src/Components/redis/tests/Tests/Model/Predis/PredisModelHash.php b/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashTest.php similarity index 76% rename from src/Components/redis/tests/Tests/Model/Predis/PredisModelHash.php rename to src/Components/redis/tests/Tests/Model/Predis/PredisModelHashTest.php index 7a9fd50a0c..f2ba47559c 100644 --- a/src/Components/redis/tests/Tests/Model/Predis/PredisModelHash.php +++ b/src/Components/redis/tests/Tests/Model/Predis/PredisModelHashTest.php @@ -8,8 +8,8 @@ use Imi\Util\Format\PhpSerialize; use PHPUnit\Framework\Attributes\TestDox; -#[TestDox('Redis/PhpRedis/Model/HashModel')] -class PredisModelHash extends AbstractRedisModelHash +#[TestDox('Redis/Predis/Model/HashModel')] +class PredisModelHashTest extends AbstractRedisModelHash { protected string $poolName = 'test_predis_standalone'; protected ?string $formatter = PhpSerialize::class; diff --git a/src/Components/redis/tests/Tests/Model/Predis/PredisModel.php b/src/Components/redis/tests/Tests/Model/Predis/PredisModelTest.php similarity index 77% rename from src/Components/redis/tests/Tests/Model/Predis/PredisModel.php rename to src/Components/redis/tests/Tests/Model/Predis/PredisModelTest.php index 776d907e29..c621b4e67f 100644 --- a/src/Components/redis/tests/Tests/Model/Predis/PredisModel.php +++ b/src/Components/redis/tests/Tests/Model/Predis/PredisModelTest.php @@ -8,8 +8,8 @@ use Imi\Util\Format\PhpSerialize; use PHPUnit\Framework\Attributes\TestDox; -#[TestDox('Redis/PhpRedis/Model/BaseModel')] -class PredisModel extends AbstractRedisModel +#[TestDox('Redis/Predis/Model/BaseModel')] +class PredisModelTest extends AbstractRedisModel { protected string $poolName = 'test_predis_standalone'; protected ?string $formatter = PhpSerialize::class; diff --git a/src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelHashObjectTest.php b/src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelHashObjectTest.php new file mode 100644 index 0000000000..30193322e9 --- /dev/null +++ b/src/Components/redis/tests/Tests/Model/PredisCluster/PredisModelHashObjectTest.php @@ -0,0 +1,24 @@ +getNodes() as $node) { self::assertTrue($redis->flushdb($node, false)); } } + + #[Depends('testGetDrive')] + public function testHashKeys(IRedisHandler $redis): void + { + /** @var PhpRedisClusterHandler $redis */ + $prefix = 'imi:hash-test:k'; + + $groupItems = []; + for ($i = 0; $i < 100; $i++) { + $key = $prefix . \dechex($i); + $groupItems[$key] = []; + for ($ii = 0; $ii < 100; $ii++) { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + } + } + foreach ($groupItems as $k => $items) { + self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); + } + + foreach ($groupItems as $k => $items) { + $result = $redis->hgetall($k); + self::assertEquals($items, $result, "hgetall {$k} failed"); + } + + $hasKeys = []; + foreach ($redis->scanEach($prefix . '*', 20) as $key) { + $hasKeys[] = $key; + } + + $keys = \array_keys($groupItems); + self::assertEquals($keys, \array_intersect($keys, $hasKeys), "scanEach failed"); + + self::assertEquals(count($keys), $redis->del($keys), 'del failed'); + } } diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index 79ea5dcf95..395f058e27 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -10,6 +10,7 @@ use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\TestDox; use Predis\Client; +use Predis\Collection\Iterator\Keyspace; /** * @implements PhpRedisTest @@ -44,7 +45,8 @@ protected function flush(IRedisHandler $redis): void foreach ($redis->getNodes() as $node) { $client = $redis->getClientBy('id', "{$node[0]}:{$node[1]}"); - self::assertTrue($client->flushdb()); + $result = $client->flushdb(); + self::assertTrue($result instanceof \Predis\Response\Status && 'OK' === (string) $result); } } @@ -58,4 +60,77 @@ public function testGeoAdd(IRedisHandler $redis): void self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); } + + #[Depends('testGetDrive')] + public function testHashKeysSlot(IRedisHandler $redis): void + { + /** @var PredisClusterHandler $redis */ + $prefix = 'imi:hash-test:k'; + + $groupItems = []; + for ($i = 0; $i < 100; $i++) { + $key = $prefix . \dechex($i); + $groupItems[$key] = []; + for ($ii = 0; $ii < 100; $ii++) { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + } + } + foreach ($groupItems as $k => $items) { + self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); + } + + foreach ($groupItems as $k => $items) { + $result = $redis->hgetall($k); + self::assertEquals($items, $result, "hgetall {$k} failed"); + } + + $hasKeys = []; + foreach ($redis->scanEach($prefix . '*', 20) as $key) { + $hasKeys[] = $key; + } + + $keys = \array_keys($groupItems); + self::assertEquals($keys, \array_intersect($keys, $hasKeys), "scanEach failed"); + + $keysBySlot = $redis->getSlotGroupByKeys($keys); + + foreach ($keysBySlot as $items) { + self::assertEquals(count($items), $redis->del($items), 'del failed'); + } + } + + #[Depends('testGetDrive')] + public function testHashKeysTags(IRedisHandler $redis): void + { + /** @var PredisClusterHandler $redis */ + + $prefix = '{imi:hash-test}:k'; + $groupItems = []; + for ($i = 0; $i < 100; $i++) { + $key = $prefix . \dechex($i); + $groupItems[$key] = []; + for ($ii = 0; $ii < 100; $ii++) { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + } + } + foreach ($groupItems as $k => $items) { + self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); + } + + foreach ($groupItems as $k => $items) { + $result = $redis->hgetall($k); + self::assertEquals($items, $result, "hgetall {$k} failed"); + } + + $hasKeys = []; + foreach ($redis->scanEach($prefix . '*', 20) as $key) { + $hasKeys[] = $key; + } + + $keys = \array_keys($groupItems); + self::assertEquals($keys, \array_intersect($keys, $hasKeys), 'scanEach failed'); + + $keys = \array_keys($groupItems); + self::assertEquals(count($keys), $redis->del($keys), 'del failed'); + } } From ee51d466b595680b4a0a89237c9ee582ee6c8761 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 11:13:13 +0800 Subject: [PATCH 21/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/model/src/RedisModel.php | 37 ++++++++---- .../redis/src/Handler/IRedisHandler.php | 11 +--- .../src/Handler/PredisClusterHandler.php | 13 +++-- .../redis/tests/Tests/PhpRedisClusterTest.php | 26 +++++---- .../redis/tests/Tests/PredisClusterTest.php | 57 +++++++++++-------- 5 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index 0e0a85ec65..f038e31995 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -18,7 +18,6 @@ use Imi\Redis\Handler\PhpRedisHandler; use Imi\Redis\Handler\PredisClusterHandler; use Imi\Redis\Handler\PredisHandler; -use Imi\Redis\RedisHandler; use Imi\Redis\RedisManager; use Imi\Util\Format\IFormat; use Imi\Util\Imi; @@ -312,12 +311,16 @@ public static function select(mixed ...$conditions): array { case RedisStorageMode::STRING: $redis = static::__getRedis(); - if ($redis instanceof PredisClusterHandler) { + if ($redis instanceof PredisClusterHandler) + { $datas = []; - foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { - \array_push($datas, ...$redis->mget($slotGroupByKey)); + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) + { + array_push($datas, ...$redis->mget($slotGroupByKey)); } - } else { + } + else + { $datas = $redis->mget($keys); } if ($datas) @@ -581,15 +584,21 @@ public static function deleteBatch(mixed ...$conditions): int $keys[] = static::generateKey($condition); } $redis = static::__getRedis(); - if ($redis instanceof PredisClusterHandler) { + if ($redis instanceof PredisClusterHandler) + { $result = 0; - foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) + { $result += $redis->del(...$slotGroupByKey) ?: 0; } + return $result; - } else { + } + else + { return $redis->del(...$keys) ?: 0; } + // no break case RedisStorageMode::HASH: $result = 0; foreach ($conditions as $condition) @@ -608,15 +617,21 @@ public static function deleteBatch(mixed ...$conditions): int } $redis = static::__getRedis(); - if ($redis instanceof PredisClusterHandler) { + if ($redis instanceof PredisClusterHandler) + { $result = 0; - foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) { + foreach ($redis->getSlotGroupByKeys($keys) as $slotGroupByKey) + { $result += $redis->del(...$slotGroupByKey) ?: 0; } + return $result; - } else { + } + else + { return $redis->del(...$keys) ?: 0; } + // no break default: throw new \InvalidArgumentException(sprintf('Invalid RedisEntity->storage %s', $redisEntity->storage)); } diff --git a/src/Components/redis/src/Handler/IRedisHandler.php b/src/Components/redis/src/Handler/IRedisHandler.php index d06cf46f79..b8bcdbac7e 100644 --- a/src/Components/redis/src/Handler/IRedisHandler.php +++ b/src/Components/redis/src/Handler/IRedisHandler.php @@ -12,14 +12,7 @@ public function isCluster(): bool; public function isSupportSerialize(): bool; - /** - * @param mixed $value - * @return string - */ - public function _serialize(mixed $value); + public function _serialize(mixed $value): string; - /** - * @param string $value - */ - public function _unserialize($value): mixed; + public function _unserialize(string $value): mixed; } diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php index 0dc11b075a..77c128b37b 100644 --- a/src/Components/redis/src/Handler/PredisClusterHandler.php +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -34,7 +34,8 @@ public function getNodes(): array $cluster = $this->client->getConnection(); $nodes = []; - foreach ($cluster as $node) { + foreach ($cluster as $node) + { /** @var \Predis\Connection\StreamConnection $node */ $arr = explode(':', (string) $node); $arr[1] = (int) $arr[1]; @@ -91,12 +92,16 @@ public function getSlotGroupByKeys(array $keys): array /** @var \Predis\Cluster\StrategyInterface $strategy */ $strategy = $this->client->getConnection()->getClusterStrategy(); $keysBySlot = []; - foreach ($keys as $key) { + foreach ($keys as $key) + { $slot = $strategy->getSlotByKey($key); - if (isset($keysBySlot[$slot])) { + if (isset($keysBySlot[$slot])) + { $keysBySlot[$slot][] = $key; - } else { + } + else + { $keysBySlot[$slot] = [$key]; } } diff --git a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php index 492371eb23..ac2f859af2 100644 --- a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php @@ -6,7 +6,6 @@ use Imi\Redis\Handler\IRedisHandler; use Imi\Redis\Handler\PhpRedisClusterHandler; -use Imi\Redis\Handler\PredisClusterHandler; use Imi\Redis\RedisManager; use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\TestDox; @@ -55,30 +54,35 @@ public function testHashKeys(IRedisHandler $redis): void $prefix = 'imi:hash-test:k'; $groupItems = []; - for ($i = 0; $i < 100; $i++) { - $key = $prefix . \dechex($i); + for ($i = 0; $i < 100; ++$i) + { + $key = $prefix . dechex($i); $groupItems[$key] = []; - for ($ii = 0; $ii < 100; $ii++) { - $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + for ($ii = 0; $ii < 100; ++$ii) + { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . dechex($ii); } } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { $result = $redis->hgetall($k); self::assertEquals($items, $result, "hgetall {$k} failed"); } $hasKeys = []; - foreach ($redis->scanEach($prefix . '*', 20) as $key) { + foreach ($redis->scanEach($prefix . '*', 20) as $key) + { $hasKeys[] = $key; } - $keys = \array_keys($groupItems); - self::assertEquals($keys, \array_intersect($keys, $hasKeys), "scanEach failed"); + $keys = array_keys($groupItems); + self::assertEquals($keys, array_intersect($keys, $hasKeys), 'scanEach failed'); - self::assertEquals(count($keys), $redis->del($keys), 'del failed'); + self::assertEquals(\count($keys), $redis->del($keys), 'del failed'); } } diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index 395f058e27..7595f1e072 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -10,7 +10,6 @@ use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\TestDox; use Predis\Client; -use Predis\Collection\Iterator\Keyspace; /** * @implements PhpRedisTest @@ -68,34 +67,40 @@ public function testHashKeysSlot(IRedisHandler $redis): void $prefix = 'imi:hash-test:k'; $groupItems = []; - for ($i = 0; $i < 100; $i++) { - $key = $prefix . \dechex($i); + for ($i = 0; $i < 100; ++$i) + { + $key = $prefix . dechex($i); $groupItems[$key] = []; - for ($ii = 0; $ii < 100; $ii++) { - $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + for ($ii = 0; $ii < 100; ++$ii) + { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . dechex($ii); } } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { $result = $redis->hgetall($k); self::assertEquals($items, $result, "hgetall {$k} failed"); } $hasKeys = []; - foreach ($redis->scanEach($prefix . '*', 20) as $key) { + foreach ($redis->scanEach($prefix . '*', 20) as $key) + { $hasKeys[] = $key; } - $keys = \array_keys($groupItems); - self::assertEquals($keys, \array_intersect($keys, $hasKeys), "scanEach failed"); + $keys = array_keys($groupItems); + self::assertEquals($keys, array_intersect($keys, $hasKeys), 'scanEach failed'); $keysBySlot = $redis->getSlotGroupByKeys($keys); - foreach ($keysBySlot as $items) { - self::assertEquals(count($items), $redis->del($items), 'del failed'); + foreach ($keysBySlot as $items) + { + self::assertEquals(\count($items), $redis->del($items), 'del failed'); } } @@ -103,34 +108,38 @@ public function testHashKeysSlot(IRedisHandler $redis): void public function testHashKeysTags(IRedisHandler $redis): void { /** @var PredisClusterHandler $redis */ - $prefix = '{imi:hash-test}:k'; $groupItems = []; - for ($i = 0; $i < 100; $i++) { - $key = $prefix . \dechex($i); + for ($i = 0; $i < 100; ++$i) + { + $key = $prefix . dechex($i); $groupItems[$key] = []; - for ($ii = 0; $ii < 100; $ii++) { - $groupItems[$key]["hk_{$ii}"] = 'hv_' . \dechex($ii); + for ($ii = 0; $ii < 100; ++$ii) + { + $groupItems[$key]["hk_{$ii}"] = 'hv_' . dechex($ii); } } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { self::assertTrue($redis->hmset($k, $items), "hmset {$k} failed"); } - foreach ($groupItems as $k => $items) { + foreach ($groupItems as $k => $items) + { $result = $redis->hgetall($k); self::assertEquals($items, $result, "hgetall {$k} failed"); } $hasKeys = []; - foreach ($redis->scanEach($prefix . '*', 20) as $key) { + foreach ($redis->scanEach($prefix . '*', 20) as $key) + { $hasKeys[] = $key; } - $keys = \array_keys($groupItems); - self::assertEquals($keys, \array_intersect($keys, $hasKeys), 'scanEach failed'); + $keys = array_keys($groupItems); + self::assertEquals($keys, array_intersect($keys, $hasKeys), 'scanEach failed'); - $keys = \array_keys($groupItems); - self::assertEquals(count($keys), $redis->del($keys), 'del failed'); + $keys = array_keys($groupItems); + self::assertEquals(\count($keys), $redis->del($keys), 'del failed'); } } From b922a3592ff984f9bbd6c1c076730d3399e2c681 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 14:27:18 +0800 Subject: [PATCH 22/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E9=9D=99?= =?UTF-8?q?=E6=80=81=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Connector/RedisConnectionDriver.php | 18 +++++++++------ .../src/Handler/AbstractRedisHandler.php | 2 +- .../redis/src/Handler/IRedisHandler.php | 4 ++-- ...sScanExMethod.php => IRedisScanMethod.php} | 10 ++++---- .../src/Handler/PhpRedisClusterHandler.php | 20 +++++----------- .../redis/src/Handler/PhpRedisHandler.php | 13 ++--------- .../src/Handler/PredisClusterHandler.php | 20 ++++------------ .../redis/src/Handler/PredisHandler.php | 10 -------- src/Components/redis/src/RedisManager.php | 6 ++--- .../redis/src/Traits/TPhpRedisMethod.php | 23 +++++++++++++++---- .../redis/src/Traits/TPredisMethod.php | 23 ++++++++++++++----- 11 files changed, 69 insertions(+), 80 deletions(-) rename src/Components/redis/src/Handler/{IRedisScanExMethod.php => IRedisScanMethod.php} (69%) diff --git a/src/Components/redis/src/Connector/RedisConnectionDriver.php b/src/Components/redis/src/Connector/RedisConnectionDriver.php index 83545f4a51..657d8533f2 100644 --- a/src/Components/redis/src/Connector/RedisConnectionDriver.php +++ b/src/Components/redis/src/Connector/RedisConnectionDriver.php @@ -7,14 +7,17 @@ use Imi\ConnectionCenter\Contract\AbstractConnectionDriver; use Imi\ConnectionCenter\Contract\IConnectionConfig; use Imi\Redis\Enum\RedisMode; -use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisClusterHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; class RedisConnectionDriver extends AbstractConnectionDriver { /** * @param RedisDriverConfig $config * - * @return object|\Imi\Redis\Handler\IRedisClusterHandler|\Imi\Redis\Handler\IRedisHandler + * @return object|PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler */ protected function createInstanceByConfig(IConnectionConfig $config): object { @@ -23,6 +26,7 @@ protected function createInstanceByConfig(IConnectionConfig $config): object { 'phpredis' => PhpRedisConnector::class, 'predis' => PredisConnector::class, + default => throw new \RuntimeException(sprintf('Unsupported redis client: %s', $config->client)), }; return match ($config->mode) @@ -39,7 +43,7 @@ public static function createConnectionConfig(array|string $config): IConnection } /** - * @param IRedisHandler $instance + * @param PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $instance */ public function connect(object $instance): object { @@ -47,14 +51,14 @@ public function connect(object $instance): object } /** - * @param IRedisHandler $instance + * @param PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $instance */ public function close(object $instance): void { } /** - * @param IRedisHandler $instance + * @param PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $instance */ public function reset(object $instance): void { @@ -68,7 +72,7 @@ public function reset(object $instance): void } /** - * @param IRedisHandler $instance + * @param PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $instance */ public function checkAvailable(object $instance): bool { @@ -76,7 +80,7 @@ public function checkAvailable(object $instance): bool } /** - * @param IRedisHandler $instance + * @param PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $instance */ public function ping(object $instance): bool { diff --git a/src/Components/redis/src/Handler/AbstractRedisHandler.php b/src/Components/redis/src/Handler/AbstractRedisHandler.php index 55802bd020..6e9701ceac 100644 --- a/src/Components/redis/src/Handler/AbstractRedisHandler.php +++ b/src/Components/redis/src/Handler/AbstractRedisHandler.php @@ -6,7 +6,7 @@ use Imi\Redis\Connector\RedisDriverConfig; -abstract class AbstractRedisHandler implements IRedisScanExMethod +abstract class AbstractRedisHandler implements IRedisScanMethod, IRedisHandler { protected RedisDriverConfig $config; diff --git a/src/Components/redis/src/Handler/IRedisHandler.php b/src/Components/redis/src/Handler/IRedisHandler.php index b8bcdbac7e..ae77917922 100644 --- a/src/Components/redis/src/Handler/IRedisHandler.php +++ b/src/Components/redis/src/Handler/IRedisHandler.php @@ -12,7 +12,7 @@ public function isCluster(): bool; public function isSupportSerialize(): bool; - public function _serialize(mixed $value): string; + public function _serialize(mixed $value): ?string; - public function _unserialize(string $value): mixed; + public function _unserialize(?string $value): mixed; } diff --git a/src/Components/redis/src/Handler/IRedisScanExMethod.php b/src/Components/redis/src/Handler/IRedisScanMethod.php similarity index 69% rename from src/Components/redis/src/Handler/IRedisScanExMethod.php rename to src/Components/redis/src/Handler/IRedisScanMethod.php index 97eb1c07f7..4d15ff0c94 100644 --- a/src/Components/redis/src/Handler/IRedisScanExMethod.php +++ b/src/Components/redis/src/Handler/IRedisScanMethod.php @@ -4,13 +4,13 @@ namespace Imi\Redis\Handler; -interface IRedisScanExMethod +interface IRedisScanMethod { - public function scanEach(?string $pattern = null, int $count = 0); + public function scanEach(?string $pattern = null, int $count = 0): \Generator; - public function hscanEach(string $key, ?string $pattern = null, int $count = 0); + public function hscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator; - public function sscanEach(string $key, ?string $pattern = null, int $count = 0); + public function sscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator; - public function zscanEach(string $key, ?string $pattern = null, int $count = 0); + public function zscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator; } diff --git a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php index 0e82086c45..cd5114ab95 100644 --- a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php @@ -31,6 +31,9 @@ public function __call(string $name, array $arguments): mixed return $this->client->{$name}(...$arguments); } + /** + * @return array> + */ public function getNodes(): array { return $this->client->_masters(); @@ -40,17 +43,16 @@ public function isConnected(): bool { foreach ($this->getNodes() as $node) { + /** @var array $node */ $this->client->ping($node); } return true; } - /** - * scan. - */ - public function scan(?int &$iterator, array|string $node, ?string $pattern = null, int $count = 0): array + public function scan(?int &$iterator, array|string $node, ?string $pattern = null, int $count = 0): array|false { + // @phpstan-ignore-next-line return $this->client->scan($iterator, $node, $pattern, $count); } @@ -58,14 +60,4 @@ public function isSupportSerialize(): bool { return true; } - - public function _serialize(mixed $value) - { - return $this->client->_serialize($value); - } - - public function _unserialize($value): mixed - { - return $this->client->_unserialize($value); - } } diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php index d4f88be984..f9338a6f50 100644 --- a/src/Components/redis/src/Handler/PhpRedisHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -39,8 +39,9 @@ public function isConnected(): bool return true === $result || '+PONG' === $result; } - public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ?string $type = null) + public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ?string $type = null): mixed { + // @phpstan-ignore-next-line return $this->client->scan($iterator, $pattern, $count, $type); } @@ -48,14 +49,4 @@ public function isSupportSerialize(): bool { return true; } - - public function _serialize(mixed $value) - { - return $this->client->_serialize($value); - } - - public function _unserialize($value): mixed - { - return $this->client->_unserialize($value); - } } diff --git a/src/Components/redis/src/Handler/PredisClusterHandler.php b/src/Components/redis/src/Handler/PredisClusterHandler.php index 77c128b37b..031f360d3a 100644 --- a/src/Components/redis/src/Handler/PredisClusterHandler.php +++ b/src/Components/redis/src/Handler/PredisClusterHandler.php @@ -72,10 +72,7 @@ public function __call(string $name, array $arguments): mixed return $result; } - /** - * scan. - */ - public function scan(string $node, $cursor, $options): array + public function scan(string $node, null|string|int $cursor, ?array $options): array { return $this->client->getClientBy('id', $node)->scan($cursor, $options); } @@ -89,8 +86,9 @@ public function getSlotGroupByKeys(array $keys): array { // https://gist.github.com/nrk/e07311af2316ea7e51719735274ded94 - /** @var \Predis\Cluster\StrategyInterface $strategy */ - $strategy = $this->client->getConnection()->getClusterStrategy(); + /** @var \Predis\Connection\Cluster\RedisCluster $connection */ + $connection = $this->client->getConnection(); + $strategy = $connection->getClusterStrategy(); $keysBySlot = []; foreach ($keys as $key) { @@ -113,14 +111,4 @@ public function isSupportSerialize(): bool { return false; } - - public function _serialize(mixed $value) - { - return $value; - } - - public function _unserialize($value): mixed - { - return $value; - } } diff --git a/src/Components/redis/src/Handler/PredisHandler.php b/src/Components/redis/src/Handler/PredisHandler.php index 32e895c949..2b57bdddf1 100644 --- a/src/Components/redis/src/Handler/PredisHandler.php +++ b/src/Components/redis/src/Handler/PredisHandler.php @@ -52,14 +52,4 @@ public function isSupportSerialize(): bool { return false; } - - public function _serialize(mixed $value) - { - return $value; - } - - public function _unserialize($value): mixed - { - return $value; - } } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index ec93fa9d22..f6f6117d35 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -89,12 +89,12 @@ protected static function getConnectionByInstance(IRedisHandler $handler): ?ICon protected static function unsetConnectionInstance(IRedisHandler $handler): bool { - /** @var object|null $ref */ - $ref = self::$instanceLinkConnectionMap[$handler] ?? null; - if (null !== $ref) + if (!isset(self::$instanceLinkConnectionMap[$handler])) { return true; } + /** @var object{count: int, connection: IConnection} $ref */ + $ref = self::$instanceLinkConnectionMap[$handler]; if ($ref->count > 1) { --$ref->count; diff --git a/src/Components/redis/src/Traits/TPhpRedisMethod.php b/src/Components/redis/src/Traits/TPhpRedisMethod.php index eb45ee0a1a..c7d0371595 100644 --- a/src/Components/redis/src/Traits/TPhpRedisMethod.php +++ b/src/Components/redis/src/Traits/TPhpRedisMethod.php @@ -4,8 +4,20 @@ namespace Imi\Redis\Traits; +use Imi\Redis\Handler\IRedisClusterHandler; + trait TPhpRedisMethod { + public function _serialize(mixed $value): ?string + { + return $this->client->_serialize($value); + } + + public function _unserialize(?string $value): mixed + { + return $this->client->_unserialize($value); + } + /** * eval扩展方法,结合了 eval、evalSha. * @@ -43,15 +55,16 @@ public function evalEx(string $script, ?array $args = null, ?int $numKeys = null /** * scan 方法的扩展简易遍历方法. */ - public function scanEach(?string $pattern = null, int $count = 0): mixed + public function scanEach(?string $pattern = null, int $count = 0): \Generator { - if ($this->isCluster()) + if ($this instanceof IRedisClusterHandler) { foreach ($this->getNodes() as $node) { $it = null; do { + // @phpstan-ignore-next-line $keys = $this->client->scan($it, $node, $pattern, $count); if ($keys) @@ -91,7 +104,7 @@ public function hscan(string $key, ?int &$iterator, ?string $pattern = null, int /** * hscan 方法的扩展简易遍历方法. */ - public function hscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + public function hscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $it = null; do @@ -116,7 +129,7 @@ public function sscan(string $key, ?int &$iterator, ?string $pattern = null, int /** * sscan 方法的扩展简易遍历方法. */ - public function sscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + public function sscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $it = null; do @@ -141,7 +154,7 @@ public function zscan(string $key, ?int &$iterator, ?string $pattern = null, int /** * zscan 方法的扩展简易遍历方法. */ - public function zscanEach(string $key, ?string $pattern = null, int $count = 0): mixed + public function zscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $it = null; do diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php index ada546c1e2..8a59f72aba 100644 --- a/src/Components/redis/src/Traits/TPredisMethod.php +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -4,14 +4,25 @@ namespace Imi\Redis\Traits; +use Imi\Redis\Handler\IRedisClusterHandler; use Predis\PredisException; trait TPredisMethod { + public function _serialize(mixed $value): ?string + { + return $value; + } + + public function _unserialize(?string $value): mixed + { + return $value; + } + public function getDBNum(): int { // 不建议使用,性能差 - if ($this->isCluster()) + if ($this instanceof IRedisClusterHandler) { return 0; } @@ -57,9 +68,9 @@ public function evalEx(string $script, ?array $args = null, ?int $numKeys = null } } - public function scanEach(?string $pattern = null, int $count = 0) + public function scanEach(?string $pattern = null, int $count = 0): \Generator { - if ($this->isCluster()) + if ($this instanceof IRedisClusterHandler) { foreach ($this->getNodes() as $node) { @@ -92,7 +103,7 @@ public function scanEach(?string $pattern = null, int $count = 0) } } - public function hscanEach(string $key, ?string $pattern = null, int $count = 0) + public function hscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $cursor = null; do @@ -107,7 +118,7 @@ public function hscanEach(string $key, ?string $pattern = null, int $count = 0) while ($cursor > 0); } - public function sscanEach(string $key, ?string $pattern = null, int $count = 0) + public function sscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $cursor = null; do @@ -122,7 +133,7 @@ public function sscanEach(string $key, ?string $pattern = null, int $count = 0) while ($cursor > 0); } - public function zscanEach(string $key, ?string $pattern = null, int $count = 0) + public function zscanEach(string $key, ?string $pattern = null, int $count = 0): \Generator { $cursor = null; do From 37cc4e2d0bdb898da4b6c4c46345798df490b9ad Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 17:32:06 +0800 Subject: [PATCH 23/97] =?UTF-8?q?Update:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/Redis.php | 72 +++---------------- src/Components/redis/src/RedisManager.php | 39 ++++++---- .../redis/src/Traits/TPhpRedisMethod.php | 1 + .../redis/src/Traits/TPredisMethod.php | 1 + 4 files changed, 39 insertions(+), 74 deletions(-) diff --git a/src/Components/redis/src/Redis.php b/src/Components/redis/src/Redis.php index 11cf7c63c9..238e9edfa7 100644 --- a/src/Components/redis/src/Redis.php +++ b/src/Components/redis/src/Redis.php @@ -253,17 +253,7 @@ class Redis public static function __callStatic(string $name, array $arguments): mixed { - if (RedisManager::isQuickFromRequestContext()) - { - return RedisManager::getInstance()->{$name}(...$arguments); - } - else - { - return RedisManager::use( - RedisManager::getDefaultPoolName(), - static fn (IConnection $resource, IRedisHandler $redis) => $redis->{$name}(...$arguments), - ); - } + return RedisManager::getInstance()->{$name}(...$arguments); } /** @@ -271,17 +261,9 @@ public static function __callStatic(string $name, array $arguments): mixed * 回调有 1 个参数:$instance(操作实例对象,Imi\Redis\Handler\IRedisHandler 类型) * 本方法返回值为回调的返回值 */ - public static function use(callable $callable, ?string $poolName = null, bool $forceUse = false): mixed + public static function use(callable $callable, ?string $poolName = null): mixed { - $poolName = RedisManager::parsePoolName($poolName); - if (!$forceUse && RedisManager::isQuickFromRequestContext() || !ConnectionCenter::hasConnectionManager($poolName)) - { - return $callable(RedisManager::getInstance($poolName)); - } - else - { - return RedisManager::use($poolName, static fn (IConnection $resource, IRedisHandler $redis) => $callable($redis)); - } + return RedisManager::use($poolName, static fn (IConnection $resource, IRedisHandler $redis) => $callable($redis)); } /** @@ -289,16 +271,8 @@ public static function use(callable $callable, ?string $poolName = null, bool $f */ public static function scan(?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (RedisManager::isQuickFromRequestContext()) - { - return RedisManager::getInstance()->scan($iterator, $pattern, $count); - } - else - { - return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use (&$iterator, $pattern, $count) { - return $redis->scan($iterator, $pattern, $count); - }); - } + // todo 只适用于 phpredis + return RedisManager::getInstance()->scan($iterator, $pattern, $count); } /** @@ -306,16 +280,8 @@ public static function scan(?int &$iterator, ?string $pattern = null, int $count */ public static function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (RedisManager::isQuickFromRequestContext()) - { - return RedisManager::getInstance()->hscan($key, $iterator, $pattern, $count); - } - else - { - return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->hscan($key, $iterator, $pattern, $count); - }); - } + // todo 只适用于 phpredis + return RedisManager::getInstance()->hscan($key, $iterator, $pattern, $count); } /** @@ -323,16 +289,8 @@ public static function hscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (RedisManager::isQuickFromRequestContext()) - { - return RedisManager::getInstance()->sscan($key, $iterator, $pattern, $count); - } - else - { - return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->sscan($key, $iterator, $pattern, $count); - }); - } + // todo 只适用于 phpredis + return RedisManager::getInstance()->sscan($key, $iterator, $pattern, $count); } /** @@ -340,15 +298,7 @@ public static function sscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - if (RedisManager::isQuickFromRequestContext()) - { - return RedisManager::getInstance()->zscan($key, $iterator, $pattern, $count); - } - else - { - return RedisManager::use(RedisManager::getDefaultPoolName(), static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->zscan($key, $iterator, $pattern, $count); - }); - } + // todo 只适用于 phpredis + return RedisManager::getInstance()->zscan($key, $iterator, $pattern, $count); } } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index f6f6117d35..a03ee09d3d 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -9,25 +9,35 @@ use Imi\ConnectionCenter\Enum\ConnectionStatus; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Redis\Handler\IRedisHandler; - +use Imi\Redis\Handler\PhpRedisClusterHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; + +/** + * @template InstanceLink of object{count: int, connection: IConnection} + */ class RedisManager { use \Imi\Util\Traits\TStaticClass; + /** + * @var \WeakMap + */ private static \WeakMap $instanceLinkConnectionMap; /** * 获取新的 Redis 连接实例. * * @param string|null $poolName 连接池名称 + * @return PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler */ public static function getNewInstance(?string $poolName = null): IRedisHandler { $poolName = self::parsePoolName($poolName); - $connection = ConnectionCenter::getConnection($poolName); + $manager = ConnectionCenter::getConnectionManager($poolName); /** @var IRedisHandler $instance */ - $instance = $connection->getInstance(); - self::recordInstanceLinkPool($instance, $connection); + $instance = $manager->getDriver()->createInstance(); return $instance; } @@ -36,6 +46,7 @@ public static function getNewInstance(?string $poolName = null): IRedisHandler * 获取 Redis 连接实例,每个RequestContext中共用一个. * * @param string $poolName 连接池名称 + * @return PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler */ public static function getInstance(?string $poolName = null): IRedisHandler { @@ -43,7 +54,6 @@ public static function getInstance(?string $poolName = null): IRedisHandler $connection = ConnectionCenter::getRequestContextConnection($poolName); /** @var IRedisHandler $instance */ $instance = $connection->getInstance(); - self::recordInstanceLinkPool($instance, $connection); return $instance; } @@ -53,18 +63,19 @@ public static function getInstance(?string $poolName = null): IRedisHandler * 回调有两个参数:$connection(连接对象), $instance(操作实例对象,Redis实例) * 本方法返回值为回调的返回值 */ - public static function use(string $name, callable $callback): mixed + public static function use(?string $poolName, callable $callable): mixed { - $resource = static::getNewInstance($name); - try + $poolName = self::parsePoolName($poolName); + + if (ConnectionCenter::hasConnectionManager($poolName)) { - $connection = self::getConnectionByInstance($resource); + $connection = ConnectionCenter::getConnection($poolName); - return $callback($connection, $resource); + return $callable($connection->getInstance()); } - finally + else { - static::release($resource); + return $callable(static::getInstance($poolName)); } } @@ -93,7 +104,7 @@ protected static function unsetConnectionInstance(IRedisHandler $handler): bool { return true; } - /** @var object{count: int, connection: IConnection} $ref */ + /** @var InstanceLink $ref */ $ref = self::$instanceLinkConnectionMap[$handler]; if ($ref->count > 1) { @@ -111,6 +122,7 @@ protected static function unsetConnectionInstance(IRedisHandler $handler): bool /** * 释放 Redis 连接实例. + * @deprecated */ public static function release(IRedisHandler $redis): void { @@ -148,6 +160,7 @@ public static function getDefaultPoolName(): string /** * 从当前上下文中获取公用连接. + * @deprecated */ public static function isQuickFromRequestContext(): bool { diff --git a/src/Components/redis/src/Traits/TPhpRedisMethod.php b/src/Components/redis/src/Traits/TPhpRedisMethod.php index c7d0371595..5b9d3b7d6a 100644 --- a/src/Components/redis/src/Traits/TPhpRedisMethod.php +++ b/src/Components/redis/src/Traits/TPhpRedisMethod.php @@ -77,6 +77,7 @@ public function scanEach(?string $pattern = null, int $count = 0): \Generator } else { + /** @var int|null $it */ $it = null; do { diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php index 8a59f72aba..f31feb109e 100644 --- a/src/Components/redis/src/Traits/TPredisMethod.php +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -77,6 +77,7 @@ public function scanEach(?string $pattern = null, int $count = 0): \Generator $cursor = null; do { + // @phpstan-ignore-next-line $result = $this->scan("{$node[0]}:{$node[1]}", $cursor, ['match' => $pattern, 'count' => $count]); [$cursor, $keys] = $result; if ($keys) From 75bc666ebe4d5b1de84028ca70df4bf0d7fd59a9 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 17:42:55 +0800 Subject: [PATCH 24/97] =?UTF-8?q?Update:=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/phpstan.yml | 1 - src/Components/redis/src/Redis.php | 22 ++++-- src/Components/redis/src/RedisManager.php | 91 ++--------------------- 3 files changed, 23 insertions(+), 91 deletions(-) diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index d48973e082..854b497b41 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -18,7 +18,6 @@ concurrency: jobs: phpstan: runs-on: ubuntu-latest - if: false strategy: fail-fast: false matrix: diff --git a/src/Components/redis/src/Redis.php b/src/Components/redis/src/Redis.php index 238e9edfa7..faccb9ae82 100644 --- a/src/Components/redis/src/Redis.php +++ b/src/Components/redis/src/Redis.php @@ -5,7 +5,6 @@ namespace Imi\Redis; use Imi\ConnectionCenter\Contract\IConnection; -use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Pool\Interfaces\IPoolResource; use Imi\Redis\Handler\IRedisHandler; @@ -253,7 +252,10 @@ class Redis public static function __callStatic(string $name, array $arguments): mixed { - return RedisManager::getInstance()->{$name}(...$arguments); + return RedisManager::use( + null, + static fn (IConnection $resource, IRedisHandler $redis) => $redis->{$name}(...$arguments), + ); } /** @@ -272,7 +274,9 @@ public static function use(callable $callable, ?string $poolName = null): mixed public static function scan(?int &$iterator, ?string $pattern = null, int $count = 0): mixed { // todo 只适用于 phpredis - return RedisManager::getInstance()->scan($iterator, $pattern, $count); + return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use (&$iterator, $pattern, $count) { + return $redis->scan($iterator, $pattern, $count); + }); } /** @@ -281,7 +285,9 @@ public static function scan(?int &$iterator, ?string $pattern = null, int $count public static function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { // todo 只适用于 phpredis - return RedisManager::getInstance()->hscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return $redis->hscan($key, $iterator, $pattern, $count); + }); } /** @@ -290,7 +296,9 @@ public static function hscan(string $key, ?int &$iterator, ?string $pattern = nu public static function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { // todo 只适用于 phpredis - return RedisManager::getInstance()->sscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return $redis->sscan($key, $iterator, $pattern, $count); + }); } /** @@ -299,6 +307,8 @@ public static function sscan(string $key, ?int &$iterator, ?string $pattern = nu public static function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { // todo 只适用于 phpredis - return RedisManager::getInstance()->zscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + return $redis->zscan($key, $iterator, $pattern, $count); + }); } } diff --git a/src/Components/redis/src/RedisManager.php b/src/Components/redis/src/RedisManager.php index a03ee09d3d..ae88c7c8a0 100644 --- a/src/Components/redis/src/RedisManager.php +++ b/src/Components/redis/src/RedisManager.php @@ -5,8 +5,6 @@ namespace Imi\Redis; use Imi\Config; -use Imi\ConnectionCenter\Contract\IConnection; -use Imi\ConnectionCenter\Enum\ConnectionStatus; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Redis\Handler\IRedisHandler; use Imi\Redis\Handler\PhpRedisClusterHandler; @@ -14,48 +12,38 @@ use Imi\Redis\Handler\PredisClusterHandler; use Imi\Redis\Handler\PredisHandler; -/** - * @template InstanceLink of object{count: int, connection: IConnection} - */ class RedisManager { use \Imi\Util\Traits\TStaticClass; - /** - * @var \WeakMap - */ - private static \WeakMap $instanceLinkConnectionMap; - /** * 获取新的 Redis 连接实例. * * @param string|null $poolName 连接池名称 + * * @return PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler */ public static function getNewInstance(?string $poolName = null): IRedisHandler { $poolName = self::parsePoolName($poolName); $manager = ConnectionCenter::getConnectionManager($poolName); - /** @var IRedisHandler $instance */ - $instance = $manager->getDriver()->createInstance(); - return $instance; + return $manager->getDriver()->createInstance(); } /** * 获取 Redis 连接实例,每个RequestContext中共用一个. * * @param string $poolName 连接池名称 + * * @return PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler */ public static function getInstance(?string $poolName = null): IRedisHandler { $poolName = self::parsePoolName($poolName); $connection = ConnectionCenter::getRequestContextConnection($poolName); - /** @var IRedisHandler $instance */ - $instance = $connection->getInstance(); - return $instance; + return $connection->getInstance(); } /** @@ -71,69 +59,13 @@ public static function use(?string $poolName, callable $callable): mixed { $connection = ConnectionCenter::getConnection($poolName); - return $callable($connection->getInstance()); - } - else - { - return $callable(static::getInstance($poolName)); - } - } - - protected static function recordInstanceLinkPool(IRedisHandler $handler, IConnection $connection): void - { - if (!isset(self::$instanceLinkConnectionMap)) - { - self::$instanceLinkConnectionMap = new \WeakMap(); - } - - $ref = self::$instanceLinkConnectionMap[$handler] ?? new \stdClass(); - $ref->connection = $connection; - $ref->count = ($ref->count ?? 0) + 1; - - self::$instanceLinkConnectionMap[$handler] = $ref; - } - - protected static function getConnectionByInstance(IRedisHandler $handler): ?IConnection - { - return (self::$instanceLinkConnectionMap[$handler] ?? null)?->connection; - } - - protected static function unsetConnectionInstance(IRedisHandler $handler): bool - { - if (!isset(self::$instanceLinkConnectionMap[$handler])) - { - return true; - } - /** @var InstanceLink $ref */ - $ref = self::$instanceLinkConnectionMap[$handler]; - if ($ref->count > 1) - { - --$ref->count; - - return false; + return $callable($connection, $connection->getInstance()); } else { - unset(self::$instanceLinkConnectionMap[$handler]); + $connection = ConnectionCenter::getRequestContextConnection($poolName); - return true; - } - } - - /** - * 释放 Redis 连接实例. - * @deprecated - */ - public static function release(IRedisHandler $redis): void - { - $connection = self::getConnectionByInstance($redis); - if (null === $connection) - { - throw new \RuntimeException('RedisHandler is not a valid connection center connection instance'); - } - if (self::unsetConnectionInstance($redis)) - { - ConnectionStatus::Available === $connection->getStatus() && $connection->release(); + return $callable($connection, $connection->getInstance()); } } @@ -157,13 +89,4 @@ public static function getDefaultPoolName(): string { return Config::get('@currentServer.redis.defaultPool'); } - - /** - * 从当前上下文中获取公用连接. - * @deprecated - */ - public static function isQuickFromRequestContext(): bool - { - return Config::get('@currentServer.redis.quickFromRequestContext', true); - } } From 80353abc043b3f590cce70fe9c219ead9640ebeb Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 19 Feb 2024 18:54:30 +0800 Subject: [PATCH 25/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cache/Handler/Redis.php | 16 +++++++-------- src/Cache/Handler/RedisHash.php | 14 ++++++------- .../amqp/src/Queue/AMQPQueueDriverHandler.php | 14 ++++++------- .../queue/src/Driver/RedisQueueDriver.php | 20 +++++++++---------- .../src/Driver/RedisStreamQueueDriver.php | 20 +++++++++---------- .../StoreHandler/MemoryTable.php | 2 +- src/Lock/Handler/Redis.php | 4 ++-- .../ConnectionContext/StoreHandler/Redis.php | 2 +- src/Server/Group/Handler/Redis.php | 2 +- src/Server/Session/Handler/Redis.php | 6 +++--- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Cache/Handler/Redis.php b/src/Cache/Handler/Redis.php index 7999a37729..7cf31c99d1 100644 --- a/src/Cache/Handler/Redis.php +++ b/src/Cache/Handler/Redis.php @@ -31,7 +31,7 @@ class Redis extends Base */ public function get(string $key, mixed $default = null): mixed { - $result = ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->get($this->parseKey($key)), $this->poolName, true); + $result = ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->get($this->parseKey($key)), $this->poolName); if (false === $result) { return $default; @@ -53,7 +53,7 @@ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = nul $ttl = DateTime::getSecondsByInterval($ttl); } - return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->set($this->parseKey($key), $this->encode($value), $ttl), $this->poolName, true); + return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->set($this->parseKey($key), $this->encode($value), $ttl), $this->poolName); } /** @@ -61,7 +61,7 @@ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = nul */ public function delete(string $key): bool { - return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->del($this->parseKey($key)) > 0, $this->poolName, true); + return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->del($this->parseKey($key)) > 0, $this->poolName); } /** @@ -69,7 +69,7 @@ public function delete(string $key): bool */ public function clear(): bool { - return (bool) ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->flushDB(), $this->poolName, true); + return (bool) ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->flushDB(), $this->poolName); } /** @@ -81,7 +81,7 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable { $key = $this->parseKey($key); } - $mgetResult = ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->mget($keys), $this->poolName, true); + $mgetResult = ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->mget($keys), $this->poolName); $result = []; if ($mgetResult) { @@ -142,7 +142,7 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null } return true; - }, $this->poolName, true); + }, $this->poolName); return (bool) $result; } @@ -157,7 +157,7 @@ public function deleteMultiple(iterable $keys): bool $key = $this->parseKey($key); } - return (bool) ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->del($keys), $this->poolName, true); + return (bool) ImiRedis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->del($keys), $this->poolName); } /** @@ -165,7 +165,7 @@ public function deleteMultiple(iterable $keys): bool */ public function has(string $key): bool { - return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->exists($this->parseKey($key)), $this->poolName, true); + return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->exists($this->parseKey($key)), $this->poolName); } /** diff --git a/src/Cache/Handler/RedisHash.php b/src/Cache/Handler/RedisHash.php index dc87f648ee..1af097a9d8 100644 --- a/src/Cache/Handler/RedisHash.php +++ b/src/Cache/Handler/RedisHash.php @@ -58,7 +58,7 @@ class RedisHash extends Base public function get(string $key, mixed $default = null): mixed { $this->parseKey($key, $member); - $result = Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->hGet($key, $member), $this->poolName, true); + $result = Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->hGet($key, $member), $this->poolName); if (false === $result) { return $default; @@ -76,7 +76,7 @@ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = nul { $this->parseKey($key, $member); - return false !== Redis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->hSet($key, $member, $this->encode($value)), $this->poolName, true); + return false !== Redis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->hSet($key, $member, $this->encode($value)), $this->poolName); } /** @@ -103,7 +103,7 @@ public function delete(string $key): bool */ public function clear(): bool { - return (bool) Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->flushDB(), $this->poolName, true); + return (bool) Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->flushDB(), $this->poolName); } /** @@ -142,7 +142,7 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -179,7 +179,7 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null } return true; - }, $this->poolName, true); + }, $this->poolName); return (bool) $result; } @@ -210,7 +210,7 @@ public function deleteMultiple(iterable $keys): bool } return true; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -220,7 +220,7 @@ public function has(string $key): bool { $this->parseKey($key, $member); - return (bool) Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->hExists($key, $member), $this->poolName, true); + return (bool) Redis::use(static fn (\Imi\Redis\RedisHandler $redis) => $redis->hExists($key, $member), $this->poolName); } /** diff --git a/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php b/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php index ff15466581..f7b2a92203 100644 --- a/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php +++ b/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php @@ -281,7 +281,7 @@ public function push(IMessage $message, float $delay = 0, array $options = []): } return $messageId; - }, $this->redisPoolName, true); + }, $this->redisPoolName); } /** @@ -335,7 +335,7 @@ public function pop(float $timeout = 0): ?IMessage Redis::use(function (\Imi\Redis\RedisHandler $redis) use ($score, $message): void { $redis->zAdd($this->getRedisQueueKey(QueueType::Working), $score, json_encode($message->toArray(), \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); - }, $this->redisPoolName, true); + }, $this->redisPoolName); return $message; } @@ -354,7 +354,7 @@ public function pop(float $timeout = 0): ?IMessage */ public function delete(IMessage $message): bool { - return Redis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->sAdd($this->getRedisQueueKey('deleted'), $message->getMessageId()) > 0, $this->redisPoolName, true); + return Redis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->sAdd($this->getRedisQueueKey('deleted'), $message->getMessageId()) > 0, $this->redisPoolName); } /** @@ -408,7 +408,7 @@ public function clear(?IQueueType $queueType = null): void { } } - }, $this->redisPoolName, true); + }, $this->redisPoolName); } /** @@ -537,7 +537,7 @@ public function status(): QueueStatus $status['delay'] = $delayReady; return new QueueStatus($status); - }, $this->redisPoolName, true); + }, $this->redisPoolName); } /** @@ -639,7 +639,7 @@ protected function parseTimeoutMessages(int $count = 100): void $amqpMessage->setRoutingKey(AMQPQueueDriver::ROUTING_TIMEOUT); $this->timeoutPublisher->publish($amqpMessage); } - }, $this->redisPoolName, true); + }, $this->redisPoolName); } /** @@ -661,6 +661,6 @@ protected function messageIsDeleted(string $messageId, bool $delete = true): boo $this->getRedisQueueKey('deleted'), $redis->_serialize($messageId), $delete, - ], 1) > 0, $this->redisPoolName, true); + ], 1) > 0, $this->redisPoolName); } } diff --git a/src/Components/queue/src/Driver/RedisQueueDriver.php b/src/Components/queue/src/Driver/RedisQueueDriver.php index 1daf4f9f6f..961bc7e19b 100644 --- a/src/Components/queue/src/Driver/RedisQueueDriver.php +++ b/src/Components/queue/src/Driver/RedisQueueDriver.php @@ -61,7 +61,7 @@ public function __init(): void { $this->keyName = $this->name; } - }, $this->poolName, true); + }, $this->poolName); } /** @@ -167,7 +167,7 @@ public function push(IMessage $message, float $delay = 0, array $options = []): } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -234,7 +234,7 @@ public function pop(float $timeout = 0): ?IMessage } return $result; - }, $this->poolName, true); + }, $this->poolName); if ($result && \is_array($result)) { $data = []; @@ -295,7 +295,7 @@ public function delete(IMessage $message): bool } return 1 == $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -319,7 +319,7 @@ public function clear(?IQueueType $queueType = null): void Redis::use(static function (\Imi\Redis\RedisHandler $redis) use ($keys): void { $redis->del(...$keys); - }, $this->poolName, true); + }, $this->poolName); } /** @@ -356,7 +356,7 @@ public function success(IMessage $message): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -389,7 +389,7 @@ public function fail(IMessage $message, bool $requeue = false): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -411,7 +411,7 @@ public function status(): QueueStatus } return new QueueStatus($status); - }, $this->poolName, true); + }, $this->poolName); } /** @@ -445,7 +445,7 @@ public function restoreFailMessages(): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -479,7 +479,7 @@ public function restoreTimeoutMessages(): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** diff --git a/src/Components/queue/src/Driver/RedisStreamQueueDriver.php b/src/Components/queue/src/Driver/RedisStreamQueueDriver.php index cbaff72988..67f130815b 100644 --- a/src/Components/queue/src/Driver/RedisStreamQueueDriver.php +++ b/src/Components/queue/src/Driver/RedisStreamQueueDriver.php @@ -95,7 +95,7 @@ public function __init(): void { $this->keyName = $this->name; } - }, $this->poolName, true); + }, $this->poolName); } /** @@ -142,7 +142,7 @@ public function push(IMessage $message, float $delay = 0, array $options = []): } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -176,7 +176,7 @@ public function pop(float $timeout = 0): ?IMessage $message->loadFromArray($data); return $message; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -200,7 +200,7 @@ public function delete(IMessage $message): bool } return 1 == $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -210,7 +210,7 @@ public function clear(?IQueueType $queueType = null): void { Redis::use(function (\Imi\Redis\RedisHandler $redis): void { $redis->del($this->getQueueKey()); - }, $this->poolName, true); + }, $this->poolName); } /** @@ -236,7 +236,7 @@ public function success(IMessage $message): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -277,7 +277,7 @@ public function fail(IMessage $message, bool $requeue = false): int return $result ? 1 : 0; } - }, $this->poolName, true); + }, $this->poolName); } /** @@ -332,7 +332,7 @@ public function status(): QueueStatus $status['ready'] = $status['timeout'] = $status['delay'] = 0; return new QueueStatus($status); - }, $this->poolName, true); + }, $this->poolName); } /** @@ -388,7 +388,7 @@ public function restoreFailMessages(): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** @@ -464,7 +464,7 @@ public function restoreTimeoutMessages(): int } return $result; - }, $this->poolName, true); + }, $this->poolName); } /** diff --git a/src/Components/swoole/src/Server/ConnectionContext/StoreHandler/MemoryTable.php b/src/Components/swoole/src/Server/ConnectionContext/StoreHandler/MemoryTable.php index 731eb26e7c..b7189a94af 100644 --- a/src/Components/swoole/src/Server/ConnectionContext/StoreHandler/MemoryTable.php +++ b/src/Components/swoole/src/Server/ConnectionContext/StoreHandler/MemoryTable.php @@ -294,6 +294,6 @@ private function useRedis(callable $callback): mixed } return $callback($redis); - }, $this->redisPool, true); + }, $this->redisPool); } } diff --git a/src/Lock/Handler/Redis.php b/src/Lock/Handler/Redis.php index 4929db9663..1a8157cc11 100644 --- a/src/Lock/Handler/Redis.php +++ b/src/Lock/Handler/Redis.php @@ -111,7 +111,7 @@ protected function __tryLock(): bool $this->guid, $this->db, $this->lockExpire, - ], 1), $this->poolName, true); + ], 1), $this->poolName); } /** @@ -139,6 +139,6 @@ protected function __unlock(): bool ], 1); return $result > 0; - }, $this->poolName, true); + }, $this->poolName); } } diff --git a/src/Server/ConnectionContext/StoreHandler/Redis.php b/src/Server/ConnectionContext/StoreHandler/Redis.php index dd5d19d849..a06ab12df6 100644 --- a/src/Server/ConnectionContext/StoreHandler/Redis.php +++ b/src/Server/ConnectionContext/StoreHandler/Redis.php @@ -285,7 +285,7 @@ private function useRedis(callable $callback): mixed } return $callback($redis); - }, $this->redisPool, true); + }, $this->redisPool); } /** diff --git a/src/Server/Group/Handler/Redis.php b/src/Server/Group/Handler/Redis.php index 33eee0e55f..cd221f2f18 100644 --- a/src/Server/Group/Handler/Redis.php +++ b/src/Server/Group/Handler/Redis.php @@ -328,6 +328,6 @@ private function useRedis(callable $callback): mixed } return $callback($redis); - }, $this->redisPool, true); + }, $this->redisPool); } } diff --git a/src/Server/Session/Handler/Redis.php b/src/Server/Session/Handler/Redis.php index 4e5945152d..14fc880249 100644 --- a/src/Server/Session/Handler/Redis.php +++ b/src/Server/Session/Handler/Redis.php @@ -37,7 +37,7 @@ public function destroy(string $sessionId): void { ImiRedis::use(function (\Imi\Redis\RedisHandler $redis) use ($sessionId): void { $redis->del($this->getKey($sessionId)); - }, $this->poolName, true); + }, $this->poolName); } /** @@ -53,7 +53,7 @@ public function gc(int $maxLifeTime): void */ public function read(string $sessionId): string { - return ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->get($this->getKey($sessionId)), $this->poolName, true) ?: ''; + return ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->get($this->getKey($sessionId)), $this->poolName) ?: ''; } /** @@ -63,7 +63,7 @@ public function write(string $sessionId, string $sessionData, int $maxLifeTime): { ImiRedis::use(function (\Imi\Redis\RedisHandler $redis) use ($sessionId, $sessionData, $maxLifeTime): void { $redis->set($this->getKey($sessionId), $sessionData, $maxLifeTime); - }, $this->poolName, true); + }, $this->poolName); } /** From bfa71914c53b1aa2926b5f3973a8951b6457a741 Mon Sep 17 00:00:00 2001 From: auooru Date: Wed, 6 Mar 2024 20:47:07 +0800 Subject: [PATCH 26/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cache/Handler/RedisHash.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cache/Handler/RedisHash.php b/src/Cache/Handler/RedisHash.php index 1af097a9d8..ea738c5e3f 100644 --- a/src/Cache/Handler/RedisHash.php +++ b/src/Cache/Handler/RedisHash.php @@ -95,7 +95,7 @@ public function delete(string $key): bool { return $redis->hDel($key, $member) > 0; } - }, $this->poolName, true); + }, $this->poolName); } /** From ab5eebc43c550fbdea23ef7c103c7f2fd89b959c Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:27:08 +0800 Subject: [PATCH 27/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E6=83=85=E5=86=B5=E4=B8=8B=E5=BC=BA=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/Handler/PhpRedisHandler.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php index f9338a6f50..b113bd99fb 100644 --- a/src/Components/redis/src/Handler/PhpRedisHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -41,8 +41,13 @@ public function isConnected(): bool public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ?string $type = null): mixed { + $args = []; + if (null !== $type) + { + $args[] = $type; + } // @phpstan-ignore-next-line - return $this->client->scan($iterator, $pattern, $count, $type); + return $this->client->scan($iterator, $pattern, $count, ...$args); } public function isSupportSerialize(): bool From 085fbd0f970ecb0e12afe615bef1f1f25e7b632c Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:27:54 +0800 Subject: [PATCH 28/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/Traits/TPredisMethod.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/redis/src/Traits/TPredisMethod.php b/src/Components/redis/src/Traits/TPredisMethod.php index f31feb109e..9cfd1a292e 100644 --- a/src/Components/redis/src/Traits/TPredisMethod.php +++ b/src/Components/redis/src/Traits/TPredisMethod.php @@ -53,7 +53,7 @@ public function evalEx(string $script, ?array $args = null, ?int $numKeys = null try { - return $client->evalSha($sha1, $numKeys, ...$args); + return $client->evalsha($sha1, $numKeys, ...$args); } catch (PredisException $exception) { From 7f5b7cabf5d936f27b4262b8770efdfde315e895 Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:28:44 +0800 Subject: [PATCH 29/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E5=AF=B9?= =?UTF-8?q?=E9=9D=99=E6=80=81=E8=B0=83=E7=94=A8=20scan=20=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/Redis.php | 62 +++++-- .../redis/tests/Tests/PhpRedisTest.php | 165 ++++++++++++++++++ .../redis/tests/Tests/RedisManagerTest.php | 104 ----------- .../redis/tests/Tests/RedisTest.php | 78 --------- src/Components/redis/tests/phpunit.xml | 2 +- 5 files changed, 214 insertions(+), 197 deletions(-) delete mode 100644 src/Components/redis/tests/Tests/RedisManagerTest.php diff --git a/src/Components/redis/src/Redis.php b/src/Components/redis/src/Redis.php index faccb9ae82..a884bc2823 100644 --- a/src/Components/redis/src/Redis.php +++ b/src/Components/redis/src/Redis.php @@ -5,8 +5,12 @@ namespace Imi\Redis; use Imi\ConnectionCenter\Contract\IConnection; -use Imi\Pool\Interfaces\IPoolResource; +use Imi\Redis\Handler\IRedisClusterHandler; use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisClusterHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; /** * Redis 快捷操作类. @@ -265,7 +269,7 @@ public static function __callStatic(string $name, array $arguments): mixed */ public static function use(callable $callable, ?string $poolName = null): mixed { - return RedisManager::use($poolName, static fn (IConnection $resource, IRedisHandler $redis) => $callable($redis)); + return RedisManager::use($poolName, static fn (IConnection $connection, IRedisHandler $redis) => $callable($redis)); } /** @@ -273,9 +277,18 @@ public static function use(callable $callable, ?string $poolName = null): mixed */ public static function scan(?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - // todo 只适用于 phpredis - return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use (&$iterator, $pattern, $count) { - return $redis->scan($iterator, $pattern, $count); + return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use (&$iterator, $pattern, $count) { + if ($redis instanceof PhpRedisHandler) { + return $redis->scan($iterator, $pattern, $count); + } elseif ($redis instanceof PredisHandler) { + [$cursor, $keys] = $redis->scan($iterator, ['match' => $pattern, 'count' => $count]); + $iterator = (int) $cursor; + return $keys; + } elseif ($redis instanceof IRedisClusterHandler) { + throw new \RuntimeException('redis cluster handler not support scan proxy, please use scanEach method'); + } else { + throw new \RuntimeException('unknown redis handler'); + } }); } @@ -284,9 +297,16 @@ public static function scan(?int &$iterator, ?string $pattern = null, int $count */ public static function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - // todo 只适用于 phpredis - return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->hscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + return $redis->hscan($key, $iterator, $pattern, $count); + } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + [$cursor, $keys] = $redis->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]); + $iterator = (int) $cursor; + return $keys; + } else { + throw new \RuntimeException('redis handler not support'); + } }); } @@ -295,9 +315,16 @@ public static function hscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - // todo 只适用于 phpredis - return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->sscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + return $redis->sscan($key, $iterator, $pattern, $count); + } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + [$cursor, $keys] = $redis->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]); + $iterator = (int) $cursor; + return $keys; + } else { + throw new \RuntimeException('redis handler not support'); + } }); } @@ -306,9 +333,16 @@ public static function sscan(string $key, ?int &$iterator, ?string $pattern = nu */ public static function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { - // todo 只适用于 phpredis - return RedisManager::use(null, static function (IPoolResource $resource, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - return $redis->zscan($key, $iterator, $pattern, $count); + return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + return $redis->zscan($key, $iterator, $pattern, $count); + } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + [$cursor, $keys] = $redis->zscan($key, $iterator, ['match' => $pattern, 'count' => $count]); + $iterator = (int) $cursor; + return $keys; + } else { + throw new \RuntimeException('redis handler not support'); + } }); } } diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php index a3e6468462..3976d072a1 100644 --- a/src/Components/redis/tests/Tests/PhpRedisTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -4,12 +4,17 @@ namespace Imi\Redis\Test\Tests; +use Imi\Config; +use Imi\Redis\Handler\IRedisClusterHandler; use Imi\Redis\Handler\IRedisHandler; use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Redis; use Imi\Redis\RedisManager; +use Imi\RequestContext; use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; +use Predis\Collection\Iterator\Keyspace; /** * @template T of PhpRedisHandler @@ -183,4 +188,164 @@ public function testGeoAdd(IRedisHandler $redis): void $redis->setOption(\Redis::OPT_SERIALIZER, $oriOption); } + + protected function staticContextWarp(callable $fn): void + { + $defaultName = RedisManager::getDefaultPoolName(); + // Config::get() + self::assertTrue(Config::set('@app.redis.defaultPool', $this->driveName)); + self::assertEquals($this->driveName, RedisManager::getDefaultPoolName()); + try { + $fn(); + } finally { + Config::set('@app.redis.defaultPool', $defaultName); + } + } + + #[Depends('testGetDrive')] + public function testStaticCall(): void + { + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $this->staticContextWarp(function () use ($prefix) { + Redis::set($prefix, '123456'); + self::assertEquals('123456', Redis::get($prefix)); + self::assertTrue(Redis::del($prefix) > 0); + }); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testStaticCallScan(IRedisHandler $redis): void + { + if ($redis instanceof IRedisClusterHandler) { + self::markTestSkipped('RedisClusterHandler does not support hscan'); + } + + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $this->staticContextWarp(function () use ($redis, $prefix) { + $excepted = $map = []; + for ($i = 0; $i < 100; ++$i) + { + $key = $prefix . ':scanEach:' . $i; + $excepted[$key] = 1; + $map[$key] = 0; + $redis->set($key, $i); + } + + $map = []; + do { + $keys = Redis::scan($it, $prefix . ':scanEach:*', 10); + foreach ($keys as $key) { + $map[$key] = 1; + } + } while ($it != 0); + self::assertEquals($excepted, $map); + self::assertTrue(Redis::del(\array_keys($excepted)) > 0); + }); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testStaticCallHScan(IRedisHandler $redis): void + { + if ($redis instanceof IRedisClusterHandler) { + self::markTestSkipped('RedisClusterHandler does not support hscan'); + } + + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $this->staticContextWarp(function () use ($redis, $prefix) { + $excepted = $map = $values = $exceptedValues = []; + $key = $prefix . ':hscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $member = 'value:' . $i; + $excepted[$member] = 1; + $map[$member] = 0; + $values[$member] = -1; + $exceptedValues[$member] = $i; + $redis->hSet($key, $member, $i); + } + do { + $items = Redis::hscan($key, $it, 'value:*', 10); + foreach ($items as $k => $value) { + $map[$k] = 1; + $values[$k] = $value; + } + } while ($it > 0); + self::assertEquals($excepted, $map); + self::assertEquals($exceptedValues, $values); + self::assertTrue(Redis::del($key) > 0); + }); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testStaticCallSScan(IRedisHandler $redis): void + { + if ($redis instanceof IRedisClusterHandler) { + self::markTestSkipped('RedisClusterHandler does not support sscan'); + } + + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $this->staticContextWarp(function () use ($redis, $prefix) { + $excepted = $map = []; + $key = $prefix . ':sscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $value = 'value:' . $i; + $excepted[$value] = 1; + $map[$value] = 0; + $redis->sAdd($key, $value); + } + do { + $items = Redis::sscan($key, $it, '*', 10); + foreach ($items as $value) { + $map[$value] = 1; + } + } while ($it > 0); + self::assertEquals($excepted, $map); + self::assertTrue(Redis::del($key) > 0); + }); + } + + /** + * @phpstan-param PhpRedisHandler $redis + */ + #[Depends('testGetDrive')] + public function testStaticCallZScan(IRedisHandler $redis): void + { + if ($redis instanceof IRedisClusterHandler) { + self::markTestSkipped('RedisClusterHandler does not support zscan'); + } + + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $this->staticContextWarp(function () use ($redis, $prefix) { + $excepted = $map = []; + $key = $prefix . ':zscanEach'; + $redis->del($key); + for ($i = 0; $i < 100; ++$i) + { + $value = 'value:' . $i; + $excepted[$i] = 1; + $map[$i] = 0; + $redis->zAdd($key, $i, $value); + } + do { + $items = Redis::zscan($key, $it, '*', 10); + foreach ($items as $score) { + $map[$score] = 1; + } + } while ($it > 0); + self::assertEquals($excepted, $map); + self::assertTrue(Redis::del($key) > 0); + }); + } } diff --git a/src/Components/redis/tests/Tests/RedisManagerTest.php b/src/Components/redis/tests/Tests/RedisManagerTest.php deleted file mode 100644 index 89532736d6..0000000000 --- a/src/Components/redis/tests/Tests/RedisManagerTest.php +++ /dev/null @@ -1,104 +0,0 @@ -markTestSkipped('Deprecated Test'); - } - - public function testDefaultPoolName(): void - { - Assert::assertEquals('redis_test', RedisManager::getDefaultPoolName()); - } - - public function testGetInstance(): void - { - $a = RedisManager::getInstance(self::CONNECTION_NAME); - $b = RedisManager::getInstance(self::CONNECTION_NAME); - $this->assertEquals(spl_object_id($a), spl_object_id($b)); - $value = 'imi' . bin2hex(random_bytes(4)); - $a->set('test', $value); - $this->assertEquals($value, $a->get('test')); - } - - public function testGetNewInstance(): void - { - $a = RedisManager::getInstance(self::CONNECTION_NAME); - $b = RedisManager::getNewInstance(self::CONNECTION_NAME); - $this->assertNotEquals(spl_object_id($a), spl_object_id($b)); - $value = 'imi' . bin2hex(random_bytes(4)); - $b->set('test', $value); - $this->assertEquals($value, $b->get('test')); - } - - public function testNewInstance(): void - { - $pool = PoolManager::getInstance('redis_manager_test'); - $instance = null; - try - { - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(1, $pool->getFree()); - - $instance = RedisManager::getNewInstance('redis_manager_test'); - - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(0, $pool->getFree()); - $this->assertRedisHandler($instance); - } - finally - { - if (null !== $instance) - { - RedisManager::release($instance); - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(1, $pool->getFree()); - } - } - } - - public function testInstance(): void - { - $pool = PoolManager::getInstance('redis_manager_test'); - $this->go(function () use ($pool): void { - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(1, $pool->getFree()); - - $instance = RedisManager::getInstance('redis_manager_test'); - - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(0, $pool->getFree()); - - $this->assertRedisHandler($instance); - }); - sleep(1); - Assert::assertEquals(1, $pool->getCount()); - Assert::assertEquals(0, $pool->getFree()); - } - - private function assertRedisHandler(IRedisHandler $redisHandler): void - { - Assert::assertInstanceOf(IRedisHandler::class, $redisHandler); - $str = bin2hex(random_bytes(8)); - $redisHandler->set('imi:test:a', $str); - Assert::assertEquals($str, $redisHandler->get('imi:test:a')); - } -} diff --git a/src/Components/redis/tests/Tests/RedisTest.php b/src/Components/redis/tests/Tests/RedisTest.php index 9048d99f50..56aea9a897 100644 --- a/src/Components/redis/tests/Tests/RedisTest.php +++ b/src/Components/redis/tests/Tests/RedisTest.php @@ -64,84 +64,6 @@ public function testEvalEx2(): void Assert::assertEquals('imi very 6', $value); } - public function testScanEach(): void - { - $excepted = $map = []; - for ($i = 0; $i < 100; ++$i) - { - $key = 'imi:scanEach:' . $i; - $excepted[$key] = 1; - $map[$key] = 0; - Redis::set($key, $i); - } - foreach (Redis::scanEach('imi:scanEach:*', 10) as $value) - { - $map[$value] = 1; - } - $this->assertEquals($excepted, $map); - } - - public function testHscanEach(): void - { - $excepted = $map = $values = $exceptedValues = []; - $key = 'imi:hscanEach'; - Redis::del($key); - for ($i = 0; $i < 100; ++$i) - { - $member = 'value:' . $i; - $excepted[$member] = 1; - $map[$member] = 0; - $values[$member] = -1; - $exceptedValues[$member] = $i; - Redis::hSet($key, $member, $i); - } - foreach (Redis::hscanEach($key, 'value:*', 10) as $k => $value) - { - $map[$k] = 1; - $values[$k] = $value; - } - $this->assertEquals($excepted, $map); - $this->assertEquals($exceptedValues, $values); - } - - public function testSscanEach(): void - { - $excepted = $map = []; - $key = 'imi:sscanEach'; - Redis::del($key); - for ($i = 0; $i < 100; ++$i) - { - $value = 'value:' . $i; - $excepted[$value] = 1; - $map[$value] = 0; - Redis::sAdd($key, $value); - } - foreach (Redis::sscanEach($key, '*', 10) as $value) - { - $map[$value] = 1; - } - $this->assertEquals($excepted, $map); - } - - public function testZscanEach(): void - { - $excepted = $map = []; - $key = 'imi:zscanEach'; - Redis::del($key); - for ($i = 0; $i < 100; ++$i) - { - $value = 'value:' . $i; - $excepted[$i] = 1; - $map[$i] = 0; - Redis::zAdd($key, $i, $value); - } - foreach (Redis::zscanEach($key, '*', 10) as $score) - { - $map[$score] = 1; - } - $this->assertEquals($excepted, $map); - } - public function testGeoAdd(): void { if (\PHP_OS_FAMILY === 'Windows') diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index c06c50bf53..782501e00a 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -20,6 +20,6 @@ - + \ No newline at end of file From b8a1be2dfce20d4b51dda416b387cfa56a1ff512 Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:30:19 +0800 Subject: [PATCH 30/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Handler/PhpRedisHandler.php | 1 + src/Components/redis/src/Redis.php | 52 ++++++++++---- .../redis/tests/Tests/PhpRedisTest.php | 69 ++++++++++++------- 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/Components/redis/src/Handler/PhpRedisHandler.php b/src/Components/redis/src/Handler/PhpRedisHandler.php index b113bd99fb..2aef7809af 100644 --- a/src/Components/redis/src/Handler/PhpRedisHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisHandler.php @@ -46,6 +46,7 @@ public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ? { $args[] = $type; } + // @phpstan-ignore-next-line return $this->client->scan($iterator, $pattern, $count, ...$args); } diff --git a/src/Components/redis/src/Redis.php b/src/Components/redis/src/Redis.php index a884bc2823..2c63be95f1 100644 --- a/src/Components/redis/src/Redis.php +++ b/src/Components/redis/src/Redis.php @@ -278,15 +278,23 @@ public static function use(callable $callable, ?string $poolName = null): mixed public static function scan(?int &$iterator, ?string $pattern = null, int $count = 0): mixed { return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use (&$iterator, $pattern, $count) { - if ($redis instanceof PhpRedisHandler) { + if ($redis instanceof PhpRedisHandler) + { return $redis->scan($iterator, $pattern, $count); - } elseif ($redis instanceof PredisHandler) { + } + elseif ($redis instanceof PredisHandler) + { [$cursor, $keys] = $redis->scan($iterator, ['match' => $pattern, 'count' => $count]); $iterator = (int) $cursor; + return $keys; - } elseif ($redis instanceof IRedisClusterHandler) { + } + elseif ($redis instanceof IRedisClusterHandler) + { throw new \RuntimeException('redis cluster handler not support scan proxy, please use scanEach method'); - } else { + } + else + { throw new \RuntimeException('unknown redis handler'); } }); @@ -298,13 +306,19 @@ public static function scan(?int &$iterator, ?string $pattern = null, int $count public static function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) + { return $redis->hscan($key, $iterator, $pattern, $count); - } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + } + elseif ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) + { [$cursor, $keys] = $redis->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]); $iterator = (int) $cursor; + return $keys; - } else { + } + else + { throw new \RuntimeException('redis handler not support'); } }); @@ -316,13 +330,19 @@ public static function hscan(string $key, ?int &$iterator, ?string $pattern = nu public static function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) + { return $redis->sscan($key, $iterator, $pattern, $count); - } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + } + elseif ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) + { [$cursor, $keys] = $redis->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]); $iterator = (int) $cursor; + return $keys; - } else { + } + else + { throw new \RuntimeException('redis handler not support'); } }); @@ -334,13 +354,19 @@ public static function sscan(string $key, ?int &$iterator, ?string $pattern = nu public static function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): mixed { return RedisManager::use(null, static function (IConnection $connection, IRedisHandler $redis) use ($key, &$iterator, $pattern, $count) { - if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) { + if ($redis instanceof PhpRedisHandler || $redis instanceof PhpRedisClusterHandler) + { return $redis->zscan($key, $iterator, $pattern, $count); - } else if ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) { + } + elseif ($redis instanceof PredisHandler || $redis instanceof PredisClusterHandler) + { [$cursor, $keys] = $redis->zscan($key, $iterator, ['match' => $pattern, 'count' => $count]); $iterator = (int) $cursor; + return $keys; - } else { + } + else + { throw new \RuntimeException('redis handler not support'); } }); diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php index 3976d072a1..5a859684c4 100644 --- a/src/Components/redis/tests/Tests/PhpRedisTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -10,11 +10,9 @@ use Imi\Redis\Handler\PhpRedisHandler; use Imi\Redis\Redis; use Imi\Redis\RedisManager; -use Imi\RequestContext; use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\TestCase; -use Predis\Collection\Iterator\Keyspace; /** * @template T of PhpRedisHandler @@ -195,9 +193,12 @@ protected function staticContextWarp(callable $fn): void // Config::get() self::assertTrue(Config::set('@app.redis.defaultPool', $this->driveName)); self::assertEquals($this->driveName, RedisManager::getDefaultPoolName()); - try { + try + { $fn(); - } finally { + } + finally + { Config::set('@app.redis.defaultPool', $defaultName); } } @@ -206,7 +207,7 @@ protected function staticContextWarp(callable $fn): void public function testStaticCall(): void { $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); - $this->staticContextWarp(function () use ($prefix) { + $this->staticContextWarp(static function () use ($prefix): void { Redis::set($prefix, '123456'); self::assertEquals('123456', Redis::get($prefix)); self::assertTrue(Redis::del($prefix) > 0); @@ -219,12 +220,13 @@ public function testStaticCall(): void #[Depends('testGetDrive')] public function testStaticCallScan(IRedisHandler $redis): void { - if ($redis instanceof IRedisClusterHandler) { + if ($redis instanceof IRedisClusterHandler) + { self::markTestSkipped('RedisClusterHandler does not support hscan'); } $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); - $this->staticContextWarp(function () use ($redis, $prefix) { + $this->staticContextWarp(static function () use ($redis, $prefix): void { $excepted = $map = []; for ($i = 0; $i < 100; ++$i) { @@ -235,14 +237,17 @@ public function testStaticCallScan(IRedisHandler $redis): void } $map = []; - do { + do + { $keys = Redis::scan($it, $prefix . ':scanEach:*', 10); - foreach ($keys as $key) { + foreach ($keys as $key) + { $map[$key] = 1; } - } while ($it != 0); + } + while (0 != $it); self::assertEquals($excepted, $map); - self::assertTrue(Redis::del(\array_keys($excepted)) > 0); + self::assertTrue(Redis::del(array_keys($excepted)) > 0); }); } @@ -252,12 +257,13 @@ public function testStaticCallScan(IRedisHandler $redis): void #[Depends('testGetDrive')] public function testStaticCallHScan(IRedisHandler $redis): void { - if ($redis instanceof IRedisClusterHandler) { + if ($redis instanceof IRedisClusterHandler) + { self::markTestSkipped('RedisClusterHandler does not support hscan'); } $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); - $this->staticContextWarp(function () use ($redis, $prefix) { + $this->staticContextWarp(static function () use ($redis, $prefix): void { $excepted = $map = $values = $exceptedValues = []; $key = $prefix . ':hscanEach'; $redis->del($key); @@ -270,13 +276,16 @@ public function testStaticCallHScan(IRedisHandler $redis): void $exceptedValues[$member] = $i; $redis->hSet($key, $member, $i); } - do { + do + { $items = Redis::hscan($key, $it, 'value:*', 10); - foreach ($items as $k => $value) { + foreach ($items as $k => $value) + { $map[$k] = 1; $values[$k] = $value; } - } while ($it > 0); + } + while ($it > 0); self::assertEquals($excepted, $map); self::assertEquals($exceptedValues, $values); self::assertTrue(Redis::del($key) > 0); @@ -289,12 +298,13 @@ public function testStaticCallHScan(IRedisHandler $redis): void #[Depends('testGetDrive')] public function testStaticCallSScan(IRedisHandler $redis): void { - if ($redis instanceof IRedisClusterHandler) { + if ($redis instanceof IRedisClusterHandler) + { self::markTestSkipped('RedisClusterHandler does not support sscan'); } $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); - $this->staticContextWarp(function () use ($redis, $prefix) { + $this->staticContextWarp(static function () use ($redis, $prefix): void { $excepted = $map = []; $key = $prefix . ':sscanEach'; $redis->del($key); @@ -305,12 +315,15 @@ public function testStaticCallSScan(IRedisHandler $redis): void $map[$value] = 0; $redis->sAdd($key, $value); } - do { + do + { $items = Redis::sscan($key, $it, '*', 10); - foreach ($items as $value) { + foreach ($items as $value) + { $map[$value] = 1; } - } while ($it > 0); + } + while ($it > 0); self::assertEquals($excepted, $map); self::assertTrue(Redis::del($key) > 0); }); @@ -322,12 +335,13 @@ public function testStaticCallSScan(IRedisHandler $redis): void #[Depends('testGetDrive')] public function testStaticCallZScan(IRedisHandler $redis): void { - if ($redis instanceof IRedisClusterHandler) { + if ($redis instanceof IRedisClusterHandler) + { self::markTestSkipped('RedisClusterHandler does not support zscan'); } $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); - $this->staticContextWarp(function () use ($redis, $prefix) { + $this->staticContextWarp(static function () use ($redis, $prefix): void { $excepted = $map = []; $key = $prefix . ':zscanEach'; $redis->del($key); @@ -338,12 +352,15 @@ public function testStaticCallZScan(IRedisHandler $redis): void $map[$i] = 0; $redis->zAdd($key, $i, $value); } - do { + do + { $items = Redis::zscan($key, $it, '*', 10); - foreach ($items as $score) { + foreach ($items as $score) + { $map[$score] = 1; } - } while ($it > 0); + } + while ($it > 0); self::assertEquals($excepted, $map); self::assertTrue(Redis::del($key) > 0); }); From 3b5a4e45c8eebeae243ad4063fc8aff88e2cd451 Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:31:08 +0800 Subject: [PATCH 31/97] Update: phpunit.xml --- src/Components/redis/tests/phpunit.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index 782501e00a..c06c50bf53 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -20,6 +20,6 @@ - + \ No newline at end of file From ec8940b5508e4df876eda9497e5f14f29b2747fc Mon Sep 17 00:00:00 2001 From: auooru Date: Thu, 7 Mar 2024 23:40:17 +0800 Subject: [PATCH 32/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/src/Handler/PhpRedisClusterHandler.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php index cd5114ab95..422abb802d 100644 --- a/src/Components/redis/src/Handler/PhpRedisClusterHandler.php +++ b/src/Components/redis/src/Handler/PhpRedisClusterHandler.php @@ -31,9 +31,6 @@ public function __call(string $name, array $arguments): mixed return $this->client->{$name}(...$arguments); } - /** - * @return array> - */ public function getNodes(): array { return $this->client->_masters(); @@ -43,7 +40,7 @@ public function isConnected(): bool { foreach ($this->getNodes() as $node) { - /** @var array $node */ + // @phpstan-ignore-next-line $this->client->ping($node); } From 42b565e54f58c360e4a20ac221ae5f2ee3ebc2a1 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:12:34 +0800 Subject: [PATCH 33/97] =?UTF-8?q?Update:=20=E5=AE=8C=E5=96=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/Tests/AbstractRedisTestCase.php | 10 ++- .../redis/tests/Tests/PhpRedisClusterTest.php | 13 ++- .../redis/tests/Tests/PhpRedisTest.php | 69 ++++++++++------ .../redis/tests/Tests/PredisClusterTest.php | 19 ++++- .../redis/tests/Tests/PredisTest.php | 11 ++- .../redis/tests/Tests/RedisTest.php | 81 ------------------- 6 files changed, 90 insertions(+), 113 deletions(-) delete mode 100644 src/Components/redis/tests/Tests/RedisTest.php diff --git a/src/Components/redis/tests/Tests/AbstractRedisTestCase.php b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php index 9e29a0eed6..aeaf289392 100644 --- a/src/Components/redis/tests/Tests/AbstractRedisTestCase.php +++ b/src/Components/redis/tests/Tests/AbstractRedisTestCase.php @@ -12,9 +12,15 @@ */ abstract class AbstractRedisTestCase extends TestCase { - public string $driveName = 'test_phpredis_cluster'; + public string $driveName = ''; + /** + * @phpstan-return T + */ abstract public function testGetDrive(): IRedisHandler; - abstract protected function flush(IRedisHandler $handler): void; + /** + * @phpstan-param T $redis + */ + abstract protected function flush(IRedisHandler $redis): void; } diff --git a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php index ac2f859af2..d478be05ba 100644 --- a/src/Components/redis/tests/Tests/PhpRedisClusterTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisClusterTest.php @@ -11,7 +11,7 @@ use PHPUnit\Framework\Attributes\TestDox; /** - * @implements PhpRedisTest + * @template T of PhpRedisClusterHandler */ #[TestDox('Redis/PhpRedis/Cluster')] class PhpRedisClusterTest extends PhpRedisTest @@ -26,6 +26,9 @@ public static function setUpBeforeClass(): void } } + /** + * @phpstan-return T + */ public function testGetDrive(): IRedisHandler { $redisClient = RedisManager::getInstance($this->driveName); @@ -37,9 +40,11 @@ public function testGetDrive(): IRedisHandler return $redisClient; } + /** + * @phpstan-param T $redis + */ protected function flush(IRedisHandler $redis): void { - /** @var PhpRedisClusterHandler $redis */ // 清空数据 foreach ($redis->getNodes() as $node) { @@ -47,10 +52,12 @@ protected function flush(IRedisHandler $redis): void } } + /** + * @phpstan-param T $redis + */ #[Depends('testGetDrive')] public function testHashKeys(IRedisHandler $redis): void { - /** @var PhpRedisClusterHandler $redis */ $prefix = 'imi:hash-test:k'; $groupItems = []; diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php index 5a859684c4..7b4285075d 100644 --- a/src/Components/redis/tests/Tests/PhpRedisTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -5,8 +5,10 @@ namespace Imi\Redis\Test\Tests; use Imi\Config; +use Imi\Redis\Handler\AbstractRedisHandler; use Imi\Redis\Handler\IRedisClusterHandler; use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisClusterHandler; use Imi\Redis\Handler\PhpRedisHandler; use Imi\Redis\Redis; use Imi\Redis\RedisManager; @@ -23,7 +25,7 @@ class PhpRedisTest extends TestCase public string $driveName = 'test_phpredis_standalone'; /** - * @phpstan-return PhpRedisHandler + * @phpstan-return T */ public function testGetDrive(): IRedisHandler { @@ -38,7 +40,7 @@ public function testGetDrive(): IRedisHandler } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ protected function flush(IRedisHandler $redis): void { @@ -46,7 +48,7 @@ protected function flush(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testGetAndSet(IRedisHandler $redis): void @@ -57,23 +59,26 @@ public function testGetAndSet(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testEvalEx(IRedisHandler $redis): void { - $value = $redis->evalEx(<<<'SCRIPT' - local key = KEYS[1] - local value = ARGV[1] - redis.call('set', key, value) - return redis.call('get', key) - SCRIPT - , ['imi:test:a', 'imi very 6'], 1); + $value = $redis->evalEx( + <<<'SCRIPT' + local key = KEYS[1] + local value = ARGV[1] + redis.call('set', key, value) + return redis.call('get', key) + SCRIPT, + ['imi:test:a', 'imi very 6'], + 1, + ); self::assertEquals('imi very 6', $value); } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testScanEach(IRedisHandler $redis): void @@ -94,7 +99,7 @@ public function testScanEach(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testHscanEach(IRedisHandler $redis): void @@ -121,7 +126,7 @@ public function testHscanEach(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testSscanEach(IRedisHandler $redis): void @@ -144,7 +149,7 @@ public function testSscanEach(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testZscanEach(IRedisHandler $redis): void @@ -167,7 +172,7 @@ public function testZscanEach(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testGeoAdd(IRedisHandler $redis): void @@ -187,15 +192,14 @@ public function testGeoAdd(IRedisHandler $redis): void $redis->setOption(\Redis::OPT_SERIALIZER, $oriOption); } - protected function staticContextWarp(callable $fn): void + protected function staticContextWarp(callable $fn): mixed { $defaultName = RedisManager::getDefaultPoolName(); - // Config::get() self::assertTrue(Config::set('@app.redis.defaultPool', $this->driveName)); self::assertEquals($this->driveName, RedisManager::getDefaultPoolName()); try { - $fn(); + return $fn(); } finally { @@ -215,7 +219,7 @@ public function testStaticCall(): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testStaticCallScan(IRedisHandler $redis): void @@ -252,7 +256,7 @@ public function testStaticCallScan(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testStaticCallHScan(IRedisHandler $redis): void @@ -293,7 +297,7 @@ public function testStaticCallHScan(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testStaticCallSScan(IRedisHandler $redis): void @@ -330,7 +334,7 @@ public function testStaticCallSScan(IRedisHandler $redis): void } /** - * @phpstan-param PhpRedisHandler $redis + * @phpstan-param T $redis */ #[Depends('testGetDrive')] public function testStaticCallZScan(IRedisHandler $redis): void @@ -365,4 +369,23 @@ public function testStaticCallZScan(IRedisHandler $redis): void self::assertTrue(Redis::del($key) > 0); }); } + + #[Depends('testGetDrive')] + public function testStaticCallEval(): void + { + $prefix = __FUNCTION__ . bin2hex(random_bytes(4)); + $value = $this->staticContextWarp(static function () use ($prefix): mixed { + return Redis::evalEx( + <<<'SCRIPT' + local key = KEYS[1] + local value = ARGV[1] + redis.call('set', key, value) + return redis.call('get', key) + SCRIPT, + [$prefix . 'imi:test:a', 'imi very 6'], + 1, + ); + }); + self::assertEquals('imi very 6', $value); + } } diff --git a/src/Components/redis/tests/Tests/PredisClusterTest.php b/src/Components/redis/tests/Tests/PredisClusterTest.php index 7595f1e072..c2d5c6df84 100644 --- a/src/Components/redis/tests/Tests/PredisClusterTest.php +++ b/src/Components/redis/tests/Tests/PredisClusterTest.php @@ -12,7 +12,7 @@ use Predis\Client; /** - * @implements PhpRedisTest + * @template T of PredisClusterHandler */ #[TestDox('Redis/Predis/Cluster')] class PredisClusterTest extends PhpRedisTest @@ -27,6 +27,9 @@ public static function setUpBeforeClass(): void } } + /** + * @phpstan-return T + */ public function testGetDrive(): IRedisHandler { $redisClient = RedisManager::getInstance($this->driveName); @@ -38,6 +41,9 @@ public function testGetDrive(): IRedisHandler return $redisClient; } + /** + * @phpstan-param T $redis + */ protected function flush(IRedisHandler $redis): void { // 清空数据 @@ -49,6 +55,9 @@ protected function flush(IRedisHandler $redis): void } } + /** + * @phpstan-param T $redis + */ #[Depends('testGetDrive')] public function testGeoAdd(IRedisHandler $redis): void { @@ -57,9 +66,12 @@ public function testGeoAdd(IRedisHandler $redis): void self::markTestSkipped('Windows redis not support geo.'); } - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); + self::assertEquals(1, $redis->geoadd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); } + /** + * @phpstan-param T $redis + */ #[Depends('testGetDrive')] public function testHashKeysSlot(IRedisHandler $redis): void { @@ -104,6 +116,9 @@ public function testHashKeysSlot(IRedisHandler $redis): void } } + /** + * @phpstan-param T $redis + */ #[Depends('testGetDrive')] public function testHashKeysTags(IRedisHandler $redis): void { diff --git a/src/Components/redis/tests/Tests/PredisTest.php b/src/Components/redis/tests/Tests/PredisTest.php index d4428f79aa..b4d0678e6f 100644 --- a/src/Components/redis/tests/Tests/PredisTest.php +++ b/src/Components/redis/tests/Tests/PredisTest.php @@ -12,13 +12,16 @@ use Predis\Client; /** - * @implements PhpRedisTest + * @template T of PredisHandler */ #[TestDox('Redis/Predis/Standalone')] class PredisTest extends PhpRedisTest { public string $driveName = 'test_predis_standalone'; + /** + * @phpstan-return T + */ public function testGetDrive(): IRedisHandler { $redisClient = RedisManager::getInstance($this->driveName); @@ -28,6 +31,10 @@ public function testGetDrive(): IRedisHandler return $redisClient; } + + /** + * @phpstan-param T $redis + */ #[Depends('testGetDrive')] public function testGeoAdd(IRedisHandler $redis): void { @@ -36,6 +43,6 @@ public function testGeoAdd(IRedisHandler $redis): void self::markTestSkipped('Windows redis not support geo.'); } - self::assertEquals(1, $redis->geoAdd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); + self::assertEquals(1, $redis->geoadd('imi:geo', 120.31858, 31.49881, 'value_' . bin2hex(random_bytes(4)))); } } diff --git a/src/Components/redis/tests/Tests/RedisTest.php b/src/Components/redis/tests/Tests/RedisTest.php deleted file mode 100644 index 56aea9a897..0000000000 --- a/src/Components/redis/tests/Tests/RedisTest.php +++ /dev/null @@ -1,81 +0,0 @@ -markTestSkipped('Deprecated Test'); - } - - public function testInject(): void - { - /** @var \Imi\Test\Component\Redis\Classes\TestInjectRedis $test */ - $test = App::getBean('TestInjectRedis'); - $test->test(); - } - - public function testGetAndSet(): void - { - $str = 'imi niubi!' . bin2hex(random_bytes(4)); - Redis::set('imi:test:a', $str); - Assert::assertEquals($str, Redis::get('imi:test:a')); - } - - public function testEvalEx(): void - { - $value = PoolManager::use('redis_test', static function (IPoolResource $resource, RedisHandler $redis) { - return $redis->evalEx(<<<'SCRIPT' - local key = KEYS[1] - local value = ARGV[1] - redis.call('set', key, value) - return redis.call('get', key) - SCRIPT - , ['imi:test:a', 'imi very 6'], 1); - }); - Assert::assertEquals('imi very 6', $value); - } - - public function testEvalEx2(): void - { - $value = Redis::evalEx(<<<'SCRIPT' - local key = KEYS[1] - local value = ARGV[1] - redis.call('set', key, value) - return redis.call('get', key) - SCRIPT - , ['imi:test:a', 'imi very 6'], 1); - Assert::assertEquals('imi very 6', $value); - } - - public function testGeoAdd(): void - { - if (\PHP_OS_FAMILY === 'Windows') - { - $this->markTestSkipped('Windows redis not support geo.'); - } - foreach ([ - 'redis_test', // 开启序列化 - 'redis_cache', // 禁用序列化 - ] as $poolName) - { - $this->assertNotFalse(Redis::use(static fn (RedisHandler $redis) => $redis->geoAdd('imi:geo', 120.31858, 31.49881, $poolName), $poolName)); - } - } -} From 750a088f527c7317dc016730e9bffacd69684df1 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:13:55 +0800 Subject: [PATCH 34/97] =?UTF-8?q?Update:=20=E6=94=AF=E6=8C=81=20unixsock?= =?UTF-8?q?=20=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PredisConnector.php | 11 ++++++++--- .../redis/src/Connector/RedisDriverConfig.php | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index 4603eca083..eca860325e 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -14,12 +14,17 @@ class PredisConnector implements IRedisConnector */ public static function connect(RedisDriverConfig $config): PredisHandler { + // tcp, unix, tls, redis, rediss, http $params = [ - 'scheme' => 'tcp', - 'host' => $config->host, - 'port' => $config->port, + 'scheme' => $config->scheme ?? 'tcp', 'database' => $config->database, ]; + if ('unix' === $config->scheme) { + $params['path'] = $config->host; + } else { + $params['host'] = $config->host; + $params['port'] = $config->port; + } if ($config->password) { $params['password'] = $config->password; diff --git a/src/Components/redis/src/Connector/RedisDriverConfig.php b/src/Components/redis/src/Connector/RedisDriverConfig.php index f5308ab131..f05e7af438 100644 --- a/src/Components/redis/src/Connector/RedisDriverConfig.php +++ b/src/Components/redis/src/Connector/RedisDriverConfig.php @@ -12,6 +12,7 @@ class RedisDriverConfig extends AbstractConnectionConfig public function __construct( public readonly string $client, public readonly RedisMode $mode, + public readonly ?string $scheme, public readonly string $host, public readonly ?int $port, public readonly ?array $seeds, @@ -32,6 +33,7 @@ protected static function __create(array $config): self return new self( client: $config['client'] ?? 'phpredis', mode: $config['mode'] ?? RedisMode::Standalone, + scheme: $config['scheme'] ?? null, host: $config['host'] ?? '127.0.0.1', port: (int) ($config['port'] ?? 6379), seeds: $config['seeds'] ?? null, From a278cd4d6e39dd501ef7fd95f1df2d53d93c558c Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:14:17 +0800 Subject: [PATCH 35/97] =?UTF-8?q?Update:=20=E5=A2=9E=E5=8A=A0=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E5=99=A8=E7=8B=AC=E7=AB=8B=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/tests/Tests/RedisHandlerTest.php | 68 +++++++++++++++++++ src/Components/redis/tests/phpunit.xml | 3 - 2 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/Components/redis/tests/Tests/RedisHandlerTest.php diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php new file mode 100644 index 0000000000..7b5a30c78f --- /dev/null +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -0,0 +1,68 @@ +ping()); + $key = 'imi:test:set_' . \bin2hex(\random_bytes(8)); + self::assertTrue($handler->set($key, '123456')); + self::assertEquals('123456', $handler->get($key)); + self::assertTrue($handler->del($key) > 0); + } + + public function testPredisUnixSockConnection() + { + $config = new RedisDriverConfig( + client: 'predis', + mode: RedisMode::Standalone, + scheme: 'unix', + host: env('REDIS_SERVER_UNIX_SOCK'), + port: 0, + seeds: null, + password: null, + database: 0, + prefix: '', + timeout: 1, + readTimeout: 1, + serialize: false, + options: [], + ); + + $handler = PredisConnector::connect($config); + + self::assertEquals('PONG', (string) $handler->ping()); + $key = 'imi:test:set_' . \bin2hex(\random_bytes(8)); + self::assertEquals(true, $handler->set($key, '123456')); + self::assertEquals('123456', $handler->get($key)); + self::assertTrue($handler->del($key) > 0); + } +} diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index c06c50bf53..0b4eca4b15 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -18,8 +18,5 @@ - - - \ No newline at end of file From 94fd13041fc024cb0313dac243f9149e8d679689 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:15:25 +0800 Subject: [PATCH 36/97] =?UTF-8?q?Update:=20=E5=BF=BD=E7=95=A5=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=20env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 69774d9b2c..46577635ec 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ composer.lock /mddoc/vendor *.lock /src/Components/*/vendor +/src/Components/*/tests/.env /split-repository/vendor /.vscode *.pid From 35abfc6493026e045eb67d33318460634e21ac1e Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:21:36 +0800 Subject: [PATCH 37/97] =?UTF-8?q?Update:=20=E8=B0=83=E6=95=B4=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/redis/tests/Tests/RedisHandlerTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 7b5a30c78f..473d5a1c80 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -14,6 +14,11 @@ class RedisHandlerTest extends TestCase { public function testPhpRedisUnixSockConnection() { + if (\PHP_OS_FAMILY !== 'Linux') + { + self::markTestSkipped('unixsock test only support linux'); + } + $config = new RedisDriverConfig( client: 'phpredis', mode: RedisMode::Standalone, @@ -41,6 +46,11 @@ public function testPhpRedisUnixSockConnection() public function testPredisUnixSockConnection() { + if (\PHP_OS_FAMILY !== 'Linux') + { + self::markTestSkipped('unixsock test only support linux'); + } + $config = new RedisDriverConfig( client: 'predis', mode: RedisMode::Standalone, From 903bdd296f5d7ebc186d0afb89b5e569d7491723 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:22:14 +0800 Subject: [PATCH 38/97] =?UTF-8?q?Update:=20=E4=BC=98=E5=8C=96=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/docker-compose.yml | 6 ++ .github/workflows/ci.yml | 98 +------------------- .github/workflows/phpstan.yml | 5 + .github/workflows/rector.yml | 5 + composer.json | 2 +- src/Components/redis/tests/config/config.php | 4 +- 6 files changed, 22 insertions(+), 98 deletions(-) diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 02f8bf19b8..8917f735cc 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -182,6 +182,9 @@ services: AMQP_SERVER_HOST: "rabbitmq" KAFKA_BOOTSTRAP_SERVERS: "kafka1:9092" GITHUB_TOKEN: ${GITHUB_TOKEN} + REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" + REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" + REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" volumes: - "${GITHUB_WORKSPACE}:/imi:rw" - shared-volume:/tmp/docker @@ -207,6 +210,9 @@ services: AMQP_SERVER_HOST: "rabbitmq" KAFKA_BOOTSTRAP_SERVERS: "kafka1:9092" GITHUB_TOKEN: ${GITHUB_TOKEN} + REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" + REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" + REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" build: context: . dockerfile: php.dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a312b4a4b..586595ba91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,100 +128,6 @@ jobs: if: failure() run: docker exec ${ENV_SERVICE} php .github/print-logs.php -# ci-unix: -# name: Linux Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} With Redis UnixSocket -# runs-on: ubuntu-latest -# strategy: -# fail-fast: false -# matrix: -# swoole: -# - version: php8.2-swoole-5.1 -# roadrunner: [2.7.*] -# env: -# ENV_SERVICE: swoole -# REPOSITORY_OWNER: ${{ github.repository_owner }} -# IMAGE_VERSION: ${{ matrix.swoole.version }} -# MYSQL_DOCKER_VERSION: "8.0" -# REDIS_SERVER_HOST: /tmp/docker/redis.sock -# ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# steps: -# - name: Checkout -# uses: actions/checkout@v4 -# - name: Prepare1 -# run: | -# echo "REPOSITORY_OWNER=${REPOSITORY_OWNER,,}" >>${GITHUB_ENV} -# mkdir -p /tmp/base_cache/composer -# - name: Cache dependencies -# uses: actions/cache@v3 -# with: -# path: /tmp/base_cache/composer -# key: ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} -# restore-keys: | -# ${{ runner.os }}-composer-${{ env.IMAGE_VERSION }}- -# ${{ runner.os }}-composer- -# - name: Prepare2 -# uses: ./.github/actions/ci-prepare -# with: -# env: ${{ env.ENV_SERVICE }} -# - name: Test -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test -# - name: Test swoole -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-swoole -# - name: Test workerman -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-workerman -# - name: Test workerman-gateway -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-workerman-gateway -# - name: Test roadrunner -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-roadrunner -# - name: Test fpm -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-fpm -# - name: Test jwt -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-jwt -# - name: Test queue -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-queue -# - name: Test amqp -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-amqp -# - name: Test kafka -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-kafka -# - name: Test grpc -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-grpc -# - name: Test snowflake -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-snowflake -# - name: Test mqtt -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-mqtt -# - name: Test smarty -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-smarty -# - name: Test pgsql -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-pgsql -# - name: Test connection-center -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-connection-center -# - name: Test database -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-database -# - name: Test model -# if: ${{ env.test_prepared && always() }} -# run: docker exec ${ENV_SERVICE} composer test-model -# - name: Print logs -# if: failure() -# run: docker exec ${ENV_SERVICE} php .github/print-logs.php - ci-swoole-cli: name: Swoole-cli-${{ matrix.swoole-cli }} runs-on: ubuntu-latest @@ -289,7 +195,9 @@ jobs: - name: Test redis if: ${{ env.test_prepared && always() }} env: - REDIS_SERVER_CLUSTER_SEEDS: "127.0.0.1:6479,127.0.0.1:6480,127.0.0.1:6481,127.0.0.1:6482,127.0.0.1:6483,127.0.0.1:6484" + REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" + REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" + REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 854b497b41..671172468f 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -196,6 +196,11 @@ jobs: run: | docker exec ${ENV_SERVICE} ./dev/phpstan.sh model + - name: Analyse redis + if: ${{ env.test_prepared && always() }} + run: | + docker exec ${ENV_SERVICE} ./dev/phpstan.sh redis + - name: Save All composer.lock And autoloader-suffix if: ${{ env.test_prepared && always() }} run: | diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index 008738df55..d0ddea1c2e 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -182,3 +182,8 @@ jobs: if: ${{ env.test_prepared && always() }} run: | docker exec -w /imi/src/Components/model ${ENV_SERVICE} /imi/vendor/bin/rector process --dry-run + + - name: Analyse redis + if: ${{ env.test_prepared && always() }} + run: | + docker exec -w /imi/src/Components/redis ${ENV_SERVICE} /imi/vendor/bin/rector process --dry-run diff --git a/composer.json b/composer.json index c853291e0d..44f1bee6e5 100644 --- a/composer.json +++ b/composer.json @@ -122,7 +122,7 @@ ], "test-database": "@php vendor/bin/phpunit -c src/Components/database/tests/phpunit.xml", "test-model": "@php vendor/bin/phpunit -c src/Components/model/tests/phpunit.xml", - "test-redis": "@php vendor/bin/phpunit -c src/Components/redis/tests/phpunit.xml", + "test-redis": "@php vendor/bin/phpunit -c src/Components/redis/tests/phpunit.xml --testdox", "test-components": [ "@composer test-swoole", "@composer test-workerman", diff --git a/src/Components/redis/tests/config/config.php b/src/Components/redis/tests/config/config.php index 21dd06367d..8f7feacec1 100644 --- a/src/Components/redis/tests/config/config.php +++ b/src/Components/redis/tests/config/config.php @@ -92,7 +92,7 @@ 'client' => 'phpredis', 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, - 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS')), + 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS', '')), ], ], ], @@ -132,7 +132,7 @@ 'client' => 'predis', 'mode' => \Imi\Redis\Enum\RedisMode::Cluster, - 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS')), + 'seeds' => explode(',', env('REDIS_SERVER_CLUSTER_SEEDS', '')), ], ], ], From 2a686ab4bdf519e04d01868bd8dad9c1b7b09a09 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:38:06 +0800 Subject: [PATCH 39/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PredisConnector.php | 7 +++++-- src/Components/redis/tests/Tests/PhpRedisTest.php | 12 +++++------- src/Components/redis/tests/Tests/PredisTest.php | 1 - .../redis/tests/Tests/RedisHandlerTest.php | 12 +++++++----- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index eca860325e..91f1fece8f 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -19,9 +19,12 @@ public static function connect(RedisDriverConfig $config): PredisHandler 'scheme' => $config->scheme ?? 'tcp', 'database' => $config->database, ]; - if ('unix' === $config->scheme) { + if ('unix' === $config->scheme) + { $params['path'] = $config->host; - } else { + } + else + { $params['host'] = $config->host; $params['port'] = $config->port; } diff --git a/src/Components/redis/tests/Tests/PhpRedisTest.php b/src/Components/redis/tests/Tests/PhpRedisTest.php index 7b4285075d..1386169e36 100644 --- a/src/Components/redis/tests/Tests/PhpRedisTest.php +++ b/src/Components/redis/tests/Tests/PhpRedisTest.php @@ -5,10 +5,8 @@ namespace Imi\Redis\Test\Tests; use Imi\Config; -use Imi\Redis\Handler\AbstractRedisHandler; use Imi\Redis\Handler\IRedisClusterHandler; use Imi\Redis\Handler\IRedisHandler; -use Imi\Redis\Handler\PhpRedisClusterHandler; use Imi\Redis\Handler\PhpRedisHandler; use Imi\Redis\Redis; use Imi\Redis\RedisManager; @@ -377,11 +375,11 @@ public function testStaticCallEval(): void $value = $this->staticContextWarp(static function () use ($prefix): mixed { return Redis::evalEx( <<<'SCRIPT' - local key = KEYS[1] - local value = ARGV[1] - redis.call('set', key, value) - return redis.call('get', key) - SCRIPT, + local key = KEYS[1] + local value = ARGV[1] + redis.call('set', key, value) + return redis.call('get', key) + SCRIPT, [$prefix . 'imi:test:a', 'imi very 6'], 1, ); diff --git a/src/Components/redis/tests/Tests/PredisTest.php b/src/Components/redis/tests/Tests/PredisTest.php index b4d0678e6f..1ecba6e06a 100644 --- a/src/Components/redis/tests/Tests/PredisTest.php +++ b/src/Components/redis/tests/Tests/PredisTest.php @@ -31,7 +31,6 @@ public function testGetDrive(): IRedisHandler return $redisClient; } - /** * @phpstan-param T $redis */ diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 473d5a1c80..4df4e4a75e 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -1,4 +1,5 @@ ping()); - $key = 'imi:test:set_' . \bin2hex(\random_bytes(8)); + $key = 'imi:test:set_' . bin2hex(random_bytes(8)); self::assertTrue($handler->set($key, '123456')); self::assertEquals('123456', $handler->get($key)); self::assertTrue($handler->del($key) > 0); } - public function testPredisUnixSockConnection() + public function testPredisUnixSockConnection(): void { if (\PHP_OS_FAMILY !== 'Linux') { @@ -70,8 +72,8 @@ public function testPredisUnixSockConnection() $handler = PredisConnector::connect($config); self::assertEquals('PONG', (string) $handler->ping()); - $key = 'imi:test:set_' . \bin2hex(\random_bytes(8)); - self::assertEquals(true, $handler->set($key, '123456')); + $key = 'imi:test:set_' . bin2hex(random_bytes(8)); + self::assertTrue($handler->set($key, '123456')); self::assertEquals('123456', $handler->get($key)); self::assertTrue($handler->del($key) > 0); } From 0e2a22d2cd49511cc507ff645a6c4b03db68b753 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:40:46 +0800 Subject: [PATCH 40/97] =?UTF-8?q?Update:=20=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- src/Components/redis/tests/phpunit.xml | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 44f1bee6e5..c853291e0d 100644 --- a/composer.json +++ b/composer.json @@ -122,7 +122,7 @@ ], "test-database": "@php vendor/bin/phpunit -c src/Components/database/tests/phpunit.xml", "test-model": "@php vendor/bin/phpunit -c src/Components/model/tests/phpunit.xml", - "test-redis": "@php vendor/bin/phpunit -c src/Components/redis/tests/phpunit.xml --testdox", + "test-redis": "@php vendor/bin/phpunit -c src/Components/redis/tests/phpunit.xml", "test-components": [ "@composer test-swoole", "@composer test-workerman", diff --git a/src/Components/redis/tests/phpunit.xml b/src/Components/redis/tests/phpunit.xml index 0b4eca4b15..8a3a559e71 100644 --- a/src/Components/redis/tests/phpunit.xml +++ b/src/Components/redis/tests/phpunit.xml @@ -1,15 +1,17 @@ + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" + bootstrap="./bootstrap.php" + colors="true" + testdox="true" +> ./ - + From 525b176ba2d124aafb05974ff986d3e6b328938a Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 15:47:08 +0800 Subject: [PATCH 41/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 586595ba91..c9869f27ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,7 +196,7 @@ jobs: if: ${{ env.test_prepared && always() }} env: REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" - REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" + REDIS_SERVER_CLUSTER_SEEDS: "127.0.0.1:6479,127.0.0.1:6480,127.0.0.1:6481,127.0.0.1:6482,127.0.0.1:6483,127.0.0.1:6484" REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" run: composer test-redis - name: Test swoole From adb1800f3f0bda7ba8f33a399eabdb7a2495ab4d Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 22:03:13 +0800 Subject: [PATCH 42/97] =?UTF-8?q?Update:=20=E5=AE=9E=E7=8E=B0=20redis-tls?= =?UTF-8?q?=20=E8=BF=9E=E6=8E=A5=E4=B8=8E=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PhpRedisConnector.php | 23 ++++- .../redis/src/Connector/PredisConnector.php | 12 +++ .../redis/src/Connector/RedisDriverConfig.php | 2 + .../redis/tests/Tests/RedisHandlerTest.php | 96 +++++++++++++++++++ 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index 7fec833398..826d5d372c 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -17,15 +17,34 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler $redis = new \Redis(); $host = $config->host; + $arguments = [ + $config->host, // host + ]; if (str_contains($host, '/')) { // unix socket - $redis->connect($host); + $arguments[] = 0; } else { - $redis->connect($host, $config->port, $config->timeout); + $arguments[] = $config->port; } + $arguments[] = $config->timeout; + $arguments[] = null; // reserved + $arguments[] = 0; // retry_interval + $arguments[] = $config->readTimeout; + + // others: array, with PhpRedis >= 5.3.0, it allows setting auth and stream configuration. + $extra = []; + if ($config->tls) { + $extra['stream'] = $config->tls; + } + if ($extra) { + $arguments[] = $extra; + } + + + $redis->connect(...$arguments); if (('' !== $config->password) && !$redis->auth($config->password) && null !== $redis->getLastError()) { throw new \RedisException($redis->getLastError()); diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index 91f1fece8f..f789558c3c 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -32,10 +32,22 @@ public static function connect(RedisDriverConfig $config): PredisHandler { $params['password'] = $config->password; } + if ($config->timeout > 0.0) + { + $params['timeout'] = $config->timeout; + } + if ($config->readTimeout > 0.0) + { + $params['read_write_timeout'] = $config->readTimeout; + } if ($config->prefix) { $params['prefix'] = $config->prefix; } + if ($config->tls) { + $params['scheme'] = 'tls'; + $params['ssl'] = $config->tls; + } $client = new \Predis\Client($params); $client->connect(); diff --git a/src/Components/redis/src/Connector/RedisDriverConfig.php b/src/Components/redis/src/Connector/RedisDriverConfig.php index f05e7af438..3eb958039b 100644 --- a/src/Components/redis/src/Connector/RedisDriverConfig.php +++ b/src/Components/redis/src/Connector/RedisDriverConfig.php @@ -23,6 +23,7 @@ public function __construct( public readonly float $readTimeout, public readonly bool $serialize, public readonly array $options, + public readonly ?array $tls, float $weight = 0 ) { parent::__construct(weight: $weight); @@ -44,6 +45,7 @@ protected static function __create(array $config): self readTimeout: (float) ($config['readTimeout'] ?? 3.0), serialize: $config['serialize'] ?? true, options: $config['options'] ?? [], + tls: $config['tls'] ?? null, weight: (int) ($config['weight'] ?? 0), ); } diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 4df4e4a75e..1c3170953a 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -14,6 +14,53 @@ class RedisHandlerTest extends TestCase { + public function testPhpRedisTlsConnection(): void + { + foreach ([ + 'REDIS_SERVER_TLS_HOST', + 'REDIS_SERVER_TLS_PORT', + 'REDIS_SERVER_TLS_CA_FILE', + 'REDIS_SERVER_TLS_CERT_FILE', + 'REDIS_SERVER_TLS_KEY_FILE', + ] as $key) { + $value = env($key); + if (empty($value)) { + self::markTestSkipped("tls options {$key} is empty, skip tls test"); + } + } + + $config = new RedisDriverConfig( + client: 'phpredis', + mode: RedisMode::Standalone, + scheme: null, + host: env('REDIS_SERVER_TLS_HOST'), + port: env('REDIS_SERVER_TLS_PORT'), + seeds: null, + password: env('REDIS_SERVER_TLS_PASSWORD'), + database: 0, + prefix: '', + timeout: 1, + readTimeout: 1, + serialize: false, + options: [], + tls: [ + // https://www.php.net/context.ssl + 'verify_peer_name' => false, + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + ], + ); + + $handler = PhpRedisConnector::connect($config); + + self::assertTrue($handler->ping()); + $key = 'imi:test:set_' . bin2hex(random_bytes(8)); + self::assertTrue($handler->set($key, '123456')); + self::assertEquals('123456', $handler->get($key)); + self::assertTrue($handler->del($key) > 0); + } + public function testPhpRedisUnixSockConnection(): void { if (\PHP_OS_FAMILY !== 'Linux') @@ -35,6 +82,7 @@ public function testPhpRedisUnixSockConnection(): void readTimeout: 1, serialize: false, options: [], + tls: null, ); $handler = PhpRedisConnector::connect($config); @@ -46,6 +94,53 @@ public function testPhpRedisUnixSockConnection(): void self::assertTrue($handler->del($key) > 0); } + public function testPredisTlsConnection(): void + { + foreach ([ + 'REDIS_SERVER_TLS_HOST', + 'REDIS_SERVER_TLS_PORT', + 'REDIS_SERVER_TLS_CA_FILE', + 'REDIS_SERVER_TLS_CERT_FILE', + 'REDIS_SERVER_TLS_KEY_FILE', + ] as $key) { + $value = env($key); + if (empty($value)) { + self::markTestSkipped("tls options {$key} is empty, skip tls test"); + } + } + + $config = new RedisDriverConfig( + client: 'predis', + mode: RedisMode::Standalone, + scheme: null, + host: env('REDIS_SERVER_TLS_HOST'), + port: env('REDIS_SERVER_TLS_PORT'), + seeds: null, + password: env('REDIS_SERVER_TLS_PASSWORD'), + database: 0, + prefix: '', + timeout: 1, + readTimeout: 1, + serialize: false, + options: [], + tls: [ + // https://www.php.net/context.ssl + 'verify_peer_name' => false, + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + ], + ); + + $handler = PredisConnector::connect($config); + + self::assertEquals('PONG', (string) $handler->ping()); + $key = 'imi:test:set_' . bin2hex(random_bytes(8)); + self::assertTrue($handler->set($key, '123456')); + self::assertEquals('123456', $handler->get($key)); + self::assertTrue($handler->del($key) > 0); + } + public function testPredisUnixSockConnection(): void { if (\PHP_OS_FAMILY !== 'Linux') @@ -67,6 +162,7 @@ public function testPredisUnixSockConnection(): void readTimeout: 1, serialize: false, options: [], + tls: null, ); $handler = PredisConnector::connect($config); From 564fdb7d1a1a5edcbbddf95a05aafb2a8934c7fb Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 22:21:26 +0800 Subject: [PATCH 43/97] =?UTF-8?q?Update:=20=E6=B5=8B=E8=AF=95=20redis-tls?= =?UTF-8?q?=20=E5=8D=95=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/docker-compose.yml | 38 ++++++++++++++++ .github/service/redis-tls/certs/ca.crt | 31 +++++++++++++ .github/service/redis-tls/certs/ca.key | 51 ++++++++++++++++++++++ .github/service/redis-tls/certs/client.crt | 24 ++++++++++ .github/service/redis-tls/certs/client.key | 27 ++++++++++++ .github/service/redis-tls/certs/redis.crt | 23 ++++++++++ .github/service/redis-tls/certs/redis.dh | 8 ++++ .github/service/redis-tls/certs/redis.key | 27 ++++++++++++ .github/workflows/ci.yml | 7 +++ 9 files changed, 236 insertions(+) create mode 100644 .github/service/redis-tls/certs/ca.crt create mode 100644 .github/service/redis-tls/certs/ca.key create mode 100644 .github/service/redis-tls/certs/client.crt create mode 100644 .github/service/redis-tls/certs/client.key create mode 100644 .github/service/redis-tls/certs/redis.crt create mode 100644 .github/service/redis-tls/certs/redis.dh create mode 100644 .github/service/redis-tls/certs/redis.key diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 8917f735cc..552094145a 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -51,6 +51,28 @@ services: ports: - 6379:6379 + redis-new: + image: bitnami/redis:7.2 + container_name: redis_new + depends_on: + - shared-tmp + volumes: + - ./service/redis-tls/certs:/opt/bitnami/redis/certs + - shared-volume:/tmp/docker + environment: + REDIS_PORT_NUMBER: 6380 + REDIS_PASSWORD: "l83aa26" + REDIS_TLS_ENABLED: true + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_AUTH_CLIENTS: "yes" + ports: + - "6380:6380" + - "6443:6443" + rabbitmq: container_name: rabbitmq image: "rabbitmq:3.8-management" @@ -170,6 +192,7 @@ services: - shared-tmp - mysql - redis + - redis-new - rabbitmq - kafka1 - postgres @@ -185,6 +208,13 @@ services: REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" + REDIS_SERVER_TLS_HOST: redis_new + REDIS_SERVER_TLS_PORT: "6443" + REDIS_SERVER_TLS_PASSWORD: "l83aa26" + REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" + REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" + REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" + REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" volumes: - "${GITHUB_WORKSPACE}:/imi:rw" - shared-volume:/tmp/docker @@ -198,6 +228,7 @@ services: - shared-tmp - mysql - redis + - redis-new - rabbitmq - kafka1 - postgres @@ -213,6 +244,13 @@ services: REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" + REDIS_SERVER_TLS_HOST: redis_new + REDIS_SERVER_TLS_PORT: "6443" + REDIS_SERVER_TLS_PASSWORD: "l83aa26" + REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" + REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" + REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" + REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" build: context: . dockerfile: php.dockerfile diff --git a/.github/service/redis-tls/certs/ca.crt b/.github/service/redis-tls/certs/ca.crt new file mode 100644 index 0000000000..891425abcd --- /dev/null +++ b/.github/service/redis-tls/certs/ca.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFSzCCAzOgAwIBAgIUJ9PoXzht9SGd1PP9unf2JK8Lp1gwDQYJKoZIhvcNAQEL +BQAwNTETMBEGA1UECgwKUmVkaXMgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MB4XDTI0MDMwODA4MTc0MloXDTM0MDMwNjA4MTc0MlowNTETMBEG +A1UECgwKUmVkaXMgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4a8sm6bsz1yz86wF8gDZ +C4pjXH5xwMZbV4/iXgtPRbPxhUM+9wk4wXJyflxtBmeVIa1tC56GLqjg/b5Td57Q +OeKtGZVCXkefTKPND87hIUafXHol8ss69FzJ/Y3K1sVeJXZyvDumuuOq4mFei4HJ +M8+e+Cy4PxRZVm/FlG7JqNKIYLpkx1HbwFChhtyH0kRPCKqm0OS2Ez0Ok6awoFM4 +LkiGDiDQUl71INn4zfwNF246V/CXUdOYRtjcZETkB4etAffg4NBFdxuklK4e1Yvu +OJTz4wotXWA3BWyEP4BazFxJDIPYhzeGR+s5/1Pv22t/rt8qjiW6OH3YKACQLddx +uBDKIxivbdwK322fLpESKoW6unGXH2G92AgjZcAzHT+u9y2A/RTUmJQ9Tvadp7r8 +hKZ6cLUYa722iT2Pwy/9InyR7gJKobtbTHeLgzaHv+yYEy+57DieVwmg9ae47Pi2 +Uv6FkuAP0WcsfCzNgUJ2+XtUBVo3XfgMMPKy9z17Ub+38pZJVN5hG/Jnj/7BCECe +/i9kleVsBp5CO6728jwDdX85zsgy7cPjbfjE0LaN9a/kq0mVB5+Aa4mHua5eTmgB +EZukUEHx6wPazuFVYAz0z4SSvIX0IWRvJK9E2mSr0akMzkXpFTMnNr5XLzympvKq +Dow5aZlrSTrqeM/SKOiEYrsCAwEAAaNTMFEwHQYDVR0OBBYEFNelk3Skwpg/I+Yr +B+rMwWPlkSlRMB8GA1UdIwQYMBaAFNelk3Skwpg/I+YrB+rMwWPlkSlRMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAE1Vho2acHEZN8v+UMMSZRoO +JAJI9RytvEoSoO7F3sl6nHsDfCgplyO5pLfhRUuU1UC0O6Vi1azwy3Hy93s9+6GP +oXe1yoseZ0rr80JMQZQMAvhymTt5uOfN7T1wd8fZFsaZmXz8WEeMduYYToZKa3pl +5i2rr2+w/A63J2wgDBvC+T9gtXkufgCDIvZ41vews2TrqPO2fy3RG5iZ0aKkTUb5 +MDxIPYgwchK7BTjY7TEidk+VKC7Gk48EuX6CCeFqftJW6I4hBb0RA3soJ2tvbGeY +ENlP+udM1lwJEO/x+n9NiNgmGJmYDvfJ0dRDLk8ugcSF0uNsKI9VtU5tn674lLHH +YpxCyvC4iPgrXW02z8SP7Jvcy/rUtg836CXx6shRr5b7WWtDdRUjr8S6FoLermzF +JgqC4LpSGwAawGKsquq2c/sbrw3p2F5OBwD4Zhub5LNYgHe5fbJUE+2GJalhwrF5 +RPOCFi7EXn8YpD3AIkojy4YGRZEPdjpre9Km87+9MTpxpr5v1YH11HvTCbmPlud+ +cXPSGEhnSV4kv8lwTnZqNJcZrk1XOkBy3mz3sOTWxs3Lx5GDR0L1ZRncR2rSAjEN +suL90zQzyMDny3HUA43M/yb46qySsp9uduGnQn9Hdq/eXUZ09yuReJq690/Ux0dd +7tP7mhYKvuJwxuokBDBc +-----END CERTIFICATE----- diff --git a/.github/service/redis-tls/certs/ca.key b/.github/service/redis-tls/certs/ca.key new file mode 100644 index 0000000000..a3e77d2c6e --- /dev/null +++ b/.github/service/redis-tls/certs/ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEA4a8sm6bsz1yz86wF8gDZC4pjXH5xwMZbV4/iXgtPRbPxhUM+ +9wk4wXJyflxtBmeVIa1tC56GLqjg/b5Td57QOeKtGZVCXkefTKPND87hIUafXHol +8ss69FzJ/Y3K1sVeJXZyvDumuuOq4mFei4HJM8+e+Cy4PxRZVm/FlG7JqNKIYLpk +x1HbwFChhtyH0kRPCKqm0OS2Ez0Ok6awoFM4LkiGDiDQUl71INn4zfwNF246V/CX +UdOYRtjcZETkB4etAffg4NBFdxuklK4e1YvuOJTz4wotXWA3BWyEP4BazFxJDIPY +hzeGR+s5/1Pv22t/rt8qjiW6OH3YKACQLddxuBDKIxivbdwK322fLpESKoW6unGX +H2G92AgjZcAzHT+u9y2A/RTUmJQ9Tvadp7r8hKZ6cLUYa722iT2Pwy/9InyR7gJK +obtbTHeLgzaHv+yYEy+57DieVwmg9ae47Pi2Uv6FkuAP0WcsfCzNgUJ2+XtUBVo3 +XfgMMPKy9z17Ub+38pZJVN5hG/Jnj/7BCECe/i9kleVsBp5CO6728jwDdX85zsgy +7cPjbfjE0LaN9a/kq0mVB5+Aa4mHua5eTmgBEZukUEHx6wPazuFVYAz0z4SSvIX0 +IWRvJK9E2mSr0akMzkXpFTMnNr5XLzympvKqDow5aZlrSTrqeM/SKOiEYrsCAwEA +AQKCAgBpAndBHZSGj93zfZFun1Jeek/tU7BeQG1z+rEbjSufhTDWDwoXLCVKbZQ0 +k5DvL/dGKknY5DQPNekqaAqyWCUPKhfdFYRCFhVbNcROnLZII3I3N2a86C9QUHR0 +FCvTbxZ1W/3a8+6KezCiEShKxWL3Rp3zX+uC/lbrTyqh/EK82Ok4CMKns8EKZPoj +pC1Wew5DPBROknzdysUjkqYQk2hKsNgfbsk/6osodAO+5I663kErdfkSy9/I51L1 +HND1Z/3qMopiUMZhu20C+VnDh06a6UPp2mxtTD2NuoZ2faTB/hbHSfnQQNesUxkz +YrzyXbyVg6VrasaRTozrYAe2LM7uNLnNSojwp5GNMSdILKR6dTttcrWy6NN2rYme +RSWu0AdhfHjOrCTynXw8Erd2QZLm7bAvYPMpLPmhKDrPBBKHPrwhSf9NEdU+LMxb +Wk87P45DhbPJIGLvvMAH6dytHGkEyRz0Rq3NnYsEhkyNlap1L7uG/YvI/G9q7qxy +XbKFCVJ5I5VoHy4BH++Wu06D6AD2Kn41BY5Sler3J+3Sh0Vbc95HRwQmJbVHMupB +XLGS38LhDDZoZGK/AOQAPf212s1+hdmYvXsqNCguBwNIIYF6E32VS5XPfnVTzK7Q +SnHN8nnKRrdDFWYQPXXNjGe46tUrqYqecR4i44/zXNf5uTF8gQKCAQEA9J1Q2J1K +tnGyGuzPFGmERtApzDkA1JyWYzcJzolldpwHmbP+WDIWO/7KTLmSa1WJkfqLOwTx +B1eVDyt7TzfT17DYy69OPW7nxCug/SlJrjg5i8+Z6jMjTJr/HLC90PsfbzhVsknc +rQfeqIwoEPtDl+m2oDPeOK7BQIGAQAZFz5/7Rb/igvOcOrojiAMwNFneoLG58sgI +0gNDXox4CXEolfZFjOBy4ubVtPyMnW7WL+sV6o6QE9pdBZ3IofGbUui8hSLDgRpr +lwffB92t8M3ghlcIMmSVOuOxavK2zdkXvujLyqajq1iDHmiouLDv4vedITRIEInG +qLcG3vrOMP+6mwKCAQEA7DBL9aNUL84X5JDh2LsPGlkjtcdhVpedWAWQFoBDZfW5 +mR7r7IG+wI300GlbCDeS28GWYrMaRLYcT5peSReNIGSiP/Q0VilgEPVmJ+KwNqv8 +D3qknEHuR625nMY1Fv2HhsH4MOVEZuzwP2PAosQrd+sh8CwcKb6FwfKX9vxNXtzT +wKPxsGKQ4KgC+vh7XJqRLmMThnvT/P3diwWy44qA81LJ6dgewJYiKTU/sO470FFs +RsScXBbbul9uCOYpOwvc6MTBiFf2TilwO+oLSvdncBLUmqhr5/SSS4kVyzl6mLGU +CAhIsPNXRBJ/lFHQoMwPisSW82BPOq72dYXZm3fqYQKCAQEA5a1cfrdZsmqYv71A +Rrs4b0D/LfkL9ZW9gxTniVzqvu6MGF6v32HQDK8UhevsNgnPrRhhaJ4gLjOnCuJZ +2qzhpPEw7jcBMJ+U0FXiyDHfM80pA0R/ES7I4yHZjbfJ0pIoFsb/d/LwWCs+fmVz +LVavRdE1H8Dz06cKXyX5JKR/Ig7l4Lzl0u0n8OBbglb0CQOlDJ8zqGj4FzDnLbyY +7MyqPfxJm5gXZ0M0v8YtxZiPVdjW8DDByVJL630WKDByFevfLubQSMVk5h+G45za +uHKmcZ0AXkig8fVe3btdt3QyXpe42eOTY8ws+P1uBlRkOWkjyUyMqbKjrECGHBHE +Tq+fJwKCAQB2ariKzXq2BSRhimpRWWf3E94dk3swCQ/wQ8m8Hk6sXgjRxnkOuPZE +YGfv3gKwGfzdhS+7CIUREiUbnA/Noas2JH5chjl/QXtSxVaUhMlIf+3+bMT/OucW +tPksqwuPHUnHvJSNH0WuPPkvLvo0IRqSIyd+3P65xzYUyWZ7hH/eIeVg3lGc164/ +lLz5y38+LJjBoxb1BDyCyV08CH1qK9T/KfDl919ju2IhOvtV3/vJNCmPSaADY8qC +pLnsaEkfu5Dke1F05HUvNwN4Zp2G1ofb3vUNHYgMYci/alms7IKU7+OCK3UWksqb +7JJecK6jD+xy7KGqIA1ZJMOYpKU3l2XBAoIBAQCS5MFHGUoVzd2v6/epcZhp4Sg2 +5QQcUhbx/0LfXcS5Lkm23T3mNV5O7MR6sVJVHz9NQum75IA43r9pzykc42rBfk5p +p3Mkay7HYOxdvVZp46hOxxlrituYTPBKmwd/nz12lwtR/Y8CvkVYaGxoZXwJld/C +nnFlNnUjNxDoDdBM0wOUNNtjA7smw0mXA/pFTThGIX8En44UjNfCngPP+sNpCeRS +NZEgeFAMO/Sqq7S6TBzG5QOH+2j0Ntm11646zql46pcbsLgLOnJlDcQ6gE88ysl1 +ecBpjNMBgB30eL5Srl6JaGp84/EQmCLOTzzoJ9KbKSon6pvO7ltyIN2o6ZTM +-----END RSA PRIVATE KEY----- diff --git a/.github/service/redis-tls/certs/client.crt b/.github/service/redis-tls/certs/client.crt new file mode 100644 index 0000000000..4f8058daa7 --- /dev/null +++ b/.github/service/redis-tls/certs/client.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEEDCCAfigAwIBAgIUbTTNMoBTdAfw6xBhAJKSkeTGHnYwDQYJKoZIhvcNAQEL +BQAwNTETMBEGA1UECgwKUmVkaXMgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MB4XDTI0MDMwODA4MTc0MloXDTI1MDMwODA4MTc0MlowKzETMBEG +A1UECgwKUmVkaXMgVGVzdDEUMBIGA1UEAwwLQ2xpZW50LW9ubHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWZyd9ecP/LoGN7Jocc3ILTeP/MBBnr+Qa +U+Z0M6PbLeMiqCPlCbrNkMl5dF3tQfRmsHW2nosl43c+zfiO+MOwEB4q1leS/Hj4 +Kdo6jXBWv0xonjOuNEEmjaHgThR3Vf8y4HpagUr7d3KNBgkbFjIfcajB/XXRdkzF +hCIsevoJnI2baopnGlFG7rTTMBAF016+LS2Wva0LK/W3Wt5Q4x7ptF9RxxS1GFcc +EYdXeP/J2Py3XODeS6W4KS6/ge2BRsIQx8q85uaZa/ygczcIb31I3KA6Ax3AB5CJ +mVVZ8s6YRi0u21mlg9U5qH4QqKTPyyl7Bv6l5DDeRVMLWT3l1o/JAgMBAAGjIjAg +MAsGA1UdDwQEAwIFoDARBglghkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQELBQAD +ggIBADllO1pLS+kHWVXsPIhLpWv0H/Yr9gccZjwceXVCN1u2Eo1DHrh8vjZPwC4I +6sTqFACXQsHGPunJxCKanmd6oxTL/SpvHh4Z+V0vw5+bhBiaEJaTo6yQZQrB9i3J +IP+pnJg+/vW+D+D5kMq52pewukpBVuFVKPZDEMkJRSCw7mU+IjkxQN7NKUsWf19Q +ri9kCOPsj3wxCNoYNHbafaipW8IydjcMdAIrrpgsG+OmekMti33AtsMsdAE7FSbA +bs1fIDUq76zda0/OLJ1k6aVjmLn9oleYoUHmubTtiMBYYSKGGSnrDvIAp7MSkPu7 +/GGjR2v6tcPm+gOE/C2u2XoIKTyhXDnINIbrrfCHUKC3mVQRVHV9qQ1f+23rMSMX +yAo6b07YRJfqRmJq3+J/CSlHS/l+EdQZhpJlCVrb07w21OSqxolixKFHlxME/neR +s7OZdpPsJ2vpMM8YnbkBRQd4N1S5d7YaumIijsxfnBv2mJjGhMkACsHhMmNr8QkD +OD+yzP+HRzr5fseuog0l0xxw8zWEP/tXcOVvWjYdXdilhc0RZog1tDrkK/xAlImB +v3mHqo0LaoK+5zr2FTT+/kbp+uwy4tJH2buQC8xrwVoOXtQJz+rB2rdYxTmM6Krc +Edmh5/nvNKUt2xxAw2sJmlczL7Y1a20kJRs2nKhY1zmTwGyc +-----END CERTIFICATE----- diff --git a/.github/service/redis-tls/certs/client.key b/.github/service/redis-tls/certs/client.key new file mode 100644 index 0000000000..42f41d709e --- /dev/null +++ b/.github/service/redis-tls/certs/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEA1mcnfXnD/y6BjeyaHHNyC03j/zAQZ6/kGlPmdDOj2y3jIqgj +5Qm6zZDJeXRd7UH0ZrB1tp6LJeN3Ps34jvjDsBAeKtZXkvx4+CnaOo1wVr9MaJ4z +rjRBJo2h4E4Ud1X/MuB6WoFK+3dyjQYJGxYyH3Gowf110XZMxYQiLHr6CZyNm2qK +ZxpRRu600zAQBdNevi0tlr2tCyv1t1reUOMe6bRfUccUtRhXHBGHV3j/ydj8t1zg +3kuluCkuv4HtgUbCEMfKvObmmWv8oHM3CG99SNygOgMdwAeQiZlVWfLOmEYtLttZ +pYPVOah+EKikz8spewb+peQw3kVTC1k95daPyQIDAQABAoIBAQCqubVuavmxR30O +YGtPYHZdngaBe+p0RlFizZBi04QU0fNd83mxtg+0BSkJt6nbdXuCEd2KL7Ep2Hlp +32Wfo2Nf3VXIUqmld7l0Ew+dNGdSDD5xyBfrDd0bMAjIriQJ6sat4qZLT00/9JuY +xEeX9BKxizYQUx3wTz1OwqrbtIlKAJQJvpi8eFfMhXZXQvWhTRAMedCDgbuOXyO2 +uHBTveNDS62BoqYZIq9LwBBpL46dpdGq6NSGQgOR8F8FYL0dFxQb+4NeTv/dIUra +YQ6cXFupnVj5D5wLJmqfCcZqX8E0pUaTcIqLIZWNBxQfpXLOTOUurwn8PKMwOSbj +u4Zx72EBAoGBAPYaZFNUyyCEn0I0X/I1hhWLcTetu8L8eXHt9jyctMeAo13aky8a +AkeUlQGmzV7ECT64/j9ysHs9jiwTVM6L1+Z1elSWYivF0TzQcTwPzFz7JRJ9BxSw +NM166vHkxBMYmlTvE1oYkn8ba1gY52b4H4nwVeSN/+jZ/6sok5zR6JpZAoGBAN8G +aY8/g27b2ib7vKgg9InL5TYT7f4cV1IQnuJ0uNbZrFSboWO/ZyMcKBPgLP0iAZ/8 +4r/Ct0QB7gRhg+g7xICkon9Gj0GXNjSiaoqyQfoZdVX/5KFvBItc1YwQo1G+Svvj +o907qtIqifGSu4J7XA7cMPJSpaj+qxY/APSwuxLxAoGBAOWtjdIDgaswep1D2gNn +FmMHBzuqZWA9Vm4QYk0BBupl0JFnyxMbV+NL9KBc9q+pjuM9rPKz66aotQXHaM92 +zaCkJO3Kh4ZIkNULx5IBQH3KWTfe/Xu+UxktzRTBpogX3vjDQrFD23zKryzB2TxM +9so6RT8PkzTSNvya2uBxOn7JAoGBAI9rzzxYiswiw+Jn5sV0E+39WhRxso3Eaf8T +Qym8CBXae3EZeCruLoQsmjVV53iNguAAv0y0CijI2OimUS5qKQ7VUM5qcLusYyZr +//nbcoREFOnOGpgaDaEVfRqKpIxvxEbB+GHP+iUXSAg65Sye6e+AeFWNAo1v4FP5 +BkNU16jxAoGBAMG2VavizJTm4Nm7XYdiNZQ4X1x655q60pwWCrWsEmDnw5LEz4ei +PUmG4nvftiEOwgAHckNnb6KHennvtSsjqFWzo/p3tHlK/O9No7r2WNYbODOxSq1i +9mIffYLxfgJSUrRWlpX1paEg231DpijLR7b2/h+Xm0t8r4Z3xAGgC9sy +-----END RSA PRIVATE KEY----- diff --git a/.github/service/redis-tls/certs/redis.crt b/.github/service/redis-tls/certs/redis.crt new file mode 100644 index 0000000000..81700aa396 --- /dev/null +++ b/.github/service/redis-tls/certs/redis.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID6DCCAdACFG00zTKAU3QH8OsQYQCSkpHkxh53MA0GCSqGSIb3DQEBCwUAMDUx +EzARBgNVBAoMClJlZGlzIFRlc3QxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhv +cml0eTAeFw0yNDAzMDgwODE3NDJaFw0yNTAzMDgwODE3NDJaMCwxEzARBgNVBAoM +ClJlZGlzIFRlc3QxFTATBgNVBAMMDEdlbmVyaWMtY2VydDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMnHIR6eACxE1Ft+0cFAP0x+ZAXw0RMgbOT8TU5j +cturdhywZq5C9KJ0SKPfBxDiEjkRCQnyetsWfRlkt8VaW4z7I8e6P3szmCVlUy5u +2ODhyDOGwue+sI4mmzxO7kpKjY0S+uH1WtfcQG1e/8nzFc+vig1SMBFh47SJnjJd +I32WOgUG/q6MN5r/NLixfUrXIAUUnOLBYdW9C1FEn8BitiZeKgJotduGggjrXV6V +mtBbFw9oOrv1YhQsYs0zV//VoLMkzHRKLBJOr86wGfl0MO++cHOpDbzLT7LlJvQt +GeR4Cn2M1U1zn9fqZZRa9lZFFS95ys8XsmjV2KEGWwBTlH0CAwEAATANBgkqhkiG +9w0BAQsFAAOCAgEATau8XAaGVzaU23PWIhRR1+R8jQa+hZTK58qBSDFBGNjy06YT +I6+AfJQV23gxC20bshLONGItcUdkKXi+O0pElWaJ/mjQUYCt2vCAtH5LLwPLug6m +lP6YvufTiWuu6KZ5cl4fstKdTAIefcN9qb6OQYI9V6qLEIqY4t8VCQBkUtuNaCck +wyrq2BTzFNgyIDT5AS2L5gpLnahHz3iyi4dGTgZznPe2qZ3qzvxpzc68r16NMe22 +WujYVzzjHJimHJgEPjpct0DPhmc0edNk25iTRzK33DGCiWLBQ9U7BqcTjr6oMQf1 +GlcmZtI1hVKBVa2B4jLWm2avkH1egqVm2ZZmXvZLwvqNA7chR1DJCWCQFsiGxf4K +E9XceBsMWyV/ccG0Pby9RGj/NzW2wujDQWXaffnwKhkfrnOJxu2Yye1KJMge0xJj +AAJQaMgRCDYCraWNuKdyFutkafMCuaOa91xriUtgJPJI81oWo2NGeLVA6Sxhzuwt +9pWvutG1fKfTA/qbqBH7kgdT5ozUthQUBgfd8NPuL/hlN5yeZWVWsVBXGbW9TeLI +JjYNmWT1bmdDHyaiAKs8R6y5d7w462kCirrxUWNB9s6AvruR+6Zz+ZJwqxhpiuW+ +u9tEVBw4oyndHdk1Yd87+kNb07VZ7RpOCL5fqWPE3Oj7840B+hE1we4bJtk= +-----END CERTIFICATE----- diff --git a/.github/service/redis-tls/certs/redis.dh b/.github/service/redis-tls/certs/redis.dh new file mode 100644 index 0000000000..5677df11d0 --- /dev/null +++ b/.github/service/redis-tls/certs/redis.dh @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAuOlvuysLa1Aw3+Qybxi+a1CNN80Zp09U5AHFj7GcJn4Oy158rmdp +xrJOHP1KS+11Fj1XIiwNByRjNTaVmPeCpM823K7fzHnNfe/AxFDksomDc9CajCPe +xLOUojW5iFiGW1HZGhN5m5g1JOYa/4YRCOdrNmHwoKLjCIg+n7TXL1ICEktSxuPs +7HeZSNL69uJ/xoX/TlCoCU5ql9dLVnAvYVkaL9sA5n0hmlPgUAHOrsIGxpd0S9Ez +aYKVkNpaHzUUsq3yNLTlgeDQjq1v9ZCpDbLv3PuMoZFawNG/I+T34Ak+gYZ4ZcFi +3q/thwzQPw3LjrM36gByHx16jISuSF3QOwIBAg== +-----END DH PARAMETERS----- diff --git a/.github/service/redis-tls/certs/redis.key b/.github/service/redis-tls/certs/redis.key new file mode 100644 index 0000000000..eb7a695cc1 --- /dev/null +++ b/.github/service/redis-tls/certs/redis.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAycchHp4ALETUW37RwUA/TH5kBfDREyBs5PxNTmNy26t2HLBm +rkL0onRIo98HEOISOREJCfJ62xZ9GWS3xVpbjPsjx7o/ezOYJWVTLm7Y4OHIM4bC +576wjiabPE7uSkqNjRL64fVa19xAbV7/yfMVz6+KDVIwEWHjtImeMl0jfZY6BQb+ +row3mv80uLF9StcgBRSc4sFh1b0LUUSfwGK2Jl4qAmi124aCCOtdXpWa0FsXD2g6 +u/ViFCxizTNX/9WgsyTMdEosEk6vzrAZ+XQw775wc6kNvMtPsuUm9C0Z5HgKfYzV +TXOf1+pllFr2VkUVL3nKzxeyaNXYoQZbAFOUfQIDAQABAoIBAAhINiHNlnA6uwSu +Zemqu25mWbCsu8gvMokLmhi3mEVP+l8fFnfco7HvV/Px+ZZF0T2qZ1aTL1vCxou+ +SJS/KrbUsBlImcZyzbHrQMjNH/XLDq6ev21HtHOBPinxi3JdMQYzWzzfF0V48uQK +XDFr2t9VczMsxnBQNkp4w5eJnyVObJA+jPsAxXA1+2nj1ZVYqACrPzzEwPrWi4ji +rqTxRqS94DIVEID6PGB1SFoKjS6BHUktYooNboUir+idl634CVwSREp1QjPge2pW +BW52+Z/VHI4cqOvXJgdRX9K4jkHFLp0qyENflchyZ2AG1mxeTIZjfffaQvwgP6T2 +JC32cfkCgYEA7413fOAKIJfM12TBokXzyAmL66TRXehlyoW0UOyyR2pikUR2f5EL +enUbh2U8Btrk8DrKTKlPNGl2SC+SefxmW+FnPY+VDwqhYp3+YnMODE+2/i4tjAIU +wL1WauzAc/78cjyihEWlH6rA+OSRJCsSwki8Qn3a9EUI4mYUidtror8CgYEA16G1 +dRjDJG7KekVaTXz3ZAmwq+k9UKu4eoVPQhw22SEw/dBJ5olpMxkUFsCLVEle82mV +xcaEoAECI2/+3Us3wUmv0dJ6bW72pc7qdW7CQathDpwozaAPRE29QgP2W3HQERUy +IHr5N0Z1Yo7XGgAcuyOlU3d4/8S0z6rhuGQJo8MCgYEAgeRjdgLFewbUu7aWiDcG +COGkTRIBtLne+AGn1HmD8dVtvPcyidlMMApv8uqhsdXfbaNzLj5gBDtrN5kUA7Eo +j4mZQXgpiw5ok+C3nwpkA6j1wL2pVNGMDzabNT9K25rXp9nZBX/+GT2thUfqq4Hv +mgl2i1dS8kC8oIZZfKbNpmECgYBhMlYd2zSTJpGEPeCvjwXghPGq++6Uf2MfbxnD +3f3nL6vqrMmy7fuKeeJxQwdKzevL4qsNRCeiC/JP0Prb+zy9lp53AN4Il/z7zmIm +3u8XNM4CDOfjkCNxkW0e5bRVkd7M5HX86BGQFeVxsJtK8AQDYtTx46eZ+qvZ89fd +CtLBiwKBgCUOvKt1WGuBlHBy3mfXsf2UgQdJATMY/HHzvpFRKakri/VEFphugKms +v1ascCbeboYn8+yfAa2uNLGJ/u346dOfXoszA/1v5UzMlRZK5HYYgGGkRAoeTMsL +6BzAUFxSe5mVIvxbIvmFUreP/ZovMC74idoMA+N8OUifAzcNF+4E +-----END RSA PRIVATE KEY----- diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9869f27ec..7edc14796e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -198,6 +198,13 @@ jobs: REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" REDIS_SERVER_CLUSTER_SEEDS: "127.0.0.1:6479,127.0.0.1:6480,127.0.0.1:6481,127.0.0.1:6482,127.0.0.1:6483,127.0.0.1:6484" REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" + REDIS_SERVER_TLS_HOST: "127.0.0.1" + REDIS_SERVER_TLS_PORT: "6443" + REDIS_SERVER_TLS_PASSWORD: "l83aa26" + REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" + REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" + REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" + REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} From e5fed35bf8b5ae17a1d8347240cce82e4e76a9ad Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 23:40:52 +0800 Subject: [PATCH 44/97] =?UTF-8?q?Update:=20=E4=BF=AE=E5=A4=8D=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PhpRedisConnector.php | 7 ++-- .../redis/src/Connector/PredisConnector.php | 3 +- .../redis/tests/Tests/RedisHandlerTest.php | 34 +++++++++++-------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index 826d5d372c..f1630e2597 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -36,14 +36,15 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler // others: array, with PhpRedis >= 5.3.0, it allows setting auth and stream configuration. $extra = []; - if ($config->tls) { + if ($config->tls) + { $extra['stream'] = $config->tls; } - if ($extra) { + if ($extra) + { $arguments[] = $extra; } - $redis->connect(...$arguments); if (('' !== $config->password) && !$redis->auth($config->password) && null !== $redis->getLastError()) { diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index f789558c3c..c5def6c5ab 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -44,7 +44,8 @@ public static function connect(RedisDriverConfig $config): PredisHandler { $params['prefix'] = $config->prefix; } - if ($config->tls) { + if ($config->tls) + { $params['scheme'] = 'tls'; $params['ssl'] = $config->tls; } diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 1c3170953a..3b20e58e0b 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -22,9 +22,11 @@ public function testPhpRedisTlsConnection(): void 'REDIS_SERVER_TLS_CA_FILE', 'REDIS_SERVER_TLS_CERT_FILE', 'REDIS_SERVER_TLS_KEY_FILE', - ] as $key) { + ] as $key) + { $value = env($key); - if (empty($value)) { + if (empty($value)) + { self::markTestSkipped("tls options {$key} is empty, skip tls test"); } } @@ -46,9 +48,9 @@ public function testPhpRedisTlsConnection(): void tls: [ // https://www.php.net/context.ssl 'verify_peer_name' => false, - 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), - 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), - 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), ], ); @@ -97,14 +99,16 @@ public function testPhpRedisUnixSockConnection(): void public function testPredisTlsConnection(): void { foreach ([ - 'REDIS_SERVER_TLS_HOST', - 'REDIS_SERVER_TLS_PORT', - 'REDIS_SERVER_TLS_CA_FILE', - 'REDIS_SERVER_TLS_CERT_FILE', - 'REDIS_SERVER_TLS_KEY_FILE', - ] as $key) { + 'REDIS_SERVER_TLS_HOST', + 'REDIS_SERVER_TLS_PORT', + 'REDIS_SERVER_TLS_CA_FILE', + 'REDIS_SERVER_TLS_CERT_FILE', + 'REDIS_SERVER_TLS_KEY_FILE', + ] as $key) + { $value = env($key); - if (empty($value)) { + if (empty($value)) + { self::markTestSkipped("tls options {$key} is empty, skip tls test"); } } @@ -126,9 +130,9 @@ public function testPredisTlsConnection(): void tls: [ // https://www.php.net/context.ssl 'verify_peer_name' => false, - 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), - 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), - 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), ], ); From 3f2e6bc209d26c1530bd552e8012282cf552b160 Mon Sep 17 00:00:00 2001 From: auooru Date: Fri, 8 Mar 2024 22:25:15 +0800 Subject: [PATCH 45/97] =?UTF-8?q?Update:=20=E9=87=8D=E6=9E=84=20ci=20?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BA=92=E8=81=94?= =?UTF-8?q?=E4=B8=8E`tls`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/ci-prepare/action.yml | 5 +- .github/docker-compose.yml | 158 ++++++------------ .github/redis.conf | 2 +- .../service/redis-cluster/docker-compose.yml | 148 ++++++++++++++++ .github/shared-env.sh | 11 ++ .github/workflows/ci.yml | 62 +++++-- .github/workflows/phpcs.yml | 3 +- .github/workflows/phpstan.yml | 4 +- .github/workflows/rector.yml | 3 +- .../redis/tests/Tests/RedisHandlerTest.php | 16 +- 10 files changed, 279 insertions(+), 133 deletions(-) create mode 100644 .github/service/redis-cluster/docker-compose.yml create mode 100755 .github/shared-env.sh diff --git a/.github/actions/ci-prepare/action.yml b/.github/actions/ci-prepare/action.yml index 8a086cf4ec..1a21f83e69 100644 --- a/.github/actions/ci-prepare/action.yml +++ b/.github/actions/ci-prepare/action.yml @@ -12,8 +12,9 @@ runs: - name: Setup Services shell: bash run: | - docker-compose -f ./.github/docker-compose.yml up -d redis-cluster-node-0 - docker-compose -f ./.github/docker-compose.yml up -d ${{ inputs.env }} + docker network create imi-ci-service-network --subnet 172.10.12.0/24 + docker compose -f ./.github/service/redis-cluster/docker-compose.yml up -d + docker compose -f ./.github/docker-compose.yml up -d ${{ inputs.env }} redis-new docker exec ${{ inputs.env }} php -v docker exec ${{ inputs.env }} php -m docker exec ${{ inputs.env }} php --ri swoole diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 552094145a..ee1a0d77e9 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -1,13 +1,14 @@ -version: "3.4" -volumes: - shared-volume: - driver: local +version: '3.5' + +name: ci services: shared-tmp: image: busybox - command: chmod -R 777 /tmp/docker + container_name: shared-tmp + command: /tmp/shared-env.sh volumes: - - shared-volume:/tmp/docker + - /run/shared:/run/shared + - ./shared-env.sh:/tmp/shared-env.sh mysql: image: mysql:${MYSQL_DOCKER_VERSION} @@ -47,30 +48,35 @@ services: command: redis-server /etc/redis.conf volumes: - ./redis.conf:/etc/redis.conf - - shared-volume:/tmp/docker + - /run/shared:/run/shared ports: - 6379:6379 redis-new: image: bitnami/redis:7.2 - container_name: redis_new + container_name: redis-new depends_on: - shared-tmp volumes: - - ./service/redis-tls/certs:/opt/bitnami/redis/certs - - shared-volume:/tmp/docker + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + - /run/shared:/run/shared environment: - REDIS_PORT_NUMBER: 6380 + REDIS_PORT_NUMBER: 6377 REDIS_PASSWORD: "l83aa26" - REDIS_TLS_ENABLED: true + REDIS_TLS_ENABLED: "true" REDIS_TLS_PORT_NUMBER: 6443 REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" REDIS_TLS_AUTH_CLIENTS: "yes" + healthcheck: + test: ["CMD-SHELL", "redis-cli -h 127.0.0.1 -p 6377 -a l83aa26 INFO | grep 'redis_version'"] + interval: 3s + timeout: 60s + retries: 30 ports: - - "6380:6380" + - "6377:6377" - "6443:6443" rabbitmq: @@ -111,80 +117,6 @@ services: ports: - "9092:9092" - redis-cluster-node-1: - container_name: redis-cluster-node-1 - image: bitnami/redis-cluster:7.2 - environment: - REDIS_PORT_NUMBER: 6480 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - ports: - - "6480:6480" - - redis-cluster-node-2: - container_name: redis-cluster-node-2 - image: bitnami/redis-cluster:7.2 - environment: - REDIS_PORT_NUMBER: 6481 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - ports: - - "6481:6481" - - redis-cluster-node-3: - container_name: redis-cluster-node-3 - image: bitnami/redis-cluster:7.2 - environment: - REDIS_PORT_NUMBER: 6482 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - ports: - - "6482:6482" - - redis-cluster-node-4: - container_name: redis-cluster-node-4 - image: bitnami/redis-cluster:7.2 - environment: - REDIS_PORT_NUMBER: 6483 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - ports: - - "6483:6483" - - redis-cluster-node-5: - container_name: redis-cluster-node-5 - image: bitnami/redis-cluster:7.2 - environment: - REDIS_PORT_NUMBER: 6484 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - ports: - - "6484:6484" - - redis-cluster-node-0: - container_name: redis-cluster-node-0 - image: bitnami/redis-cluster:7.2 - depends_on: - - redis-cluster-node-1 - - redis-cluster-node-2 - - redis-cluster-node-3 - - redis-cluster-node-4 - - redis-cluster-node-5 - environment: - REDIS_PORT_NUMBER: 6479 - REDIS_PASSWORD: "l83aa26" - REDIS_NODES: "redis-cluster-node-1:6480 redis-cluster-node-2:6481 redis-cluster-node-3:6482 redis-cluster-node-4:6483 redis-cluster-node-5:6484 redis-cluster-node-0:6479" - REDISCLI_AUTH: "l83aa26" - REDIS_CLUSTER_REPLICAS: "1" - REDIS_CLUSTER_CREATOR: "yes" - healthcheck: - test: ["CMD-SHELL", "redis-cli -h 127.0.0.1 -p 6479 -a l83aa26 CLUSTER INFO | grep 'cluster_state:ok'"] - interval: 3s - timeout: 60s - retries: 30 - ports: - - "6479:6479" - swoole: container_name: "swoole" image: ghcr.io/${REPOSITORY_OWNER}/imi-swoole-test:${IMAGE_VERSION} @@ -196,7 +128,6 @@ services: - rabbitmq - kafka1 - postgres - - redis-cluster-node-0 environment: MYSQL_SERVER_HOST: mysql REDIS_SERVER_HOST: ${REDIS_SERVER_HOST} @@ -206,18 +137,21 @@ services: KAFKA_BOOTSTRAP_SERVERS: "kafka1:9092" GITHUB_TOKEN: ${GITHUB_TOKEN} REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" - REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" - REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" - REDIS_SERVER_TLS_HOST: redis_new + REDIS_SERVER_CLUSTER_SEEDS: "172.10.12.2:6379,172.10.12.3:6379,172.10.12.4:6379,172.10.12.5:6379,172.10.12.6:6379,172.10.12.7:6379" + REDIS_SERVER_TLS_CLUSTER_SEEDS: "172.10.12.2:6443,172.10.12.3:6443,172.10.12.4:6443,172.10.12.5:6443,172.10.12.6:6443,172.10.12.7:6443" + REDIS_SERVER_UNIX_SOCK: "/run/shared/redis.sock" + REDIS_SERVER_TLS_HOST: "redis-new" REDIS_SERVER_TLS_PORT: "6443" REDIS_SERVER_TLS_PASSWORD: "l83aa26" - REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" - REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" - REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" - REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" + REDIS_SERVER_TLS_CA_FILE: "/imi/.github/service/redis-tls/certs/ca.crt" + REDIS_SERVER_TLS_CERT_FILE: "/imi/.github/service/redis-tls/certs/client.crt" + REDIS_SERVER_TLS_KEY_FILE: "/imi/.github/service/redis-tls/certs/client.key" volumes: - "${GITHUB_WORKSPACE}:/imi:rw" - - shared-volume:/tmp/docker + - /run/shared:/run/shared + networks: + default: + proxies: working_dir: /imi command: tail -f /dev/null tty: true @@ -232,7 +166,6 @@ services: - rabbitmq - kafka1 - postgres - - redis-cluster-node-0 environment: MYSQL_SERVER_HOST: mysql REDIS_SERVER_HOST: ${REDIS_SERVER_HOST} @@ -242,15 +175,15 @@ services: KAFKA_BOOTSTRAP_SERVERS: "kafka1:9092" GITHUB_TOKEN: ${GITHUB_TOKEN} REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" - REDIS_SERVER_CLUSTER_SEEDS: "redis-cluster-node-0:6479,redis-cluster-node-1:6480,redis-cluster-node-2:6481,redis-cluster-node-3:6482,redis-cluster-node-4:6483,redis-cluster-node-5:6484" - REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" - REDIS_SERVER_TLS_HOST: redis_new + REDIS_SERVER_CLUSTER_SEEDS: "172.10.12.2:6379,172.10.12.3:6379,172.10.12.4:6379,172.10.12.5:6379,172.10.12.6:6379,172.10.12.7:6379" + REDIS_SERVER_TLS_CLUSTER_SEEDS: "172.10.12.2:6443,172.10.12.3:6443,172.10.12.4:6443,172.10.12.5:6443,172.10.12.6:6443,172.10.12.7:6443" + REDIS_SERVER_UNIX_SOCK: "/run/shared/redis.sock" + REDIS_SERVER_TLS_HOST: "redis-new" REDIS_SERVER_TLS_PORT: "6443" REDIS_SERVER_TLS_PASSWORD: "l83aa26" - REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" - REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" - REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" - REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" + REDIS_SERVER_TLS_CA_FILE: "/imi/.github/service/redis-tls/certs/ca.crt" + REDIS_SERVER_TLS_CERT_FILE: "/imi/.github/service/redis-tls/certs/client.crt" + REDIS_SERVER_TLS_KEY_FILE: "/imi/.github/service/redis-tls/certs/client.key" build: context: . dockerfile: php.dockerfile @@ -262,7 +195,10 @@ services: volumes: - "${GITHUB_WORKSPACE}:/imi:rw" - "/tmp/base_cache:/tmp/base_cache:rw" - - shared-volume:/tmp/docker + - /run/shared:/run/shared + networks: + default: + proxies: working_dir: /imi command: tail -f /dev/null @@ -275,6 +211,16 @@ services: - "${GITHUB_WORKSPACE}:/imi:rw" - "/tmp/base_cache:/tmp/base_cache:rw" - "/tmp/base_cache/phpstan:/tmp/phpstan:rw" + networks: + default: + proxies: working_dir: /imi command: tail -f /dev/null - tty: true \ No newline at end of file + tty: true + +networks: + default: + driver: bridge + proxies: + name: "imi-ci-service-network" + external: true \ No newline at end of file diff --git a/.github/redis.conf b/.github/redis.conf index e693751bc8..573cc8805c 100644 --- a/.github/redis.conf +++ b/.github/redis.conf @@ -112,7 +112,7 @@ tcp-backlog 511 # incoming connections. There is no default, so Redis will not listen # on a unix socket when not specified. # -unixsocket /tmp/docker/redis.sock +unixsocket /run/shared/redis.sock unixsocketperm 777 # Close the connection after a client is idle for N seconds (0 to disable) diff --git a/.github/service/redis-cluster/docker-compose.yml b/.github/service/redis-cluster/docker-compose.yml new file mode 100644 index 0000000000..0a56be4fd7 --- /dev/null +++ b/.github/service/redis-cluster/docker-compose.yml @@ -0,0 +1,148 @@ +version: '3.5' + +name: redis-cluster +services: + node-0: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + depends_on: + - node-1 + - node-2 + - node-3 + - node-4 + - node-5 + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDISCLI_AUTH: l83aa26 + REDIS_CLUSTER_REPLICAS: 1 + REDIS_CLUSTER_CREATOR: yes + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + healthcheck: + test: ["CMD-SHELL", "redis-cli -h 127.0.0.1 -p $${REDIS_PORT_NUMBER:-6379} -a $${REDIS_PASSWORD} CLUSTER INFO | grep 'cluster_state:ok'"] + interval: 3s + timeout: 60s + retries: 30 + networks: + proxies: + aliases: + - redis-cluster-node-0 + ipv4_address: 172.10.12.2 + + node-1: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + networks: + proxies: + aliases: + - redis-cluster-node-1 + ipv4_address: 172.10.12.3 + + node-2: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + networks: + proxies: + aliases: + - redis-cluster-node-2 + ipv4_address: 172.10.12.4 + + node-3: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + networks: + proxies: + aliases: + - redis-cluster-node-3 + ipv4_address: 172.10.12.5 + + node-4: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + networks: + proxies: + aliases: + - redis-cluster-node-4 + ipv4_address: 172.10.12.6 + + node-5: + image: bitnami/redis-cluster:7.2 + volumes: + - "${GITHUB_WORKSPACE}/.github/service/redis-tls/certs:/opt/bitnami/redis/certs" + environment: + REDIS_PORT_NUMBER: 6379 + REDIS_PASSWORD: l83aa26 + REDIS_NODES: node-0 node-1 node-2 node-3 node-4 node-5 + REDIS_TLS_ENABLED: "true" + REDIS_TLS_PORT_NUMBER: 6443 + REDIS_TLS_CERT_FILE: "/opt/bitnami/redis/certs/redis.crt" + REDIS_TLS_KEY_FILE: "/opt/bitnami/redis/certs/redis.key" + REDIS_TLS_CA_FILE: "/opt/bitnami/redis/certs/ca.crt" + REDIS_TLS_DH_PARAMS_FILE: "/opt/bitnami/redis/certs/redis.dh" + REDIS_TLS_AUTH_CLIENTS: "yes" + networks: + proxies: + aliases: + - redis-cluster-node-5 + ipv4_address: 172.10.12.7 + +networks: + proxies: + name: "imi-ci-service-network" + external: true \ No newline at end of file diff --git a/.github/shared-env.sh b/.github/shared-env.sh new file mode 100755 index 0000000000..1f7958ff34 --- /dev/null +++ b/.github/shared-env.sh @@ -0,0 +1,11 @@ +#!/bin/env sh + +set -ex + +echo "init shared" + +rm -rf /run/shared/* || true +chmod -R 777 /run/shared + + +tail -f /dev/null \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7edc14796e..e5119f6c21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,9 +60,14 @@ jobs: if: ${{ env.test_prepared && always() }} run: | docker ps + docker logs shared-tmp || true + docker logs redis-new || true + docker exec ${ENV_SERVICE} bash -c "ls -lha /run/shared" echo ">>> redis-cluster-node-0" - docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ninfo server' | nc redis-cluster-node-0 6479 -w 1" - docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc redis-cluster-node-0 6479 -w 1" + docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ninfo server' | nc redis-cluster-node-0-1 6379 -w 1" + docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc redis-cluster-node-0-1 6379 -w 1" + echo ">>> redis-new" + docker exec ${ENV_SERVICE} bash -c "echo -e 'auth l83aa26\r\ninfo server' | nc redis-new 6377 -w 1" - name: Test if: ${{ env.test_prepared && always() }} run: docker exec ${ENV_SERVICE} composer test @@ -144,8 +149,10 @@ jobs: - name: Setup Services shell: bash run: | - sudo apt update && sudo apt install -y rsync netcat-openbsd - docker-compose -f ./.github/docker-compose.yml up -d redis-cluster-node-0 mysql postgres redis rabbitmq kafka1 + sudo apt update && sudo apt install -y rsync netcat-openbsd tree + docker network create imi-ci-service-network --subnet 172.10.12.0/24 + docker compose -f ./.github/service/redis-cluster/docker-compose.yml up -d + docker compose -f ./.github/docker-compose.yml up -d mysql postgres redis redis-new rabbitmq kafka1 echo "127.0.0.1 kafka1" | sudo tee -a /etc/hosts - name: Setup swoole-cli run: .github/script/install-swoole-cli.sh ${{ matrix.swoole-cli }} @@ -187,8 +194,21 @@ jobs: if: ${{ env.test_prepared && always() }} run: | docker ps - echo -e 'auth l83aa26\r\ninfo server' | nc 127.0.0.1 6479 -w 1 - echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc 127.0.0.1 6479 -w 1 + docker logs shared-tmp + docker logs redis + find /run/shared -name *.sock + tree -alfugh /run/shared + echo ">>> redis" + echo -e 'info server' | nc 127.0.0.1 6379 -w 1 + echo ">>> =====" + echo ">>> redis-new" + echo -e 'auth l83aa26\r\ninfo server' | nc 127.0.0.1 6377 -w 1 + echo ">>> =====" + docker compose -f ./.github/service/redis-cluster/docker-compose.yml logs + echo ">>> redis-cluster" + echo -e 'auth l83aa26\r\ninfo server' | nc 172.10.12.2 6379 -w 1 + echo -e 'auth l83aa26\r\ncluster info\r\ncluster nodes' | nc 172.10.12.2 6379 -w 1 + docker compose -f ./.github/service/redis-cluster/docker-compose.yml exec node-0 cat /bitnami/redis/data/nodes.conf - name: Test if: ${{ env.test_prepared && always() }} run: composer test @@ -196,15 +216,15 @@ jobs: if: ${{ env.test_prepared && always() }} env: REDIS_SERVER_CLUSTER_PASSWORD: "l83aa26" - REDIS_SERVER_CLUSTER_SEEDS: "127.0.0.1:6479,127.0.0.1:6480,127.0.0.1:6481,127.0.0.1:6482,127.0.0.1:6483,127.0.0.1:6484" - REDIS_SERVER_UNIX_SOCK: "/tmp/docker/redis.sock" + REDIS_SERVER_CLUSTER_SEEDS: "172.10.12.2:6379,172.10.12.3:6379,172.10.12.4:6379,172.10.12.5:6379,172.10.12.6:6379,172.10.12.7:6379" + REDIS_SERVER_TLS_CLUSTER_SEEDS: "172.10.12.2:6443,172.10.12.3:6443,172.10.12.4:6443,172.10.12.5:6443,172.10.12.6:6443,172.10.12.7:6443" + REDIS_SERVER_UNIX_SOCK: "/run/shared/redis.sock" REDIS_SERVER_TLS_HOST: "127.0.0.1" REDIS_SERVER_TLS_PORT: "6443" REDIS_SERVER_TLS_PASSWORD: "l83aa26" - REDIS_SERVER_TLS_CA_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/ca.crt" - REDIS_SERVER_TLS_CERT_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.crt" - REDIS_SERVER_TLS_KEY_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.key" - REDIS_TLS_DH_PARAMS_FILE: "${GITHUB_ACTION_PATH}/.github/service/redis-tls/certs/redis.dh" + REDIS_SERVER_TLS_CA_FILE: ${{ github.workspace }}/.github/service/redis-tls/certs/ca.crt + REDIS_SERVER_TLS_CERT_FILE: ${{ github.workspace }}/.github/service/redis-tls/certs/client.crt + REDIS_SERVER_TLS_KEY_FILE: ${{ github.workspace }}/.github/service/redis-tls/certs/client.key run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} @@ -264,10 +284,8 @@ jobs: strategy: fail-fast: false matrix: -# php: ["8.1", "8.2"] -# swoole: [v5.1.0, v5.0.3] - php: ["8.2"] - swoole: [v5.1.0] + php: ["8.2"] # ["8.1", "8.2"] + swoole: [v5.1.0] # [v5.1.0, v5.0.3] roadrunner: [2.7.*] env: MYSQL_SERVER_PASSWORD: "root" @@ -288,8 +306,11 @@ jobs: socket=/tmp/mysql.sock - name: Setup Redis uses: shogo82148/actions-setup-redis@v1 + id: setup-redis with: - redis-version: "6.x" + redis-version: "7.2" + redis-port: "6379" + redis-tls-port: "6443" - name: Get Openssl Dir id: opecssl-dir run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT @@ -352,6 +373,13 @@ jobs: run: composer test - name: Test redis if: ${{ env.test_prepared && always() }} + env: + REDIS_SERVER_UNIX_SOCK: ${{ steps.setup-redis.outputs.redis-unix-socket }} + REDIS_SERVER_TLS_HOST: "127.0.0.1" + REDIS_SERVER_TLS_PORT: "6443" + REDIS_SERVER_TLS_CA_FILE: ${{ steps.setup-redis.outputs.redis-tls-dir }}/ca.crt + REDIS_SERVER_TLS_CERT_FILE: ${{ steps.setup-redis.outputs.redis-tls-dir }}/client.crt + REDIS_SERVER_TLS_KEY_FILE: ${{ steps.setup-redis.outputs.redis-tls-dir }}/client.key run: composer test-redis - name: Test swoole if: ${{ env.test_prepared && always() }} diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml index e74f3ce87a..7895201636 100644 --- a/.github/workflows/phpcs.yml +++ b/.github/workflows/phpcs.yml @@ -53,7 +53,8 @@ jobs: - name: Prepare2 run: | echo "::group::Env prepare" - docker-compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} + docker network create imi-ci-service-network --subnet 172.10.12.0/24 + docker compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} echo "::endgroup::" echo "::group::Env info" docker exec ${ENV_SERVICE} php -v diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 671172468f..8b1f220181 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -17,6 +17,7 @@ concurrency: jobs: phpstan: + if: false runs-on: ubuntu-latest strategy: fail-fast: false @@ -61,7 +62,8 @@ jobs: - name: Prepare2 run: | echo "::group::Env prepare" - docker-compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} + docker network create imi-ci-service-network --subnet 172.10.12.0/24 + docker compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} echo "::endgroup::" echo "::group::Env info" docker exec ${ENV_SERVICE} php -v diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index d0ddea1c2e..75bedda188 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -45,7 +45,8 @@ jobs: - name: Prepare2 run: | echo "::group::Env prepare" - docker-compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} + docker network create imi-ci-service-network --subnet 172.10.12.0/24 + docker compose -f ./.github/docker-compose.yml up -d ${ENV_SERVICE} echo "::endgroup::" echo "::group::Env info" docker exec ${ENV_SERVICE} php -v diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 3b20e58e0b..7a58e9066d 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -65,9 +65,13 @@ public function testPhpRedisTlsConnection(): void public function testPhpRedisUnixSockConnection(): void { - if (\PHP_OS_FAMILY !== 'Linux') + if (\PHP_OS_FAMILY === 'Windows') { - self::markTestSkipped('unixsock test only support linux'); + self::markTestSkipped('unixsock test not support windows'); + } + + if (!env('REDIS_SERVER_UNIX_SOCK')) { + self::markTestSkipped('unixsock test not support, please set REDIS_SERVER_UNIX_SOCK'); } $config = new RedisDriverConfig( @@ -147,9 +151,13 @@ public function testPredisTlsConnection(): void public function testPredisUnixSockConnection(): void { - if (\PHP_OS_FAMILY !== 'Linux') + if (\PHP_OS_FAMILY === 'Windows') { - self::markTestSkipped('unixsock test only support linux'); + self::markTestSkipped('unixsock test not support windows'); + } + + if (!env('REDIS_SERVER_UNIX_SOCK')) { + self::markTestSkipped('unixsock test not support, please set REDIS_SERVER_UNIX_SOCK'); } $config = new RedisDriverConfig( From cbe148ab58dc118af7f0e1b50b6c2d9cd7968cc4 Mon Sep 17 00:00:00 2001 From: auooru Date: Sat, 9 Mar 2024 21:42:01 +0800 Subject: [PATCH 46/97] =?UTF-8?q?Update:=20Redis=20Cluster=20tls=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PhpRedisConnector.php | 22 ++- .../redis/src/Connector/PredisConnector.php | 5 + .../redis/tests/Tests/RedisHandlerTest.php | 129 +++++++++++++++--- 3 files changed, 137 insertions(+), 19 deletions(-) diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index f1630e2597..3dd9bc2a66 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -14,6 +14,9 @@ class PhpRedisConnector implements IRedisConnector */ public static function connect(RedisDriverConfig $config): PhpRedisHandler { + // PHP Redis 5.3.2+ supports SSL/TLS. + // if ( version_compare( phpversion( 'redis' ), '5.3.2', '>=' ) ) {} + $redis = new \Redis(); $host = $config->host; @@ -67,7 +70,24 @@ public static function connectCluster(RedisDriverConfig $config): PhpRedisCluste $readTimeout = $config->readTimeout; $password = $config->password; - $redis = new \RedisCluster(null, $seeds, $timeout, $readTimeout, false, $password); + $arguments = [ + null, + $seeds, + $timeout, + $readTimeout, + false, + $password, + ]; + + if ($config->tls) + { + // @link https://github.com/phpredis/phpredis/issues/1600#issuecomment-776109815 + // @link https://github.com/phpredis/phpredis/issues/1607#issuecomment-653578201 + // stream context + $arguments[] = $config->tls; + } + + $redis = new \RedisCluster(...$arguments); self::applyOptions($redis, $config); diff --git a/src/Components/redis/src/Connector/PredisConnector.php b/src/Components/redis/src/Connector/PredisConnector.php index c5def6c5ab..ef3b6788b8 100644 --- a/src/Components/redis/src/Connector/PredisConnector.php +++ b/src/Components/redis/src/Connector/PredisConnector.php @@ -68,6 +68,11 @@ public static function connectCluster(RedisDriverConfig $config): PredisClusterH { $options['parameters']['database'] = $config->database; } + if ($config->tls) + { + $options['parameters']['scheme'] = 'tls'; + $options['parameters']['ssl'] = $config->tls; + } if ($config->prefix) { $options['prefix'] = $config->prefix; diff --git a/src/Components/redis/tests/Tests/RedisHandlerTest.php b/src/Components/redis/tests/Tests/RedisHandlerTest.php index 7a58e9066d..ff8c673f40 100644 --- a/src/Components/redis/tests/Tests/RedisHandlerTest.php +++ b/src/Components/redis/tests/Tests/RedisHandlerTest.php @@ -8,6 +8,12 @@ use Imi\Redis\Connector\PredisConnector; use Imi\Redis\Connector\RedisDriverConfig; use Imi\Redis\Enum\RedisMode; +use Imi\Redis\Handler\IRedisClusterHandler; +use Imi\Redis\Handler\IRedisHandler; +use Imi\Redis\Handler\PhpRedisClusterHandler; +use Imi\Redis\Handler\PhpRedisHandler; +use Imi\Redis\Handler\PredisClusterHandler; +use Imi\Redis\Handler\PredisHandler; use Monolog\Test\TestCase; use function Imi\env; @@ -56,11 +62,7 @@ public function testPhpRedisTlsConnection(): void $handler = PhpRedisConnector::connect($config); - self::assertTrue($handler->ping()); - $key = 'imi:test:set_' . bin2hex(random_bytes(8)); - self::assertTrue($handler->set($key, '123456')); - self::assertEquals('123456', $handler->get($key)); - self::assertTrue($handler->del($key) > 0); + self::assertHandlerSuccess($handler); } public function testPhpRedisUnixSockConnection(): void @@ -70,7 +72,8 @@ public function testPhpRedisUnixSockConnection(): void self::markTestSkipped('unixsock test not support windows'); } - if (!env('REDIS_SERVER_UNIX_SOCK')) { + if (!env('REDIS_SERVER_UNIX_SOCK')) + { self::markTestSkipped('unixsock test not support, please set REDIS_SERVER_UNIX_SOCK'); } @@ -93,11 +96,53 @@ public function testPhpRedisUnixSockConnection(): void $handler = PhpRedisConnector::connect($config); - self::assertTrue($handler->ping()); - $key = 'imi:test:set_' . bin2hex(random_bytes(8)); - self::assertTrue($handler->set($key, '123456')); - self::assertEquals('123456', $handler->get($key)); - self::assertTrue($handler->del($key) > 0); + self::assertHandlerSuccess($handler); + } + + public function testPhpRedisTlsClusterConnection(): void + { + foreach ([ + 'REDIS_SERVER_TLS_CLUSTER_SEEDS', + 'REDIS_SERVER_TLS_CA_FILE', + 'REDIS_SERVER_TLS_CERT_FILE', + 'REDIS_SERVER_TLS_KEY_FILE', + ] as $key) + { + $value = env($key); + if (empty($value)) + { + self::markTestSkipped("tls options {$key} is empty, skip tls test"); + } + } + + $seeds = explode(',', env('REDIS_SERVER_TLS_CLUSTER_SEEDS', '')); + + $config = new RedisDriverConfig( + client: 'phpredis', + mode: RedisMode::Cluster, + scheme: null, + host: '0.0.0.0', + port: 0, + seeds: $seeds, + password: env('REDIS_SERVER_TLS_PASSWORD'), + database: 0, + prefix: '', + timeout: 1, + readTimeout: 1, + serialize: false, + options: [], + tls: [ + // https://www.php.net/context.ssl + 'verify_peer_name' => false, + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + ], + ); + + $handler = PhpRedisConnector::connectCluster($config); + + self::assertHandlerSuccess($handler); } public function testPredisTlsConnection(): void @@ -142,11 +187,7 @@ public function testPredisTlsConnection(): void $handler = PredisConnector::connect($config); - self::assertEquals('PONG', (string) $handler->ping()); - $key = 'imi:test:set_' . bin2hex(random_bytes(8)); - self::assertTrue($handler->set($key, '123456')); - self::assertEquals('123456', $handler->get($key)); - self::assertTrue($handler->del($key) > 0); + self::assertHandlerSuccess($handler); } public function testPredisUnixSockConnection(): void @@ -156,7 +197,8 @@ public function testPredisUnixSockConnection(): void self::markTestSkipped('unixsock test not support windows'); } - if (!env('REDIS_SERVER_UNIX_SOCK')) { + if (!env('REDIS_SERVER_UNIX_SOCK')) + { self::markTestSkipped('unixsock test not support, please set REDIS_SERVER_UNIX_SOCK'); } @@ -179,7 +221,58 @@ public function testPredisUnixSockConnection(): void $handler = PredisConnector::connect($config); - self::assertEquals('PONG', (string) $handler->ping()); + self::assertHandlerSuccess($handler); + } + + public function testPredisTlsClusterConnection(): void + { + foreach ([ + 'REDIS_SERVER_TLS_CLUSTER_SEEDS', + 'REDIS_SERVER_TLS_CA_FILE', + 'REDIS_SERVER_TLS_CERT_FILE', + 'REDIS_SERVER_TLS_KEY_FILE', + ] as $key) + { + $value = env($key); + if (empty($value)) + { + self::markTestSkipped("tls options {$key} is empty, skip tls test"); + } + } + + $seeds = explode(',', env('REDIS_SERVER_TLS_CLUSTER_SEEDS', '')); + + $config = new RedisDriverConfig( + client: 'predis', + mode: RedisMode::Cluster, + scheme: null, + host: '0.0.0.0', + port: 0, + seeds: $seeds, + password: env('REDIS_SERVER_TLS_PASSWORD'), + database: 0, + prefix: '', + timeout: 1, + readTimeout: 1, + serialize: false, + options: [], + tls: [ + // https://www.php.net/context.ssl + 'verify_peer_name' => false, + 'cafile' => env('REDIS_SERVER_TLS_CA_FILE'), + 'local_cert' => env('REDIS_SERVER_TLS_CERT_FILE'), + 'local_pk' => env('REDIS_SERVER_TLS_KEY_FILE'), + ], + ); + + $handler = PredisConnector::connectCluster($config); + + self::assertHandlerSuccess($handler); + } + + protected static function assertHandlerSuccess(IRedisHandler|IRedisClusterHandler|PhpRedisHandler|PhpRedisClusterHandler|PredisHandler|PredisClusterHandler $handler): void + { + self::assertTrue($handler->isConnected()); $key = 'imi:test:set_' . bin2hex(random_bytes(8)); self::assertTrue($handler->set($key, '123456')); self::assertEquals('123456', $handler->get($key)); From 95351a8671d427ab4398e34eabfb7c15d3126046 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 11 Mar 2024 17:40:24 +0800 Subject: [PATCH 47/97] =?UTF-8?q?Update:=20=E5=AE=8C=E5=96=84=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/src/Connector/PhpRedisConnector.php | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Components/redis/src/Connector/PhpRedisConnector.php b/src/Components/redis/src/Connector/PhpRedisConnector.php index 3dd9bc2a66..da801813ac 100644 --- a/src/Components/redis/src/Connector/PhpRedisConnector.php +++ b/src/Components/redis/src/Connector/PhpRedisConnector.php @@ -9,14 +9,29 @@ class PhpRedisConnector implements IRedisConnector { + protected static function checkLibrary(): void + { + // 检查redis库是否存在 + if (!\extension_loaded('redis')) + { + throw new \RuntimeException('Please install phpredis extension'); + } + // PHP Redis 5.3.2+ supports SSL/TLS. + // 最低支持版本考虑提升到 5.3.7 + if (!version_compare(phpversion('redis'), '5.3.2', '>=')) + { + throw new \RuntimeException('PHP Redis extension version must be 5.3.2+'); + } + } + /** * 初始化 Redis 连接. */ public static function connect(RedisDriverConfig $config): PhpRedisHandler { - // PHP Redis 5.3.2+ supports SSL/TLS. - // if ( version_compare( phpversion( 'redis' ), '5.3.2', '>=' ) ) {} + self::checkLibrary(); + // 可以考虑适配 6.0 初始化方式 $redis = new \Redis(); $host = $config->host; @@ -37,7 +52,7 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler $arguments[] = 0; // retry_interval $arguments[] = $config->readTimeout; - // others: array, with PhpRedis >= 5.3.0, it allows setting auth and stream configuration. + // extra array, with PhpRedis >= 5.3.0, it allows setting auth and stream configuration. $extra = []; if ($config->tls) { @@ -49,6 +64,8 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler } $redis->connect(...$arguments); + + // todo 需要支持 acl 用户名与密码验证 if (('' !== $config->password) && !$redis->auth($config->password) && null !== $redis->getLastError()) { throw new \RedisException($redis->getLastError()); @@ -65,17 +82,19 @@ public static function connect(RedisDriverConfig $config): PhpRedisHandler public static function connectCluster(RedisDriverConfig $config): PhpRedisClusterHandler { + self::checkLibrary(); + $seeds = $config->seeds; $timeout = $config->timeout; $readTimeout = $config->readTimeout; $password = $config->password; $arguments = [ - null, + null, // name $seeds, $timeout, $readTimeout, - false, + false, // persistent $password, ]; @@ -83,6 +102,7 @@ public static function connectCluster(RedisDriverConfig $config): PhpRedisCluste { // @link https://github.com/phpredis/phpredis/issues/1600#issuecomment-776109815 // @link https://github.com/phpredis/phpredis/issues/1607#issuecomment-653578201 + // stream context $arguments[] = $config->tls; } From eb72d3a58c609699e080dd77978c1ef6998f351b Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 11 Mar 2024 18:14:35 +0800 Subject: [PATCH 48/97] =?UTF-8?q?Update:=20=E8=B0=83=E6=95=B4=20fork=20mod?= =?UTF-8?q?el=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/model/src/RedisModel.php | 2 +- .../tests/Tests/Model/AbstractRedisModel.php | 22 +++++++++---------- .../Tests/Model/AbstractRedisModelHash.php | 14 ++++++------ .../Model/AbstractRedisModelHashObject.php | 14 ++++++------ 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index f038e31995..049ae8491b 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -911,7 +911,7 @@ protected function parseSaveData(array &$data): void * * @return class-string */ - public static function fork(?int $db = null, ?string $poolName = null, ?string $formatter = null): string + public static function fork(?string $poolName = null, ?string $formatter = null, ?int $db = null): string { // todo 觉得 model 的 meta 设置不统一, 建议 BaseModel 能提供更多底层支持扩展支持 // 建议能传入 RedisEntity 对象的全部参数,能适用于更多场景 diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModel.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModel.php index 3f941455c0..887dd9e587 100644 --- a/src/Components/redis/tests/Tests/Model/AbstractRedisModel.php +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModel.php @@ -20,7 +20,7 @@ abstract class AbstractRedisModel extends TestCase public function testSave(): void { - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -31,7 +31,7 @@ public function testSave(): void public function testFind(): void { - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $expected = [ 'id' => 1, 'name' => 'a', @@ -62,7 +62,7 @@ public function testSelect(): void 'age' => 22, ], ]; - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 2, 'name' => 'b', @@ -83,7 +83,7 @@ public function testSelect(): void public function testDelete(): void { - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::find('1-a'); $this->assertNotNull($record); $this->assertTrue($record->delete()); @@ -94,7 +94,7 @@ public function testSafeDelete(): void { // --更新-- // 原始记录 - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 114514, 'name' => __METHOD__, @@ -158,7 +158,7 @@ public function testSafeDelete(): void public function testDeleteBatch(): void { - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -187,7 +187,7 @@ public function testTTL(): void 'name' => 'a', 'age' => 11, ]; - $model = TestRedisModel2::fork(null, 'test_phpredis_standalone', $this->formatter); + $model = TestRedisModel2::fork('test_phpredis_standalone', $this->formatter); $record = $model::newInstance($expected); $this->assertTrue($record->save()); @@ -207,7 +207,7 @@ public function testTTL(): void public function testFormatter(): void { - $model = TestRedisWithFormatterModel::fork(null, 'test_phpredis_standalone', $this->formatter); + $model = TestRedisWithFormatterModel::fork('test_phpredis_standalone', $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -269,7 +269,7 @@ public function testSerialize(): void 'age' => 22, ], ]; - $model = TestRedisModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 2, 'name' => 'b', @@ -303,7 +303,7 @@ public function testSerializable(): void 'name' => 'b', 'age' => 22, ]; - $model = TestRedisModelSerializable::fork(null, 'test_phpredis_standalone', $this->formatter); + $model = TestRedisModelSerializable::fork('test_phpredis_standalone', $this->formatter); $record = $model::newInstance($data); $record->save(); @@ -320,7 +320,7 @@ public function testSerializable(): void public function testVirtual(): void { - $model = TestRedisModelVirtual::fork(null, 'test_phpredis_standalone', $this->formatter); + $model = TestRedisModelVirtual::fork('test_phpredis_standalone', $this->formatter); $record = $model::newInstance([ 'id' => 2, 'name' => 'b', diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php index e51978b96f..7840fea3f5 100644 --- a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHash.php @@ -15,7 +15,7 @@ abstract class AbstractRedisModelHash extends TestCase public function testSave(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -26,7 +26,7 @@ public function testSave(): void public function testFind(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); $expected = [ 'id' => 1, 'name' => 'a', @@ -42,7 +42,7 @@ public function testFind(): void public function testSelect(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); $expected = [ [ 'id' => 1, @@ -73,7 +73,7 @@ public function testSelect(): void public function testDelete(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); $record = $model::find([ 'id' => 1, 'name' => 'a', @@ -88,7 +88,7 @@ public function testDelete(): void public function testSafeDelete(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); // --更新-- // 原始记录 $record = $model::newInstance([ @@ -150,7 +150,7 @@ public function testSafeDelete(): void public function testDeleteBatch(): void { - $model = TestRedisHashModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -174,7 +174,7 @@ public function testDeleteBatch(): void public function testFormatter(): void { - $model = TestRedisHashWithFormatterModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashWithFormatterModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', diff --git a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php index 4486f8a70f..aa9a809e2e 100644 --- a/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php +++ b/src/Components/redis/tests/Tests/Model/AbstractRedisModelHashObject.php @@ -16,7 +16,7 @@ abstract class AbstractRedisModelHashObject extends TestCase public function testSave(): void { /** @var class-string $model */ - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -28,7 +28,7 @@ public function testSave(): void public function testFind(): void { /** @var class-string $model */ - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); $expected = [ 'id' => 1, 'name' => 'a', @@ -45,7 +45,7 @@ public function testFind(): void public function testSelect(): void { /** @var class-string $model */ - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); $expected = [ [ 'id' => 1, @@ -76,7 +76,7 @@ public function testSelect(): void public function testDelete(): void { - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); $record = $model::find([ 'id' => 1, 'name' => 'a', @@ -92,7 +92,7 @@ public function testDelete(): void public function testSafeDelete(): void { /** @var class-string $model */ - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); // --更新-- // 原始记录 $record = $model::newInstance([ @@ -156,7 +156,7 @@ public function testSafeDelete(): void public function testDeleteBatch(): void { - $model = TestRedisHashObjectModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectModel::fork($this->poolName, $this->formatter); $record = $model::newInstance([ 'id' => 1, 'name' => 'a', @@ -180,7 +180,7 @@ public function testDeleteBatch(): void public function testColumnType(): void { - $model = TestRedisHashObjectColumnTypeModel::fork(null, $this->poolName, $this->formatter); + $model = TestRedisHashObjectColumnTypeModel::fork($this->poolName, $this->formatter); $record = $model::newInstance(); $record->setJson([ 'name' => 'imi', From 125b01394a75d24d75a003820e8dbb6e6ba68163 Mon Sep 17 00:00:00 2001 From: auooru Date: Mon, 11 Mar 2024 20:06:09 +0800 Subject: [PATCH 49/97] =?UTF-8?q?Update:=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/SUMMARY.md | 4 +- doc/base/version/2.1-3.0.md | 9 + doc/components/orm/RedisModel.md | 31 +++ doc/components/redis/function.md | 173 +++++++++++++++ doc/components/redis/index.md | 360 ++++++++++--------------------- 5 files changed, 333 insertions(+), 244 deletions(-) create mode 100644 doc/components/redis/function.md diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 2e883a2896..b0dded04a4 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -183,7 +183,9 @@ * [前置和后置事件](components/orm/relation/events.md) * [数据库迁移](components/orm/migration.md) * [Redis](components/redis/index.md) -* [Redis 模型](components/orm/RedisModel.md) + * [连接与配置](components/redis/index.md) + * [Redis 使用](components/redis/function.md) + * [Redis 模型](components/orm/RedisModel.md) * [内存表模型](components/orm/MemoryTableModel.md) * [缓存](components/cache/index.md) * [使用说明](components/cache/index.md) diff --git a/doc/base/version/2.1-3.0.md b/doc/base/version/2.1-3.0.md index 032f4be6d8..a8abb6b5e0 100644 --- a/doc/base/version/2.1-3.0.md +++ b/doc/base/version/2.1-3.0.md @@ -115,6 +115,15 @@ return [ 由于 Hprose 官方弃坑,废弃并移出主仓库,代码仓库: +### imi-redis + +* 弃用为核心独立组件 +* 适配新连接中心 +* 支持多客户端支持(`phpredis`, `predis`) +* 支持`TLS`连接 +* 新的使用方法请[参考文档](/v3.0/components/redis/index.html) +* 废弃`\Imi\Redis\RedisHandler::class`,使用到的地方请迁移为`\Imi\Redis\Handler\IRedisHandler::class`或者具体实现类 + ### 废弃 * 废弃命名空间声明在 `config.php` 的写法,统一写到 `composer.json` 的 `imi.namespace` diff --git a/doc/components/orm/RedisModel.md b/doc/components/orm/RedisModel.md index e98be390c5..7947bd8273 100644 --- a/doc/components/orm/RedisModel.md +++ b/doc/components/orm/RedisModel.md @@ -232,3 +232,34 @@ TestRedisModel::deleteBatch('kkk', [ 'name' => 'imi' ]); ``` + +### Fork 模型 + +Fork 模型特性,支持在运行阶段创建一个新的模型类,这个类从原模型继承。 + +并且支持指定新模型类使用的:数据库名、数据表名、连接池名。 + +方法定义: + +```php +/** + * Fork 模型. + * + * @return class-string + */ +public static function fork(?string $poolName = null, ?string $formatter = null, int $db = null) +``` + +例子: + +```php +// 重新指定模型要使用的连接池 +$newClassName = TestModel::fork('redis_pool_2'); + +// 重新指定模型要使用的序列化类 +$formatter = \Imi\Util\Format\PhpSerialize::class; +$newClassName = TestModel::fork('redis_pool_2', $formatter); + +// 重新指定模型使用指定 db (不推荐把redis分多个库的用法) +$newClassName = TestModel::fork('redis_pool_2', null, 3); +``` diff --git a/doc/components/redis/function.md b/doc/components/redis/function.md new file mode 100644 index 0000000000..bedff88586 --- /dev/null +++ b/doc/components/redis/function.md @@ -0,0 +1,173 @@ +# Redis 使用 + +[toc] + +## 基础使用 + +**注意,方法和传参在不同客户端中可能存在不一致性,具体参考各自客户端文档** + +### 获取连接对象 + +```php +use \Imi\Redis\RedisManager; + +/** @var \Imi\Redis\Handler\PhpRedisHandler $redis */ +$redis = RedisManager::getInstance(); + +// 获取到`$redis`返回值为实现`Imi\Redis\Handler\IRedisHandler`的具体驱动 +// 建议根据实际情况使用注解或强类型把`$redis`的类型限制为`Imi\Redis\Handler\IRedisHandler`具体实现驱动以活动更好的`IDE`提示支持 +// 具体驱动有: +// \Imi\Redis\Handler\PhpRedisHandler +// \Imi\Redis\Handler\PhpRedisClusterHandler +// \Imi\Redis\Handler\PredisHandler +// \Imi\Redis\Handler\PredisClusterHandler + +$redis->set('imi:redis:test', date('Y-m-d H:i:s')); +$datetime = $redis->get('imi:redis:test'); +``` + +### 获取新连接对象 + +每次调用都尝试从连接池中获取新的对象! + +```php +use \Imi\Redis\RedisManager; +$redis = RedisManager::getNewInstance(); +$redis->get('key-xxx') +``` + +### 获取默认连接池名称 + +```php +use \Imi\Redis\RedisManager; +echo RedisManager::getDefaultPoolName(); +``` + +### 便捷操作(不建议使用) + +> **不建议使用该模式,`ide`提示无法完善** + +`Redis::方法名()` + +```php +use \Imi\Redis\Redis; +Redis::set('imi:redis:test', date('Y-m-d H:i:s')); +$datetime = Redis::get('imi:redis:test'); +``` + +### 回调方式使用`Redis` + +```php +use \Imi\Redis\Redis; +$result = Redis::use(function(Imi\Redis\Handler\IRedisHandler $redis){ + $redis->set('a', 1); + return true; +}); // true +``` + +## 进阶使用 + +### evalEx + +imi 封装了一个基于 `evalSha` 和 `eval` 的便捷方法,优先使用 `evalSha` 尝试,失败则使用 `eval` 方法。 + +定义:`public function evalEx($script, $args = null, $num_keys = null)` + +```php +use \Imi\Redis\RedisManager; +/** @var \Imi\Redis\Handler\PhpRedisHandler $redis */ +$redis = RedisManager::getInstance(); +return false !== $redis->evalEx(<<