modify plugin name
This commit is contained in:
+3
-3
@@ -441,12 +441,12 @@ if (!function_exists('redis')) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Kiri\Cache\Redis|Redis
|
* @return \Kiri\Redis\Redis|Redis
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
function redis(): \Kiri\Cache\Redis|Redis
|
function redis(): \Kiri\Redis\Redis|Redis
|
||||||
{
|
{
|
||||||
return Kiri::getDi()->get(\Kiri\Cache\Redis::class);
|
return Kiri::getDi()->get(\Kiri\Redis\Redis::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Created by PhpStorm.
|
|
||||||
* User: whwyy
|
|
||||||
* Date: 2018/5/2 0002
|
|
||||||
* Time: 14:51
|
|
||||||
*/
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Kiri\Cache;
|
|
||||||
|
|
||||||
|
|
||||||
use JetBrains\PhpStorm\Pure;
|
|
||||||
use Kiri\Abstracts\Component;
|
|
||||||
use Swoole\Coroutine\System;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class File
|
|
||||||
* @package Kiri\Cache
|
|
||||||
*/
|
|
||||||
class File extends Component implements ICache
|
|
||||||
{
|
|
||||||
public string $path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @param $val
|
|
||||||
* @return string|int
|
|
||||||
*/
|
|
||||||
public function set($key, $val): string|int
|
|
||||||
{
|
|
||||||
if (is_array($val) || is_object($val)) {
|
|
||||||
$val = swoole_serialize($val);
|
|
||||||
}
|
|
||||||
$tmpFile = $this->getCacheKey($key);
|
|
||||||
if (!$this->exists($tmpFile)) {
|
|
||||||
touch($tmpFile);
|
|
||||||
}
|
|
||||||
return System::writeFile($tmpFile, $val, LOCK_EX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @param array $hashKeys
|
|
||||||
* @return array|bool
|
|
||||||
*/
|
|
||||||
public function hMGet($key, array $hashKeys): array|bool
|
|
||||||
{
|
|
||||||
$hash = $this->get($key);
|
|
||||||
if (!is_array($hash)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$nowHash = [];
|
|
||||||
foreach ($hashKeys as $hashKey) {
|
|
||||||
$nowHash[$hashKey] = $hash[$hashKey] ?? null;
|
|
||||||
}
|
|
||||||
return $nowHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @param array $val
|
|
||||||
* @return bool|int|string
|
|
||||||
*/
|
|
||||||
public function hMSet($key, array $val): bool|int|string
|
|
||||||
{
|
|
||||||
$hash = $this->get($key);
|
|
||||||
if (!is_array($hash)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$merge = array_merge($hash, $val);
|
|
||||||
return $this->set($key, $merge);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $key
|
|
||||||
* @param string $hashKey
|
|
||||||
* @return string|int|bool
|
|
||||||
*/
|
|
||||||
public function hGet(string $key, string $hashKey): string|int|bool
|
|
||||||
{
|
|
||||||
$hash = $this->get($key);
|
|
||||||
if (!is_array($hash)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $hash[$hashKey] ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @param $hashKey
|
|
||||||
* @param $hashValue
|
|
||||||
* @return bool|int|string
|
|
||||||
*/
|
|
||||||
public function hSet($key, $hashKey, $hashValue): bool|int|string
|
|
||||||
{
|
|
||||||
$hash = $this->get($key);
|
|
||||||
if (!is_array($hash)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hash[$hashKey] = $hashValue;
|
|
||||||
|
|
||||||
return $this->set($key, $hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
#[Pure] public function exists($key): bool
|
|
||||||
{
|
|
||||||
return file_exists($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @return mixed|bool
|
|
||||||
*/
|
|
||||||
public function get($key): mixed
|
|
||||||
{
|
|
||||||
$tmpFile = $this->getCacheKey($key);
|
|
||||||
if (!$this->exists($tmpFile)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$content = file_get_contents($tmpFile);
|
|
||||||
return swoole_unserialize($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $key
|
|
||||||
* @return string
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
private function getCacheKey($key): string
|
|
||||||
{
|
|
||||||
return storage($key, 'cache');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,8 @@ use Kiri;
|
|||||||
use Kiri\Abstracts\Component;
|
use Kiri\Abstracts\Component;
|
||||||
use Kiri\Abstracts\Config;
|
use Kiri\Abstracts\Config;
|
||||||
use Kiri\Context;
|
use Kiri\Context;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
use Swoole\Error;
|
use Swoole\Error;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@@ -20,7 +22,19 @@ use Throwable;
|
|||||||
class Connection extends Component
|
class Connection extends Component
|
||||||
{
|
{
|
||||||
|
|
||||||
use Alias;
|
|
||||||
|
private Pool $pool;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->pool = $this->getContainer()->get(Pool::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,15 +97,15 @@ class Connection extends Component
|
|||||||
public function get(mixed $config): ?PDO
|
public function get(mixed $config): ?PDO
|
||||||
{
|
{
|
||||||
$coroutineName = $config['cds'];
|
$coroutineName = $config['cds'];
|
||||||
|
//
|
||||||
if (($connection = Context::getContext($coroutineName)) instanceof PDO) {
|
// if (($connection = Context::getContext($coroutineName)) instanceof PDO) {
|
||||||
return $connection;
|
// return $connection;
|
||||||
}
|
// }
|
||||||
|
|
||||||
$minx = Config::get('databases.pool.min', 1);
|
$minx = Config::get('databases.pool.min', 1);
|
||||||
|
|
||||||
/** @var PDO $connections */
|
/** @var PDO $connections */
|
||||||
$connections = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $minx);
|
$connections = $this->pool->get($coroutineName, $this->create($coroutineName, $config), $minx);
|
||||||
if (Context::hasContext('begin_' . $coroutineName)) {
|
if (Context::hasContext('begin_' . $coroutineName)) {
|
||||||
$connections->beginTransaction();
|
$connections->beginTransaction();
|
||||||
}
|
}
|
||||||
@@ -121,7 +135,7 @@ class Connection extends Component
|
|||||||
*/
|
*/
|
||||||
public function addItem(string $name, PDO $PDO)
|
public function addItem(string $name, PDO $PDO)
|
||||||
{
|
{
|
||||||
$this->getPool()->push($name, $PDO);
|
$this->pool->push($name, $PDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -132,7 +146,7 @@ class Connection extends Component
|
|||||||
*/
|
*/
|
||||||
public function initConnections($name, $max)
|
public function initConnections($name, $max)
|
||||||
{
|
{
|
||||||
$this->getPool()->initConnections($name, $max);
|
$this->pool->initConnections($name, $max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,7 +162,7 @@ class Connection extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getPool()->push($coroutineName, $client);
|
$this->pool->push($coroutineName, $client);
|
||||||
Context::remove($coroutineName);
|
Context::remove($coroutineName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +183,7 @@ class Connection extends Component
|
|||||||
*/
|
*/
|
||||||
public function connection_clear($name)
|
public function connection_clear($name)
|
||||||
{
|
{
|
||||||
$this->getPool()->clean($name);
|
$this->pool->clean($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,17 +216,8 @@ class Connection extends Component
|
|||||||
public function disconnect($coroutineName)
|
public function disconnect($coroutineName)
|
||||||
{
|
{
|
||||||
Context::remove($coroutineName);
|
Context::remove($coroutineName);
|
||||||
$this->getPool()->clean($coroutineName);
|
$this->pool->clean($coroutineName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Pool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function getPool(): Pool
|
|
||||||
{
|
|
||||||
return Kiri::getDi()->get(Pool::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ namespace Kiri\Pool;
|
|||||||
|
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Kiri\Context;
|
|
||||||
use Kiri\Abstracts\Component;
|
use Kiri\Abstracts\Component;
|
||||||
use Kiri\Abstracts\Config;
|
use Kiri\Abstracts\Config;
|
||||||
|
use Kiri\Context;
|
||||||
use Kiri\Exception\ConfigException;
|
use Kiri\Exception\ConfigException;
|
||||||
use Kiri\Pool\Helper\SplQueue;
|
|
||||||
use Swoole\Coroutine;
|
use Swoole\Coroutine;
|
||||||
use Swoole\Coroutine\Channel;
|
use Swoole\Coroutine\Channel;
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kiri\Pool\Helper;
|
namespace Kiri\Pool;
|
||||||
|
|
||||||
interface QueueInterface
|
interface QueueInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public function isEmpty(): bool;
|
public function isEmpty(): bool;
|
||||||
|
|
||||||
public function push(mixed $data, float $timeout = -1): bool;
|
public function push(mixed $data, float $timeout = -1): bool;
|
||||||
|
|
||||||
|
|
||||||
public function pop(float $timeout = -1): mixed;
|
public function pop(float $timeout = -1): mixed;
|
||||||
|
|
||||||
|
|
||||||
public function stats(): array;
|
public function stats(): array;
|
||||||
|
|
||||||
|
|
||||||
public function close(): bool;
|
public function close(): bool;
|
||||||
|
|
||||||
|
|
||||||
public function length(): int;
|
public function length(): int;
|
||||||
|
|
||||||
|
|
||||||
public function isFull(): bool;
|
public function isFull(): bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
|
|
||||||
namespace Kiri\Pool;
|
|
||||||
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Exception;
|
|
||||||
use Kiri\Abstracts\Component;
|
|
||||||
use Kiri\Context;
|
|
||||||
use Kiri\Exception\ConfigException;
|
|
||||||
use Kiri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class RedisClient
|
|
||||||
* @package Kiri\Pool
|
|
||||||
*/
|
|
||||||
class Redis extends Component
|
|
||||||
{
|
|
||||||
|
|
||||||
use Alias;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $config
|
|
||||||
* @param bool $isMaster
|
|
||||||
* @return mixed
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function get(mixed $config, bool $isMaster = false): mixed
|
|
||||||
{
|
|
||||||
$coroutineName = $config['host'];
|
|
||||||
if (Context::hasContext($coroutineName)) {
|
|
||||||
return Context::getContext($coroutineName);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pool = $config['pool'] ?? ['min' => 1, 'max' => 100];
|
|
||||||
|
|
||||||
$clients = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $pool['min'] ?? 1);
|
|
||||||
return Context::setContext($coroutineName, $clients);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
* @param mixed $config
|
|
||||||
* @return Closure
|
|
||||||
*/
|
|
||||||
public function create(string $name, mixed $config): Closure
|
|
||||||
{
|
|
||||||
return static function () use ($name, $config) {
|
|
||||||
return Kiri::getDi()->create(\Kiri\Cache\Base\Redis::class, [$config]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $config
|
|
||||||
* @param bool $isMaster
|
|
||||||
* @throws ConfigException
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function release(array $config, bool $isMaster = false)
|
|
||||||
{
|
|
||||||
$coroutineName = $config['host'];
|
|
||||||
if (!Context::hasContext($coroutineName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->getPool()->push($coroutineName, Context::getContext($coroutineName));
|
|
||||||
Context::remove($coroutineName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $config
|
|
||||||
* @param bool $isMaster
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function destroy(array $config, bool $isMaster = false)
|
|
||||||
{
|
|
||||||
$this->getPool()->clean($config['host']);
|
|
||||||
Context::remove($config['host']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $config
|
|
||||||
* @param bool $isMaster
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function connection_clear(array $config, bool $isMaster = false)
|
|
||||||
{
|
|
||||||
$this->getPool()->clean($config['host']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Pool
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function getPool(): Pool
|
|
||||||
{
|
|
||||||
return Kiri::getDi()->get(Pool::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param $isMaster
|
|
||||||
* @param $max
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function initConnections($name, $isMaster, $max)
|
|
||||||
{
|
|
||||||
$this->getPool()->initConnections($name, $max);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,101 +1,101 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kiri\Pool\Helper;
|
namespace Kiri\Pool;
|
||||||
|
|
||||||
|
|
||||||
use JetBrains\PhpStorm\Pure;
|
use JetBrains\PhpStorm\Pure;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class SplQueue implements QueueInterface
|
class SplQueue implements QueueInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
private \SplQueue $channel;
|
private \SplQueue $channel;
|
||||||
|
|
||||||
|
|
||||||
public int $errCode = 0;
|
public int $errCode = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $max
|
* @param int $max
|
||||||
*/
|
*/
|
||||||
#[Pure] public function __construct(public int $max)
|
#[Pure] public function __construct(public int $max)
|
||||||
{
|
{
|
||||||
$this->channel = new \SplQueue();
|
$this->channel = new \SplQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isEmpty(): bool
|
public function isEmpty(): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement isEmpty() method.
|
// TODO: Implement isEmpty() method.
|
||||||
return $this->channel->count() < 1;
|
return $this->channel->count() < 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $data
|
* @param mixed $data
|
||||||
* @param float $timeout
|
* @param float $timeout
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function push(mixed $data, float $timeout = -1): bool
|
public function push(mixed $data, float $timeout = -1): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement push() method.
|
// TODO: Implement push() method.
|
||||||
$this->channel->enqueue($data);
|
$this->channel->enqueue($data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param float $timeout
|
* @param float $timeout
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function pop(float $timeout = -1): mixed
|
public function pop(float $timeout = -1): mixed
|
||||||
{
|
{
|
||||||
// TODO: Implement pop() method.
|
// TODO: Implement pop() method.
|
||||||
return $this->channel->dequeue();
|
return $this->channel->dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function stats(): array
|
public function stats(): array
|
||||||
{
|
{
|
||||||
// TODO: Implement stats() method.
|
// TODO: Implement stats() method.
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function close(): bool
|
public function close(): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement close() method.
|
// TODO: Implement close() method.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function length(): int
|
public function length(): int
|
||||||
{
|
{
|
||||||
// TODO: Implement length() method.
|
// TODO: Implement length() method.
|
||||||
return $this->channel->count();
|
return $this->channel->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isFull(): bool
|
public function isFull(): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement isFull() method.
|
// TODO: Implement isFull() method.
|
||||||
return $this->channel->count() >= $this->max;
|
return $this->channel->count() >= $this->max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,65 +1,65 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Created by PhpStorm.
|
* Created by PhpStorm.
|
||||||
* User: whwyy
|
* User: whwyy
|
||||||
* Date: 2018/11/8 0008
|
* Date: 2018/11/8 0008
|
||||||
* Time: 16:35
|
* Time: 16:35
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Kiri\Cache;
|
namespace Kiri\Redis;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface ICache
|
* Interface ICache
|
||||||
* @package Kiri\Cache
|
* @package Kiri\Cache
|
||||||
*/
|
*/
|
||||||
interface ICache
|
interface CacheInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param $val
|
* @param $val
|
||||||
* @return string|int
|
* @return string|int
|
||||||
*/
|
*/
|
||||||
public function set($key, $val): string|int;
|
public function set($key, $val): string|int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @return string|int|bool
|
* @return string|int|bool
|
||||||
*/
|
*/
|
||||||
public function get($key): mixed;
|
public function get($key): mixed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param array $hashKeys
|
* @param array $hashKeys
|
||||||
* @return array|bool|null
|
* @return array|bool|null
|
||||||
*/
|
*/
|
||||||
public function hMGet($key, array $hashKeys): array|bool|null;
|
public function hMGet($key, array $hashKeys): array|bool|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param array $val
|
* @param array $val
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function hMSet($key, array $val): mixed;
|
public function hMSet($key, array $val): mixed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $hashKey
|
* @param string $hashKey
|
||||||
* @return string|int|bool
|
* @return string|int|bool
|
||||||
*/
|
*/
|
||||||
public function hGet(string $key, string $hashKey): string|int|bool;
|
public function hGet(string $key, string $hashKey): string|int|bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param $hashKey
|
* @param $hashKey
|
||||||
* @param $hashValue
|
* @param $hashValue
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function hSet($key, $hashKey, $hashValue): mixed;
|
public function hSet($key, $hashKey, $hashValue): mixed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function exists($key): bool;
|
public function exists($key): bool;
|
||||||
}
|
}
|
||||||
@@ -1,186 +1,171 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kiri\Cache\Base;
|
namespace Kiri\Redis;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Kiri\Abstracts\Logger;
|
use Kiri;
|
||||||
use Kiri\Events\EventProvider;
|
use Kiri\Abstracts\Logger;
|
||||||
use Kiri\Exception\RedisConnectException;
|
use Kiri\Exception\RedisConnectException;
|
||||||
use Kiri;
|
use Kiri\Pool\StopHeartbeatCheck;
|
||||||
use Kiri\Pool\StopHeartbeatCheck;
|
use Kiri\Server\Events\OnWorkerExit;
|
||||||
use Kiri\Server\Events\OnWorkerExit;
|
use RedisException;
|
||||||
use RedisException;
|
use Swoole\Timer;
|
||||||
use Swoole\Timer;
|
use function error;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Redis implements StopHeartbeatCheck
|
class Helper implements StopHeartbeatCheck
|
||||||
{
|
{
|
||||||
|
|
||||||
const DB_ERROR_MESSAGE = 'The system is busy, please try again later.';
|
private ?\Redis $pdo = null;
|
||||||
|
|
||||||
|
public string $host;
|
||||||
private ?\Redis $pdo = null;
|
|
||||||
|
public int $port;
|
||||||
public string $host;
|
|
||||||
|
public int $database = 0;
|
||||||
public int $port;
|
|
||||||
|
public string $auth = '';
|
||||||
public int $database = 0;
|
|
||||||
|
public string $prefix = '';
|
||||||
public string $auth = '';
|
|
||||||
|
public int $timeout = 30;
|
||||||
public string $prefix = '';
|
|
||||||
|
public int $read_timeout = 30;
|
||||||
public int $timeout = 30;
|
|
||||||
|
public array $pool = [];
|
||||||
public int $read_timeout = 30;
|
|
||||||
|
private int $_timer = -1;
|
||||||
public array $pool = [];
|
|
||||||
|
private int $_last = 0;
|
||||||
private int $_timer = -1;
|
|
||||||
|
|
||||||
private int $_last = 0;
|
|
||||||
|
/**
|
||||||
|
* @param array $config
|
||||||
|
*/
|
||||||
/**
|
public function __construct(array $config)
|
||||||
* @param array $config
|
{
|
||||||
*/
|
$this->host = $config['host'];
|
||||||
public function __construct(array $config)
|
$this->port = $config['port'];
|
||||||
{
|
$this->database = $config['databases'];
|
||||||
$this->host = $config['host'];
|
$this->auth = $config['auth'];
|
||||||
$this->port = $config['port'];
|
$this->prefix = $config['prefix'];
|
||||||
$this->database = $config['databases'];
|
$this->timeout = $config['timeout'];
|
||||||
$this->auth = $config['auth'];
|
$this->read_timeout = $config['read_timeout'];
|
||||||
$this->prefix = $config['prefix'];
|
$this->pool = $config['pool'];
|
||||||
$this->timeout = $config['timeout'];
|
}
|
||||||
$this->read_timeout = $config['read_timeout'];
|
|
||||||
$this->pool = $config['pool'];
|
|
||||||
}
|
public function init()
|
||||||
|
{
|
||||||
|
$this->heartbeat_check();
|
||||||
public function init()
|
}
|
||||||
{
|
|
||||||
$this->heartbeat_check();
|
|
||||||
}
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function heartbeat_check(): void
|
||||||
|
{
|
||||||
/**
|
|
||||||
* @param Kiri\Server\Events\OnWorkerExit $exit
|
if ($this->_timer === -1) {
|
||||||
* @return void
|
$this->_timer = Timer::tick(1000, fn() => $this->waite());
|
||||||
*/
|
}
|
||||||
public function onWorkerExit(OnWorkerExit $exit)
|
}
|
||||||
{
|
|
||||||
$this->stopHeartbeatCheck();
|
|
||||||
}
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
/**
|
private function waite(): void
|
||||||
*
|
{
|
||||||
*/
|
try {
|
||||||
public function heartbeat_check(): void
|
if ($this->_timer === -1) {
|
||||||
{
|
Kiri::getDi()->get(Logger::class)->critical('timer end');
|
||||||
|
$this->stopHeartbeatCheck();
|
||||||
if ($this->_timer === -1) {
|
}
|
||||||
$this->_timer = Timer::tick(1000, fn() => $this->waite());
|
if (time() - $this->_last > intval($this->pool['tick'] ?? 60)) {
|
||||||
}
|
$this->stopHeartbeatCheck();
|
||||||
}
|
|
||||||
|
$this->pdo = null;
|
||||||
|
}
|
||||||
/**
|
} catch (\Throwable $throwable) {
|
||||||
* @throws Exception
|
error($throwable);
|
||||||
*/
|
}
|
||||||
private function waite(): void
|
}
|
||||||
{
|
|
||||||
try {
|
|
||||||
if ($this->_timer === -1) {
|
/**
|
||||||
Kiri::getDi()->get(Logger::class)->critical('timer end');
|
*
|
||||||
$this->stopHeartbeatCheck();
|
*/
|
||||||
}
|
public function stopHeartbeatCheck(): void
|
||||||
if (time() - $this->_last > intval($this->pool['tick'] ?? 60)) {
|
{
|
||||||
$this->stopHeartbeatCheck();
|
if ($this->_timer > -1) {
|
||||||
|
Timer::clear($this->_timer);
|
||||||
$this->pdo = null;
|
}
|
||||||
}
|
$this->_timer = -1;
|
||||||
} catch (\Throwable $throwable) {
|
}
|
||||||
error($throwable);
|
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param array $arguments
|
||||||
/**
|
* @return mixed
|
||||||
*
|
* @throws RedisConnectException|RedisException
|
||||||
*/
|
*/
|
||||||
public function stopHeartbeatCheck(): void
|
public function __call(string $name, array $arguments)
|
||||||
{
|
{
|
||||||
if ($this->_timer > -1) {
|
if (!method_exists($this, $name)) {
|
||||||
Timer::clear($this->_timer);
|
return $this->_pdo()->{$name}(...$arguments);
|
||||||
}
|
}
|
||||||
$this->_timer = -1;
|
return $this->{$name}(...$arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @return \Redis
|
||||||
* @param array $arguments
|
* @throws RedisConnectException
|
||||||
* @return mixed
|
* @throws RedisException
|
||||||
* @throws RedisConnectException|RedisException
|
*/
|
||||||
*/
|
public function _pdo(): \Redis
|
||||||
public function __call(string $name, array $arguments)
|
{
|
||||||
{
|
if ($this->_timer === -1) {
|
||||||
if (!method_exists($this, $name)) {
|
$this->heartbeat_check();
|
||||||
return $this->_pdo()->{$name}(...$arguments);
|
}
|
||||||
}
|
$this->_last = time();
|
||||||
return $this->{$name}(...$arguments);
|
if (!($this->pdo instanceof \Redis) || !$this->pdo->ping('isOk')) {
|
||||||
}
|
$this->pdo = $this->newClient();
|
||||||
|
}
|
||||||
|
return $this->pdo;
|
||||||
/**
|
}
|
||||||
* @return \Redis
|
|
||||||
* @throws RedisConnectException
|
|
||||||
* @throws RedisException
|
/**
|
||||||
*/
|
* @return \Redis
|
||||||
public function _pdo(): \Redis
|
* @throws RedisConnectException
|
||||||
{
|
*/
|
||||||
if ($this->_timer === -1) {
|
private function newClient(): \Redis
|
||||||
$this->heartbeat_check();
|
{
|
||||||
}
|
$redis = new \Redis();
|
||||||
$this->_last = time();
|
if (!$redis->connect($this->host, $this->port, $this->timeout)) {
|
||||||
if (!($this->pdo instanceof \Redis) || !$this->pdo->ping('isOk')) {
|
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $this->host, $this->port));
|
||||||
$this->pdo = $this->newClient();
|
}
|
||||||
}
|
if (!empty($this->auth) && !$redis->auth($this->auth)) {
|
||||||
return $this->pdo;
|
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth));
|
||||||
}
|
}
|
||||||
|
if ($this->read_timeout < 0) {
|
||||||
|
$this->read_timeout = 0;
|
||||||
/**
|
}
|
||||||
* @return \Redis
|
$redis->select($this->database);
|
||||||
* @throws RedisConnectException
|
if ($this->read_timeout > 0) {
|
||||||
*/
|
$redis->setOption(\Redis::OPT_READ_TIMEOUT, $this->read_timeout);
|
||||||
private function newClient(): \Redis
|
}
|
||||||
{
|
$redis->setOption(\Redis::OPT_PREFIX, $this->prefix);
|
||||||
$redis = new \Redis();
|
return $redis;
|
||||||
if (!$redis->connect($this->host, $this->port, $this->timeout)) {
|
|
||||||
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $this->host, $this->port));
|
}
|
||||||
}
|
|
||||||
if (!empty($this->auth) && !$redis->auth($this->auth)) {
|
}
|
||||||
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth));
|
|
||||||
}
|
|
||||||
if ($this->read_timeout < 0) {
|
|
||||||
$this->read_timeout = 0;
|
|
||||||
}
|
|
||||||
$redis->select($this->database);
|
|
||||||
if ($this->read_timeout > 0) {
|
|
||||||
$redis->setOption(\Redis::OPT_READ_TIMEOUT, $this->read_timeout);
|
|
||||||
}
|
|
||||||
$redis->setOption(\Redis::OPT_PREFIX, $this->prefix);
|
|
||||||
return $redis;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,191 +1,201 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Created by PhpStorm.
|
* Created by PhpStorm.
|
||||||
* User: whwyy
|
* User: whwyy
|
||||||
* Date: 2018/4/27 0027
|
* Date: 2018/4/27 0027
|
||||||
* Time: 11:00
|
* Time: 11:00
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Kiri\Cache;
|
namespace Kiri\Redis;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Kiri\Abstracts\Component;
|
use Kiri;
|
||||||
use Kiri\Abstracts\Config;
|
use Kiri\Abstracts\Component;
|
||||||
use Kiri\Core\Json;
|
use Kiri\Abstracts\Config;
|
||||||
use Kiri\Events\EventProvider;
|
use Kiri\Core\Json;
|
||||||
use Kiri\Exception\ConfigException;
|
use Kiri\Exception\ConfigException;
|
||||||
use Kiri;
|
use Kiri\Pool\Pool;
|
||||||
use Kiri\Pool\Redis as PoolRedis;
|
use Kiri\Server\Events\OnWorkerExit;
|
||||||
use Kiri\Annotation\Inject;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
use Kiri\Server\Events\OnWorkerExit;
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
/**
|
||||||
use Swoole\Timer;
|
* Class Redis
|
||||||
|
* @package Kiri\Cache
|
||||||
/**
|
* @mixin \Redis
|
||||||
* Class Redis
|
*/
|
||||||
* @package Kiri\Cache
|
class Redis extends Component
|
||||||
* @mixin \Redis
|
{
|
||||||
*/
|
|
||||||
class Redis extends Component
|
|
||||||
{
|
const REDIS_OPTION_HOST = 'host';
|
||||||
|
const REDIS_OPTION_PORT = 'port';
|
||||||
|
const REDIS_OPTION_PREFIX = 'prefix';
|
||||||
const REDIS_OPTION_HOST = 'host';
|
const REDIS_OPTION_AUTH = 'auth';
|
||||||
const REDIS_OPTION_PORT = 'port';
|
const REDIS_OPTION_DATABASES = 'databases';
|
||||||
const REDIS_OPTION_PREFIX = 'prefix';
|
const REDIS_OPTION_TIMEOUT = 'timeout';
|
||||||
const REDIS_OPTION_AUTH = 'auth';
|
const REDIS_OPTION_POOL = 'pool';
|
||||||
const REDIS_OPTION_DATABASES = 'databases';
|
const REDIS_OPTION_POOL_TICK = 'tick';
|
||||||
const REDIS_OPTION_TIMEOUT = 'timeout';
|
const REDIS_OPTION_POOL_MIN = 'min';
|
||||||
const REDIS_OPTION_POOL = 'pool';
|
const REDIS_OPTION_POOL_MAX = 'max';
|
||||||
const REDIS_OPTION_POOL_TICK = 'tick';
|
|
||||||
const REDIS_OPTION_POOL_MIN = 'min';
|
|
||||||
const REDIS_OPTION_POOL_MAX = 'max';
|
private Kiri\Pool\Pool $pool;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ConfigException
|
* @throws ConfigException
|
||||||
* @throws ContainerExceptionInterface
|
* @throws ContainerExceptionInterface
|
||||||
* @throws NotFoundExceptionInterface
|
* @throws NotFoundExceptionInterface
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
$connections = Kiri::getDi()->get(PoolRedis::class);
|
$this->pool = Kiri::getDi()->get(Pool::class);
|
||||||
|
|
||||||
$config = $this->get_config();
|
$config = $this->get_config();
|
||||||
|
|
||||||
$length = Config::get('cache.redis.pool.max', 10);
|
$length = Config::get('cache.redis.pool.max', 10);
|
||||||
|
|
||||||
$this->getEventProvider()->on(OnWorkerExit::class, [$this, 'destroy'], 0);
|
$this->getEventProvider()->on(OnWorkerExit::class, [$this, 'destroy'], 0);
|
||||||
|
|
||||||
$connections->initConnections('Redis:' . $config['host'], true, $length);
|
$this->pool->initConnections($config['host'], $length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $name
|
* @param $name
|
||||||
* @param $arguments
|
* @param $arguments
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws
|
* @throws
|
||||||
*/
|
*/
|
||||||
public function __call($name, $arguments): mixed
|
public function __call($name, $arguments): mixed
|
||||||
{
|
{
|
||||||
$time = microtime(true);
|
$time = microtime(true);
|
||||||
if (method_exists($this, $name)) {
|
if (method_exists($this, $name)) {
|
||||||
$data = $this->{$name}(...$arguments);
|
$data = $this->{$name}(...$arguments);
|
||||||
} else {
|
} else {
|
||||||
$data = $this->proxy($name, $arguments);
|
$data = $this->proxy($name, $arguments);
|
||||||
}
|
}
|
||||||
if (microtime(true) - $time >= 0.02) {
|
if (microtime(true) - $time >= 0.02) {
|
||||||
$this->logger->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
|
$this->logger->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
|
||||||
}
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param int $timeout
|
* @param int $timeout
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function waite($key, int $timeout = 5): bool
|
public function waite($key, int $timeout = 5): bool
|
||||||
{
|
{
|
||||||
$time = time();
|
$time = time();
|
||||||
while (!$this->setNx($key, 1)) {
|
while (!$this->setNx($key, 1)) {
|
||||||
if (time()- $time >= $timeout) {
|
if (time() - $time >= $timeout) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
$this->expire($key, $timeout);
|
$this->expire($key, $timeout);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @param int $timeout
|
* @param int $timeout
|
||||||
* @return bool|int
|
* @return bool|int
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function lock($key, int $timeout = 5): bool|int
|
public function lock($key, int $timeout = 5): bool|int
|
||||||
{
|
{
|
||||||
$script = <<<SCRIPT
|
$script = <<<SCRIPT
|
||||||
local _nx = redis.call('setnx',KEYS[1], ARGV[1])
|
local _nx = redis.call('setnx',KEYS[1], ARGV[1])
|
||||||
if (_nx ~= 0) then
|
if (_nx ~= 0) then
|
||||||
redis.call('expire',KEYS[1], ARGV[1])
|
redis.call('expire',KEYS[1], ARGV[1])
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
return 0
|
return 0
|
||||||
SCRIPT;
|
SCRIPT;
|
||||||
return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
|
return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param $key
|
||||||
* @return int
|
* @return int
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function unlock($key): int
|
public function unlock($key): int
|
||||||
{
|
{
|
||||||
return $this->del('{lock}:' . $key);
|
return $this->del('{lock}:' . $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws ConfigException
|
* @throws ConfigException
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function release()
|
public function release()
|
||||||
{
|
{
|
||||||
$connections = Kiri::getDi()->get(PoolRedis::class);
|
$this->pool->clean($this->get_config()['host']);
|
||||||
$connections->release($this->get_config(), true);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* 销毁连接池
|
||||||
* 销毁连接池
|
* @throws ConfigException
|
||||||
* @throws ConfigException
|
* @throws Exception
|
||||||
* @throws Exception
|
*/
|
||||||
*/
|
public function destroy()
|
||||||
public function destroy()
|
{
|
||||||
{
|
$this->pool->clean($this->get_config()['host']);
|
||||||
$connections = Kiri::getDi()->get(PoolRedis::class);
|
}
|
||||||
$connections->connection_clear($this->get_config(), true);
|
|
||||||
}
|
/**
|
||||||
|
* @param $name
|
||||||
/**
|
* @param $arguments
|
||||||
* @param $name
|
* @return mixed
|
||||||
* @param $arguments
|
* @throws ConfigException
|
||||||
* @return mixed
|
* @throws Exception
|
||||||
* @throws ConfigException
|
*/
|
||||||
* @throws Exception
|
public function proxy($name, $arguments): mixed
|
||||||
*/
|
{
|
||||||
public function proxy($name, $arguments): mixed
|
$client = $this->getClient();
|
||||||
{
|
try {
|
||||||
$connections = Kiri::getDi()->get(PoolRedis::class);
|
$response = $client->{$name}(...$arguments);
|
||||||
|
} catch (\Throwable $throwable) {
|
||||||
$config = $this->get_config();
|
$response = $this->logger->addError($throwable->getMessage());
|
||||||
|
} finally {
|
||||||
$client = $connections->get($config, true);
|
$this->pool->push($this->get_config()['host'], $client);
|
||||||
if (!($client instanceof Base\Redis)) {
|
}
|
||||||
throw new Exception('Redis connections more.');
|
return $response;
|
||||||
}
|
}
|
||||||
$response = $client->{$name}(...$arguments);
|
|
||||||
$this->release();
|
|
||||||
return $response;
|
/**
|
||||||
}
|
* @return Helper
|
||||||
|
* @throws ConfigException
|
||||||
/**
|
*/
|
||||||
* @return array
|
private function getClient(): Helper
|
||||||
* @throws ConfigException
|
{
|
||||||
*/
|
$config = $this->get_config();
|
||||||
public function get_config(): array
|
return $this->pool->get($config['host'], static function () use ($config) {
|
||||||
{
|
return new Helper($config);
|
||||||
return Config::get('cache.redis', null, true);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigException
|
||||||
|
*/
|
||||||
|
public function get_config(): array
|
||||||
|
{
|
||||||
|
return Config::get('cache.redis', null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -12,7 +12,7 @@ namespace Gii;
|
|||||||
use Database\Connection;
|
use Database\Connection;
|
||||||
use Database\Db;
|
use Database\Db;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Kiri\Cache\Redis;
|
use Kiri\Redis\Redis;
|
||||||
use Kiri;
|
use Kiri;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user