This commit is contained in:
as2252258@163.com
2021-02-22 00:56:05 +08:00
parent 8a40bd7130
commit 985157ad8b
5 changed files with 723 additions and 768 deletions
+2 -2
View File
@@ -49,7 +49,7 @@ class Db
$event = Snowflake::app()->getEvent();
$event->trigger(Connection::TRANSACTION_COMMIT);
$event->offName(Connection::TRANSACTION_COMMIT);
Context::deleteId('begin:transaction');
Context::deleteContext('begin:transaction');
}
/**
@@ -63,7 +63,7 @@ class Db
$event = Snowflake::app()->getEvent();
$event->trigger(Connection::TRANSACTION_ROLLBACK);
$event->offName(Connection::TRANSACTION_ROLLBACK);
Context::deleteId('begin:transaction');
Context::deleteContext('begin:transaction');
}
/**
+175 -175
View File
@@ -13,194 +13,194 @@ use Swoole\Coroutine;
class Context extends BaseContext
{
protected static array $_requests = [];
protected static array $_requests = [];
protected static array $_response = [];
protected static array $_response = [];
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
public static function setContext($id, $context, $key = null): mixed
{
if (static::inCoroutine()) {
return self::setCoroutine($id, $context, $key);
} else {
return self::setStatic($id, $context, $key);
}
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
public static function setContext($id, $context, $key = null): mixed
{
if (static::inCoroutine()) {
return self::setCoroutine($id, $context, $key);
} else {
return self::setStatic($id, $context, $key);
}
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
private static function setStatic($id, $context, $key = null): mixed
{
if (!empty($key)) {
if (!is_array(static::$_requests[$id])) {
static::$_requests[$id] = [$key => $context];
} else {
static::$_requests[$id][$key] = $context;
}
} else {
static::$_requests[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
private static function setStatic($id, $context, $key = null): mixed
{
if (!empty($key)) {
if (!is_array(static::$_requests[$id])) {
static::$_requests[$id] = [$key => $context];
} else {
static::$_requests[$id][$key] = $context;
}
} else {
static::$_requests[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
private static function setCoroutine($id, $context, $key = null): mixed
{
if (!static::hasContext($id)) {
Coroutine::getContext()[$id] = [];
}
if (!empty($key)) {
if (!is_array(Coroutine::getContext()[$id])) {
Coroutine::getContext()[$id] = [$key => $context];
} else {
Coroutine::getContext()[$id][$key] = $context;
}
} else {
Coroutine::getContext()[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
private static function setCoroutine($id, $context, $key = null): mixed
{
if (!static::hasContext($id)) {
Coroutine::getContext()[$id] = [];
}
if (!empty($key)) {
if (!is_array(Coroutine::getContext()[$id])) {
Coroutine::getContext()[$id] = [$key => $context];
} else {
Coroutine::getContext()[$id][$key] = $context;
}
} else {
Coroutine::getContext()[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function autoIncr($id, $key = null): mixed
{
if (!static::inCoroutine()) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] += 1;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function autoIncr($id, $key = null): mixed
{
if (!static::inCoroutine()) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] += 1;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function autoDecr($id, $key = null): mixed
{
if (!static::inCoroutine() || !static::hasContext($id)) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] -= 1;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function autoDecr($id, $key = null): mixed
{
if (!static::inCoroutine() || !static::hasContext($id)) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] -= 1;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function getContext($id, $key = null): mixed
{
if (!static::hasContext($id)) {
return null;
}
if (static::inCoroutine()) {
if ($key === null) {
return Coroutine::getContext()[$id];
} else {
return Coroutine::getContext()[$id][$key] ?? null;
}
} else {
if ($key === null) {
return static::$_requests[$id];
} else {
return static::$_requests[$id][$key] ?? null;
}
}
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function getContext($id, $key = null): mixed
{
if (!static::hasContext($id)) {
return null;
}
if (static::inCoroutine()) {
if ($key === null) {
return Coroutine::getContext()[$id];
} else {
return Coroutine::getContext()[$id][$key] ?? null;
}
} else {
if ($key === null) {
return static::$_requests[$id];
} else {
return static::$_requests[$id][$key] ?? null;
}
}
}
/**
* @return mixed
*/
public static function getAllContext(): mixed
{
if (static::inCoroutine()) {
return Coroutine::getContext() ?? [];
} else {
return static::$_requests ?? [];
}
}
/**
* @return mixed
*/
public static function getAllContext(): mixed
{
if (static::inCoroutine()) {
return Coroutine::getContext() ?? [];
} else {
return static::$_requests ?? [];
}
}
/**
* @param string $id
* @param string|null $key
*/
public static function deleteId(string $id, string $key = null)
{
if (!static::hasContext($id, $key)) {
return;
}
if (static::inCoroutine()) {
if (!empty($key)) {
unset(Coroutine::getContext()[$id][$key]);
} else {
unset(Coroutine::getContext()[$id]);
}
} else {
unset(static::$_requests[$id]);
}
}
/**
* @param string $id
* @param string|null $key
*/
public static function deleteContext(string $id, string $key = null)
{
if (!static::hasContext($id, $key)) {
return;
}
if (static::inCoroutine()) {
if (!empty($key)) {
unset(Coroutine::getContext()[$id][$key]);
} else {
unset(Coroutine::getContext()[$id]);
}
} else {
unset(static::$_requests[$id]);
}
}
/**
* @param $id
* @param null $key
* @return bool
*/
public static function hasContext($id, $key = null): bool
{
if (!static::inCoroutine()) {
if (!isset(static::$_requests[$id]) || empty(static::$_requests[$id])) {
return false;
}
if (!empty($key) && !isset(static::$_requests[$id][$key])) {
return false;
}
return true;
}
if (!isset(Coroutine::getContext()[$id])) {
return false;
}
if (Coroutine::getContext()[$id] !== null) {
if ($key === null) {
return true;
}
return isset(Coroutine::getContext()[$id][$key]);
}
return false;
}
/**
* @param $id
* @param null $key
* @return bool
*/
public static function hasContext($id, $key = null): bool
{
if (!static::inCoroutine()) {
if (!isset(static::$_requests[$id]) || empty(static::$_requests[$id])) {
return false;
}
if (!empty($key) && !isset(static::$_requests[$id][$key])) {
return false;
}
return true;
}
if (!isset(Coroutine::getContext()[$id])) {
return false;
}
if (Coroutine::getContext()[$id] !== null) {
if ($key === null) {
return true;
}
return isset(Coroutine::getContext()[$id][$key]);
}
return false;
}
/**
* @return bool
*/
public static function inCoroutine(): bool
{
return Coroutine::getCid() > 0;
}
/**
* @return bool
*/
public static function inCoroutine(): bool
{
return Coroutine::getCid() > 0;
}
}
+168 -173
View File
@@ -22,200 +22,195 @@ use Swoole\Timer;
abstract class Pool extends Component
{
/** @var Channel[] */
private array $_items = [];
/** @var Channel[] */
private array $_items = [];
protected int $max = 60;
protected int $max = 60;
use Timeout;
use Timeout;
/**
* @param $driver
* @param $name
* @param false $isMaster
* @param int $max
*/
public function initConnections($driver, $name, $isMaster = false, $max = 60)
{
$name = $this->name($driver, $name, $isMaster);
if (isset($this->_items[$name]) && $this->_items[$name] instanceof Channel) {
return;
}
if (!Context::inCoroutine()) {
return;
}
$this->_items[$name] = new Channel((int)$max);
$this->max = (int)$max;
}
/**
* @param $driver
* @param $name
* @param false $isMaster
* @param int $max
*/
public function initConnections($driver, $name, $isMaster = false, $max = 60)
{
$name = $this->name($driver, $name, $isMaster);
if (isset($this->_items[$name]) && $this->_items[$name] instanceof Channel) {
return;
}
if (!Context::inCoroutine()) {
return;
}
$this->_items[$name] = new Channel((int)$max);
$this->max = (int)$max;
}
/**
* @param $name
* @return array
* @throws Exception
*/
protected function get($name): array
{
if (!Context::inCoroutine()) {
return [0, null];
}
[$timeout, $connection] = $this->_items[$name]->pop(-1);
if (empty($timeout) || empty($connection)) {
return [0, null];
}
if (!$this->checkCanUse($name, $timeout, $connection)) {
return [0, null];
} else {
return [$timeout, $connection];
}
}
/**
* @param $name
* @return array
* @throws Exception
*/
protected function get($name, array $callback): mixed
{
if (!Context::inCoroutine()) {
return $this->createClient($name, $callback);
}
if (!$this->hasItem($name)) {
if ($this->creates === -1) {
$this->creates = Timer::tick(1000, [$this, 'Heartbeat_detection']);
}
if (!Context::hasContext('create::client::ing::' . $name)) {
$this->push($name, $this->createClient($name, $callback));
Context::deleteContext('create::client::ing::' . $name);
}
}
$connection = $this->_items[$name]->pop(-1);
if (!$this->checkCanUse($name, $connection)) {
return $this->createClient($name, $callback);
} else {
return $connection;
}
}
/**
* @param $driver
* @param $cds
* @param false $isMaster
* @return string
*/
#[Pure] public function name($driver, $cds, $isMaster = false): string
{
if ($isMaster === true) {
return $cds . '_master';
} else {
return $cds . '_slave';
}
}
/**
* @param $cds
* @param $coroutineName
* @param false $isBefore
*/
public function printClients($cds, $coroutineName, $isBefore = false)
{
$this->warning(($isBefore ? 'before ' : '') . 'create client[address: ' . $cds . ', ' . env('workerId') . ', coroutine: ' . Coroutine::getCid() . ', has num: ' . $this->size($coroutineName) . ', has create: ' . $this->_create . ']');
}
/**
* @param $name
* @param $time
* @param $client
* @return mixed
* 检查连接可靠性
* @throws Exception
*/
public function checkCanUse(string $name, int $time, mixed $client): mixed
{
throw new Exception('Undefined system processing function.');
}
/**
* @param $name
* @throws Exception
*/
public function desc(string $name)
{
throw new Exception('Undefined system processing function.');
}
/**
* @param array $config
* @param $isMaster
* @throws Exception
*/
public function getConnection(array $config, bool $isMaster)
{
throw new Exception('Undefined system processing function.');
}
abstract public function createClient(string $name, array $config): mixed;
/**
* @param array $config
* @param string $coroutineName
* @param callable $createHandler
* @throws Exception
*/
public function createConnect(array $config, string $coroutineName, callable $createHandler)
{
if (Context::hasContext('create:connect:' . $coroutineName)) {
return;
}
if ($this->creates === -1) {
$this->creates = Timer::tick(1000, [$this, 'Heartbeat_detection']);
}
Context::setContext('create:connect:' . $coroutineName, 1);
$this->push($coroutineName, call_user_func($createHandler, ...$config));
Context::deleteId('create:connect:' . $coroutineName);
}
/**
* @param $driver
* @param $cds
* @param false $isMaster
* @return string
*/
#[Pure] public function name($driver, $cds, $isMaster = false): string
{
if ($isMaster === true) {
return $cds . '_master';
} else {
return $cds . '_slave';
}
}
/**
* @param $name
* @return bool
*/
public function hasItem(string $name): bool
{
if (isset($this->_items[$name])) {
return !$this->_items[$name]->isEmpty();
}
return false;
}
/**
* @param $name
* @param $time
* @param $client
* @return mixed
* 检查连接可靠性
* @throws Exception
*/
public function checkCanUse(string $name, mixed $client): mixed
{
throw new Exception('Undefined system processing function.');
}
/**
* @param $name
* @throws Exception
*/
public function desc(string $name)
{
throw new Exception('Undefined system processing function.');
}
/**
* @param array $config
* @param $isMaster
* @throws Exception
*/
public function getConnection(array $config, bool $isMaster)
{
throw new Exception('Undefined system processing function.');
}
/**
* @param $name
* @return mixed
*/
public function size(string $name): mixed
{
if (!Context::inCoroutine()) {
return 0;
}
if (!isset($this->_items[$name])) {
return 0;
}
return $this->_items[$name]->length();
}
/**
* @param $name
* @return bool
*/
public function hasItem(string $name): bool
{
if (isset($this->_items[$name])) {
return !$this->_items[$name]->isEmpty();
}
return false;
}
/**
* @param $name
* @param $client
*/
public function push(string $name, mixed $client)
{
if (!Context::inCoroutine()) {
return;
}
if (!$this->_items[$name]->isFull()) {
$this->_items[$name]->push([time(), $client]);
}
}
/**
* @param $name
* @return mixed
*/
public function size(string $name): mixed
{
if (!Context::inCoroutine()) {
return 0;
}
if (!isset($this->_items[$name])) {
return 0;
}
return $this->_items[$name]->length();
}
/**
* @param string $name
* @throws Exception
*/
public function clean(string $name)
{
if (!Context::inCoroutine()) {
return;
}
if (!isset($this->_items[$name])) {
return;
}
$channel = $this->_items[$name];
while ([$time, $client] = $channel->pop(0.001)) {
unset($client);
$this->desc($name);
}
}
/**
* @param $name
* @param $client
*/
public function push(string $name, mixed $client)
{
if (!Context::inCoroutine()) {
return;
}
if (!$this->_items[$name]->isFull()) {
$this->_items[$name]->push($client);
}
}
/**
* @return Channel[]
*/
protected function getChannels(): array
{
return $this->_items;
}
/**
* @param string $name
* @throws Exception
*/
public function clean(string $name)
{
if (!Context::inCoroutine()) {
return;
}
if (!isset($this->_items[$name])) {
return;
}
$channel = $this->_items[$name];
while ($client = $channel->pop(0.001)) {
unset($client);
$this->desc($name);
}
}
/**
* @return Channel[]
*/
protected function getChannels(): array
{
return $this->_items;
}
}
+259 -278
View File
@@ -19,312 +19,293 @@ class Connection extends Pool
{
public array $hasCreate = [];
public array $hasCreate = [];
public int $timeout = 1900;
public int $timeout = 1900;
/** @var PDO[] */
protected array $connections = [];
/** @var PDO[] */
protected array $connections = [];
/**
* @param $timeout
*/
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
/**
* @param $timeout
*/
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/**
* @param $cds
* @return bool
*
* db is in transaction
*/
public function inTransaction($cds): bool
{
return Context::getContext('begin_' . $this->name('mysql', $cds, true)) == 0;
}
/**
* @param $cds
* @return bool
*
* db is in transaction
*/
public function inTransaction($cds): bool
{
return Context::getContext('begin_' . $this->name('mysql', $cds, true)) == 0;
}
/**
* @param $coroutineName
*/
public function beginTransaction($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
Context::setContext('begin_' . $coroutineName, 0);
}
Context::autoIncr('begin_' . $coroutineName);
if (!Context::getContext('begin_' . $coroutineName) !== 0) {
return;
}
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO && !$connection->inTransaction()) {
$connection->beginTransaction();
}
}
/**
* @param $coroutineName
*/
public function beginTransaction($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
Context::setContext('begin_' . $coroutineName, 0);
}
Context::autoIncr('begin_' . $coroutineName);
if (!Context::getContext('begin_' . $coroutineName) !== 0) {
return;
}
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO && !$connection->inTransaction()) {
$connection->beginTransaction();
}
}
/**
* @param $coroutineName
*/
public function commit($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
return;
}
if (Context::autoDecr('begin_' . $coroutineName) > 0) {
return;
}
$connection = Context::getContext($coroutineName);
if (!($connection instanceof PDO)) {
return;
}
Context::setContext('begin_' . $coroutineName, 0);
if ($connection->inTransaction()) {
$connection->commit();
}
}
/**
* @param $coroutineName
*/
public function commit($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
return;
}
if (Context::autoDecr('begin_' . $coroutineName) > 0) {
return;
}
$connection = Context::getContext($coroutineName);
if (!($connection instanceof PDO)) {
return;
}
Context::setContext('begin_' . $coroutineName, 0);
if ($connection->inTransaction()) {
$connection->commit();
}
}
/**
* @param $name
* @param false $isMaster
* @return array
*/
private function getIndex($name, $isMaster = false): array
{
return [Coroutine::getCid(), $this->name('mysql', $name, $isMaster)];
}
/**
* @param $name
* @param false $isMaster
* @return array
*/
private function getIndex($name, $isMaster = false): array
{
return [Coroutine::getCid(), $this->name('mysql', $name, $isMaster)];
}
/**
* @param $coroutineName
*/
public function rollback($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
return;
}
if (Context::autoDecr('begin_' . $coroutineName) > 0) {
return;
}
if (($connection = Context::getContext($coroutineName)) instanceof PDO) {
if ($connection->inTransaction()) {
$connection->rollBack();
}
}
Context::setContext('begin_' . $coroutineName, 0);
}
/**
* @param $coroutineName
*/
public function rollback($coroutineName)
{
$coroutineName = $this->name('mysql', $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) {
return;
}
if (Context::autoDecr('begin_' . $coroutineName) > 0) {
return;
}
if (($connection = Context::getContext($coroutineName)) instanceof PDO) {
if ($connection->inTransaction()) {
$connection->rollBack();
}
}
Context::setContext('begin_' . $coroutineName, 0);
}
/**
* @param array $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function getConnection(array $config, $isMaster = false): mixed
{
$coroutineName = $this->name('mysql', $config['cds'], $isMaster);
if (!isset($this->hasCreate[$coroutineName])) {
$this->hasCreate[$coroutineName] = 0;
}
if (($pdo = Context::getContext($coroutineName)) instanceof PDO) {
return $pdo;
}
if (!$this->hasItem($coroutineName)) {
$this->newClient($config, $coroutineName);
}
[$time, $connections] = $this->get($coroutineName);
if (!($connections instanceof PDO)) {
return $this->getConnection($config, $coroutineName);
}
return Context::setContext($coroutineName, $connections);
}
/**
* @param array $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function getConnection(array $config, $isMaster = false): mixed
{
$coroutineName = $this->name('mysql', $config['cds'], $isMaster);
if (!isset($this->hasCreate[$coroutineName])) {
$this->hasCreate[$coroutineName] = 0;
}
if (($pdo = Context::getContext($coroutineName)) instanceof PDO) {
return $pdo;
}
$connections = $this->get($coroutineName, $config);
if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) {
$number > 0 && $connections->beginTransaction();
}
return Context::setContext($coroutineName, $connections);
}
/**
* @param $config
* @param $coroutineName
* @throws Exception
*/
private function newClient($config, $coroutineName)
{
$this->printClients($config['cds'], $coroutineName, true);
$this->createConnect($this->parseConfig($config, $coroutineName), $coroutineName, function ($cds, $username, $password, $charset, $coroutineName) {
$link = new PDO($cds, $username, $password, [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_TIMEOUT => $this->timeout,
]);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$link->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
$link->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
if (!empty($charset)) {
$link->query('SET NAMES ' . $charset);
}
$this->incr($coroutineName);
if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) {
$number > 0 && $link->beginTransaction();
}
return $link;
});
}
/**
* @param array $config
* @return mixed
*/
public function createClient(string $name, array $config): mixed
{
$this->printClients($config['cds'], $name, true);
// TODO: Implement createClient() method.
$link = new PDO($config['cds'], $config['username'], $config['password'], [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_TIMEOUT => $this->timeout,
]);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$link->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
$link->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
$charset = $config['charset'] ?? 'utf8mb4';
if (!empty($charset)) {
$link->query('SET NAMES ' . $charset);
}
return $link;
}
/**
* @param $config
* @param $name
* @return array
*/
private function parseConfig($config, $name): array
{
return [$config['cds'], $config['username'], $config['password'], $config['charset'] ?? 'utf8mb4', $name];
}
/**
* @param $cds
* @param $coroutineName
* @param false $isBefore
*/
public function printClients($cds, $coroutineName, $isBefore = false)
{
$this->warning(($isBefore ? 'before ' : '') . 'create client[address: ' . $cds . ', ' . env('workerId') . ', coroutine: ' . Coroutine::getCid() . ', has num: ' . $this->size($coroutineName) . ', has create: ' . $this->hasCreate[$coroutineName] . ']');
}
/**
* @param $cds
* @param $coroutineName
* @param false $isBefore
*/
public function printClients($cds, $coroutineName, $isBefore = false)
{
$this->warning(($isBefore ? 'before ' : '') . 'create client[address: ' . $cds . ', ' . env('workerId') . ', coroutine: ' . Coroutine::getCid() . ', has num: ' . $this->size($coroutineName) . ', has create: ' . $this->hasCreate[$coroutineName] . ']');
}
/**
* @param $coroutineName
* @param $isMaster
*/
public function release($coroutineName, $isMaster)
{
$coroutineName = $this->name('mysql', $coroutineName, $isMaster);
if (!$this->hasClient($coroutineName)) {
return;
}
/** @var PDO $client */
$client = Context::getContext($coroutineName);
if ($client->inTransaction()) {
$client->commit();
}
$this->push($coroutineName, $client);
$this->remove($coroutineName);
$this->lastTime = time();
}
/**
* @param $coroutineName
* @param $isMaster
*/
public function release($coroutineName, $isMaster)
{
$coroutineName = $this->name('mysql', $coroutineName, $isMaster);
if (!$this->hasClient($coroutineName)) {
return;
}
/** @var PDO $client */
$client = Context::getContext($coroutineName);
if ($client->inTransaction()) {
$client->commit();
}
$this->push($coroutineName, $client);
$this->remove($coroutineName);
$this->lastTime = time();
}
/**
* @param $coroutineName
* @return bool
*/
private function hasClient($coroutineName): bool
{
return Context::hasContext($coroutineName);
}
/**
* @param $coroutineName
* @return bool
*/
private function hasClient($coroutineName): bool
{
return Context::hasContext($coroutineName);
}
/**
* batch release
*/
public function connection_clear()
{
$connections = Context::getAllContext();
foreach ($connections as $name => $connection) {
if (empty($connection) || !($connection instanceof PDO)) {
continue;
}
/** @var PDO $pdoClient */
if ($connection->inTransaction()) {
$connection->commit();
}
$this->push($name, $connection);
$this->remove($name);
}
$this->hasCreate = [];
$this->creates = 0;
}
/**
* batch release
*/
public function connection_clear()
{
$connections = Context::getAllContext();
foreach ($connections as $name => $connection) {
if (empty($connection) || !($connection instanceof PDO)) {
continue;
}
/** @var PDO $pdoClient */
if ($connection->inTransaction()) {
$connection->commit();
}
$this->push($name, $connection);
$this->remove($name);
}
$this->hasCreate = [];
$this->creates = 0;
}
/**
* @param $coroutineName
*/
public function remove($coroutineName)
{
Context::deleteContext($coroutineName);
}
/**
* @param $name
* @param $client
* @return bool
*/
public function checkCanUse($name, $client): bool
{
try {
if (empty($client) || !($client instanceof PDO)) {
return $result = false;
}
if (!$client->getAttribute(PDO::ATTR_SERVER_INFO)) {
return $result = false;
}
return $result = true;
} catch (\Swoole\Error | \Throwable $exception) {
return $result = false;
} finally {
if (!$result) {
$this->desc($name);
}
}
}
/**
* @param $coroutineName
*/
public function remove($coroutineName)
{
Context::deleteId($coroutineName);
}
/**
* @param $coroutineName
* @throws Exception
*/
public function disconnect($coroutineName)
{
if (!$this->hasClient($coroutineName)) {
return;
}
$this->remove($coroutineName);
$this->clean($coroutineName);
}
/**
* @param $name
* @param $time
* @param $client
* @return bool
*/
public function checkCanUse($name, $time, $client): bool
{
try {
if (empty($client) || !($client instanceof PDO)) {
return $result = false;
}
if (!$client->getAttribute(PDO::ATTR_SERVER_INFO)) {
return $result = false;
}
return $result = true;
} catch (\Swoole\Error | \Throwable $exception) {
return $result = false;
} finally {
if (!$result) {
$this->desc($name);
}
}
}
/**
* @param $coroutineName
*/
public function incr($coroutineName)
{
if (!isset($this->hasCreate[$coroutineName])) {
$this->hasCreate[$coroutineName] = 0;
}
$this->hasCreate[$coroutineName] += 1;
}
/**
* @param $coroutineName
* @throws Exception
*/
public function disconnect($coroutineName)
{
if (!$this->hasClient($coroutineName)) {
return;
}
$this->remove($coroutineName);
$this->clean($coroutineName);
}
/**
* @param $coroutineName
*/
public function incr($coroutineName)
{
if (!isset($this->hasCreate[$coroutineName])) {
$this->hasCreate[$coroutineName] = 0;
}
$this->hasCreate[$coroutineName] += 1;
}
/**
* @param string $name
*/
public function desc(string $name)
{
if (!isset($this->hasCreate[$name])) {
$this->hasCreate[$name] = 0;
}
$this->hasCreate[$name] -= 1;
}
/**
* @param string $name
*/
public function desc(string $name)
{
if (!isset($this->hasCreate[$name])) {
$this->hasCreate[$name] = 0;
}
$this->hasCreate[$name] -= 1;
}
}
+119 -140
View File
@@ -21,161 +21,140 @@ class Redis extends Pool
{
private int $_create = 0;
private int $_create = 0;
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/**
* @param array $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function getConnection(array $config, $isMaster = false): mixed
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (($redis = Context::getContext($coroutineName)) instanceof \Redis) {
return $redis;
}
if (!$this->hasItem($coroutineName)) {
$this->newClient($config, $coroutineName);
}
[$time, $clients] = $this->get($coroutineName);
if ($clients === null) {
return $this->getConnection($config, $coroutineName);
}
return Context::setContext($coroutineName, $clients);
}
/**
* @param array $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function getConnection(array $config, $isMaster = false): mixed
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (($redis = Context::getContext($coroutineName)) instanceof \Redis) {
return $redis;
}
return Context::setContext($coroutineName, $this->get($coroutineName, $config));
}
/**
* @param $config
* @param $coroutineName
* @throws Exception
*/
private function newClient($config, $coroutineName)
{
$this->printClients($config['host'], $coroutineName, true);
$this->createConnect([$config, $coroutineName], $coroutineName, function ($config, $coroutineName) {
$redis = new SRedis();
if (!$redis->connect($config['host'], (int)$config['port'], $config['timeout'])) {
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $config['host'], $config['port']));
}
if (empty($config['auth']) || !$redis->auth($config['auth'])) {
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $config['host'], $config['auth']));
}
if (!isset($config['read_timeout'])) {
$config['read_timeout'] = 10;
}
$redis->select($config['databases']);
$redis->setOption(SRedis::OPT_READ_TIMEOUT, $config['read_timeout']);
$redis->setOption(SRedis::OPT_PREFIX, $config['prefix']);
/**
* @param array $config
* @return SRedis
* @throws RedisConnectException
*/
public function createClient(string $name, array $config): mixed
{
$this->printClients($config['host'], $name, true);
$redis = new SRedis();
if (!$redis->connect($config['host'], (int)$config['port'], $config['timeout'])) {
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $config['host'], $config['port']));
}
if (empty($config['auth']) || !$redis->auth($config['auth'])) {
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $config['host'], $config['auth']));
}
if (!isset($config['read_timeout'])) {
$config['read_timeout'] = 10;
}
$redis->select($config['databases']);
$redis->setOption(SRedis::OPT_READ_TIMEOUT, $config['read_timeout']);
$redis->setOption(SRedis::OPT_PREFIX, $config['prefix']);
$this->_create += 1;
$this->_create += 1;
return $redis;
});
}
return $redis;
}
/**
* @param $cds
* @param $coroutineName
* @param false $isBefore
*/
public function printClients($cds, $coroutineName, $isBefore = false)
{
$this->warning(($isBefore ? 'before ' : '') . 'create client[address: ' . $cds . ', ' . env('workerId') . ', coroutine: ' . Coroutine::getCid() . ', has num: ' . $this->size($coroutineName) . ', has create: ' . $this->_create . ']');
}
/**
* @param array $config
* @param bool $isMaster
*/
public function release(array $config, $isMaster = false)
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
$this->push($coroutineName, Context::getContext($coroutineName));
$this->remove($coroutineName);
$this->lastTime = time();
}
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function destroy(array $config, $isMaster = false)
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
/**
* @param array $config
* @param bool $isMaster
*/
public function release(array $config, $isMaster = false)
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
$this->push($coroutineName, Context::getContext($coroutineName));
$this->remove($coroutineName);
$this->lastTime = time();
}
$this->desc($coroutineName);
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function destroy(array $config, $isMaster = false)
{
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
$this->remove($coroutineName);
$this->clean($coroutineName);
}
$this->desc($coroutineName);
/**
* @param $coroutineName
*/
public function remove(string $coroutineName)
{
Context::deleteContext($coroutineName);
}
$this->remove($coroutineName);
$this->clean($coroutineName);
}
/**
* @param $name
* @param $time
* @param $client
* @return bool
* @throws Exception
*/
public function checkCanUse(string $name, mixed $client): bool
{
try {
if (!($client instanceof SRedis)) {
$result = false;
} else if (!$client->isConnected() || !$client->ping('connect.')) {
$result = false;
} else {
$result = true;
}
} catch (\Throwable $exception) {
$this->error($exception);
$result = false;
} finally {
if (!$result) {
$this->desc($name);
}
return $result;
}
}
/**
* @param $coroutineName
*/
public function remove(string $coroutineName)
{
Context::deleteId($coroutineName);
}
/**
* @param $name
* @param $time
* @param $client
* @return bool
* @throws Exception
*/
public function checkCanUse(string $name, int $time, mixed $client): bool
{
try {
if (!($client instanceof SRedis)) {
$result = false;
} else if (!$client->isConnected() || !$client->ping('connect.')) {
$result = false;
} else {
$result = true;
}
} catch (\Throwable $exception) {
$this->error($exception);
$result = false;
} finally {
if (!$result) {
$this->desc($name);
}
return $result;
}
}
/**
* @param string $name
*/
public function desc(string $name)
{
$this->_create -= 1;
}
/**
* @param string $name
*/
public function desc(string $name)
{
$this->_create -= 1;
}
}