diff --git a/Annotation/Loader.php b/Annotation/Loader.php index 6224f36e..1049785d 100644 --- a/Annotation/Loader.php +++ b/Annotation/Loader.php @@ -235,10 +235,7 @@ class Loader extends BaseObject $path = '/' . trim($path, '/'); foreach ($this->_directory as $key => $_path) { $key = '/' . trim($key, '/'); - if (!str_starts_with($key, $path)) { - continue; - } - if (in_array($key, $outPath)) { + if (!str_starts_with($key, $path) || in_array($key, $outPath)) { continue; } $this->execute($_path); @@ -279,98 +276,6 @@ class Loader extends BaseObject $array = '/' . trim(implode('/', $array), '/'); $this->_directory[$array][] = $className; - -// $directory = $this->splitDirectory($filePath); -// array_pop($directory); -// -// $tree = null; -// foreach ($directory as $value) { -// $tree = $this->getTree($tree, $value); -// } -// -// if ($tree instanceof FileTree) { -// $tree->addFile($className, $filePath); -// } - } - - - /** - * @param string $filePath - * @param string|null $outPath - * @return $this - * @throws Exception - */ - private function each(string $filePath, ?string $outPath): static - { - $tree = null; - $directory = $this->splitDirectory($filePath); - - $_tmp = ''; - if (!empty($outPath)) { - $outPath = rtrim($outPath, '/'); - } - - foreach ($directory as $key => $value) { - $_tmp .= DIRECTORY_SEPARATOR . $value; - if (!empty($outPath) && str_contains($_tmp, $outPath)) { - break; - } - $tree = $this->getTree($tree, $value); - } - if ($tree instanceof FileTree) { - $this->eachNode($tree->getChildes(), $outPath); - $this->execute($tree->getFiles()); - } - return $this; - } - - - /** - * @param string $filePath - * @return false|string[] - */ - private function splitDirectory(string $filePath): array|bool - { - $DIRECTORY = explode(DIRECTORY_SEPARATOR, $filePath); - return array_filter($DIRECTORY, function ($value) { - return !empty($value); - }); - } - - - /** - * @param $tree - * @param $value - * @return FileTree - */ - private function getTree($tree, $value): FileTree - { - if ($tree === null) { - $tree = $this->files->getChild($value); - } else { - $tree = $tree->getChild($value); - } - return $tree; - } - - - /** - * @param FileTree[] $nodes - * @param string|null $outPath - * @throws Exception - */ - private function eachNode(array $nodes, ?string $outPath = '') - { - foreach ($nodes as $node) { - $this->execute($node->getFiles()); - if (!empty($outPath) && str_contains($node->getDirPath(), $outPath)) { - continue; - } - $childes = $node->getChildes(); - if (!empty($childes)) { - $this->eachNode($childes, $outPath); - } - } } @@ -395,31 +300,31 @@ class Loader extends BaseObject if (empty($classes)) { return; } - $annotation = Snowflake::app()->getAnnotation(); + $annotation = Snowflake::getAnnotation(); foreach ($classes as $className) { $annotations = $this->_classes[$className] ?? null; if ($annotations === null) { continue; } + $class = clone $annotations['handler']; foreach ($annotations['target'] ?? [] as $value) { - $value->execute([$annotations['handler']]); + $value->execute([$class]); } - - $_className = $annotations['handler']::class; foreach ($annotations['methods'] as $name => $attribute) { foreach ($attribute as $value) { if ($value instanceof Relation) { - $annotation->addRelate($_className, $value->name, $name); + $annotation->addRelate($class::class, $value->name, $name); } else if ($value instanceof Get) { - $annotation->addGets($_className, $value->name, $name); + $annotation->addGets($class::class, $value->name, $name); } else if ($value instanceof Set) { - $annotation->addSets($_className, $value->name, $name); + $annotation->addSets($class::class, $value->name, $name); } else { - $value->execute([$annotations['handler'], $name]); + $value->execute([$class, $name]); } } } } } + } diff --git a/Database/ActiveRecord.php b/Database/ActiveRecord.php index c1d79098..43237297 100644 --- a/Database/ActiveRecord.php +++ b/Database/ActiveRecord.php @@ -32,418 +32,410 @@ defined('FIND_OR_CREATE_MESSAGE') or define('FIND_OR_CREATE_MESSAGE', 'Create a class ActiveRecord extends BaseActiveRecord { - const DECR = 'decr'; - const INCR = 'incr'; + const DECR = 'decr'; + const INCR = 'incr'; - /** - * @return array - */ - public function rules(): array - { - return []; - } + /** + * @return array + */ + public function rules(): array + { + return []; + } - /** - * @param string $column - * @param int $value - * @return ActiveRecord|false - * @throws Exception - */ - public function increment(string $column, int $value): bool|ActiveRecord - { - if (!$this->mathematics([$column => $value], '+')) { - return false; - } - $this->{$column} += $value; - return $this->refresh(); - } + /** + * @param string $column + * @param int $value + * @return ActiveRecord|false + * @throws Exception + */ + public function increment(string $column, int $value): bool|ActiveRecord + { + if (!$this->mathematics([$column => $value], '+')) { + return false; + } + $this->{$column} += $value; + return $this->refresh(); + } - /** - * @param string $column - * @param int $value - * @return ActiveRecord|false - * @throws Exception - */ - public function decrement(string $column, int $value): bool|ActiveRecord - { - if (!$this->mathematics([$column => $value], '-')) { - return false; - } - $this->{$column} -= $value; - return $this->refresh(); - } + /** + * @param string $column + * @param int $value + * @return ActiveRecord|false + * @throws Exception + */ + public function decrement(string $column, int $value): bool|ActiveRecord + { + if (!$this->mathematics([$column => $value], '-')) { + return false; + } + $this->{$column} -= $value; + return $this->refresh(); + } - /** - * @param array $columns - * @return ActiveRecord|false - * @throws Exception - */ - public function increments(array $columns): bool|static - { - if (!$this->mathematics($columns, '+')) { - return false; - } - foreach ($columns as $key => $attribute) { - $this->$key += $attribute; - } - return $this; - } + /** + * @param array $columns + * @return ActiveRecord|false + * @throws Exception + */ + public function increments(array $columns): bool|static + { + if (!$this->mathematics($columns, '+')) { + return false; + } + foreach ($columns as $key => $attribute) { + $this->$key += $attribute; + } + return $this; + } - /** - * @param array $columns - * @return ActiveRecord|false - * @throws Exception - */ - public function decrements(array $columns): bool|static - { - if (!$this->mathematics($columns, '-')) { - return false; - } - foreach ($columns as $key => $attribute) { - $this->$key -= $attribute; - } - return $this; - } + /** + * @param array $columns + * @return ActiveRecord|false + * @throws Exception + */ + public function decrements(array $columns): bool|static + { + if (!$this->mathematics($columns, '-')) { + return false; + } + foreach ($columns as $key => $attribute) { + $this->$key -= $attribute; + } + return $this; + } - /** - * @param array $condition - * @param array $attributes - * @return bool|ActiveRecord - * @throws ReflectionException - * @throws NotFindClassException - * @throws Exception - */ - public static function findOrCreate(array $condition, array $attributes = []): bool|static - { - $logger = Snowflake::app()->getLogger(); + /** + * @param array $condition + * @param array $attributes + * @return bool|ActiveRecord + * @throws ReflectionException + * @throws NotFindClassException + * @throws Exception + */ + public static function findOrCreate(array $condition, array $attributes = []): bool|static + { + $logger = Snowflake::app()->getLogger(); - /** @var static $select */ - $select = static::find()->where($condition)->first(); - if (!empty($select)) { - return $select; - } - if (empty($attributes)) { - return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); - } - $select = self::getModelClass(); - $select->attributes = $attributes; - if (!$select->save()) { - return $logger->addError($select->getLastError(), 'mysql'); - } - return $select; - } + /** @var static $select */ + $select = static::find()->where($condition)->first(); + if (!empty($select)) { + return $select; + } + if (empty($attributes)) { + return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); + } + $select = self::getModelClass(); + $select->attributes = $attributes; + if (!$select->save()) { + return $logger->addError($select->getLastError(), 'mysql'); + } + return $select; + } - /** - * @param array $condition - * @param array $attributes - * @return bool|static - * @throws Exception - */ - public static function createOrUpdate(array $condition, array $attributes = []): bool|static - { - $logger = Snowflake::app()->getLogger(); - if (empty($attributes)) { - return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); - } - /** @var static $select */ - $select = static::find()->where($condition)->first(); - if (empty($select)) { - $select = self::getModelClass(); - } - $select->attributes = $attributes; - if (!$select->save()) { - return $logger->addError($select->getLastError(), 'mysql'); - } - return $select; - } + /** + * @param array $condition + * @param array $attributes + * @return bool|static + * @throws Exception + */ + public static function createOrUpdate(array $condition, array $attributes = []): bool|static + { + $logger = Snowflake::app()->getLogger(); + if (empty($attributes)) { + return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); + } + /** @var static $select */ + $select = static::find()->where($condition)->first(); + if (empty($select)) { + $select = self::getModelClass(); + } + $select->attributes = $attributes; + if (!$select->save()) { + return $logger->addError($select->getLastError(), 'mysql'); + } + return $select; + } - /** - * @return static - * @throws Exception - */ - private static function getModelClass(): static - { - /** @var Channel $channel */ - $channel = Snowflake::app()->get('channel'); - return $channel->pop(static::class, function () { - return new static(); - }); - } + /** + * @return static + * @throws Exception + */ + private static function getModelClass(): static + { + /** @var Channel $channel */ + $channel = Snowflake::app()->get('channel'); + return $channel->pop(static::class, function () { + return new static(); + }); + } - /** - * @param $action - * @param $columns - * @param array $condition - * @return array|bool|int|string|null - * @throws Exception - */ - private function mathematics($columns, $action, $condition = []): int|bool|array|string|null - { - if (empty($condition)) { - $condition = [$this->getPrimary() => $this->getPrimaryValue()]; - } + /** + * @param $action + * @param $columns + * @param array $condition + * @return array|bool|int|string|null + * @throws Exception + */ + private function mathematics($columns, $action, $condition = []): int|bool|array|string|null + { + if (empty($condition)) { + $condition = [$this->getPrimary() => $this->getPrimaryValue()]; + } - $activeQuery = static::find()->where($condition); - $create = SqlBuilder::builder($activeQuery)->mathematics($columns, $action); - if (is_bool($create)) { - return false; - } - return static::getDb()->createCommand($create[0], $create[1])->exec(); - } + $activeQuery = static::find()->where($condition); + $create = SqlBuilder::builder($activeQuery)->mathematics($columns, $action); + if (is_bool($create)) { + return false; + } + return static::getDb()->createCommand($create[0], $create[1])->exec(); + } - /** - * @param array $fields - * @return ActiveRecord|bool - * @throws Exception - */ - public function update(array $fields): static|bool - { - return $this->save($fields); - } + /** + * @param array $fields + * @return ActiveRecord|bool + * @throws Exception + */ + public function update(array $fields): static|bool + { + return $this->save($fields); + } - /** - * @param array $data - * @return bool - * @throws Exception - */ - public static function inserts(array $data): bool - { - /** @var static $class */ - $class = Snowflake::createObject(['class' => static::class]); - if (empty($data)) { - return $class->addError('Insert data empty.', 'mysql'); - } - return $class::find()->batchInsert($data); - } + /** + * @param array $data + * @return bool + * @throws Exception + */ + public static function inserts(array $data): bool + { + /** @var static $class */ + $class = Snowflake::createObject(['class' => static::class]); + if (empty($data)) { + return $class->addError('Insert data empty.', 'mysql'); + } + return $class::find()->batchInsert($data); + } - /** - * @return bool - * @throws Exception - */ - public function delete(): bool - { - $conditions = $this->_oldAttributes; - if (empty($conditions)) { - return $this->addError("Delete condition do not empty.", 'mysql'); - } - $primary = $this->getPrimary(); + /** + * @return bool + * @throws Exception + */ + public function delete(): bool + { + $conditions = $this->_oldAttributes; + if (empty($conditions)) { + return $this->addError("Delete condition do not empty.", 'mysql'); + } + $primary = $this->getPrimary(); - if (!empty($primary)) { - $conditions = [$primary => $this->getAttribute($primary)]; - } - return static::deleteByCondition($conditions); - } + if (!empty($primary)) { + $conditions = [$primary => $this->getAttribute($primary)]; + } + return static::deleteByCondition($conditions); + } - /** - * @param $condition - * @param array $attributes - * - * @return bool - * @throws Exception - */ - public static function updateAll(mixed $condition, $attributes = []): bool - { - $condition = static::find()->where($condition); - return $condition->batchUpdate($attributes); - } + /** + * @param $condition + * @param array $attributes + * + * @return bool + * @throws Exception + */ + public static function updateAll(mixed $condition, $attributes = []): bool + { + $condition = static::find()->where($condition); + return $condition->batchUpdate($attributes); + } - /** - * @param $condition - * @param array $attributes - * - * @return array|Collection - * @throws Exception - */ - public static function findAll($condition, $attributes = []): array|Collection - { - $query = static::find()->where($condition); - if (!empty($attributes)) { - $query->bindParams($attributes); - } - return $query->all(); - } + /** + * @param $condition + * @param array $attributes + * + * @return array|Collection + * @throws Exception + */ + public static function findAll($condition, $attributes = []): array|Collection + { + $query = static::find()->where($condition); + if (!empty($attributes)) { + $query->bindParams($attributes); + } + return $query->all(); + } - /** - * @param $method - * @return mixed - * @throws Exception - */ - private function resolveObject($method): mixed - { - $resolve = $this->{$this->getRelate($method)}(); - if ($resolve instanceof HasBase) { - $resolve = $resolve->get(); - } - if ($resolve instanceof Collection) { - return $resolve->toArray(); - } else if ($resolve instanceof ActiveRecord) { - return $resolve->toArray(); - } else if (is_object($resolve)) { - return get_object_vars($resolve); - } else { - return $resolve; - } - } + /** + * @param $method + * @return mixed + * @throws Exception + */ + private function resolveObject($method): mixed + { + $resolve = $this->{$this->getRelate($method)}(); + if ($resolve instanceof HasBase) { + $resolve = $resolve->get(); + } + if ($resolve instanceof Collection) { + return $resolve->toArray(); + } else if ($resolve instanceof ActiveRecord) { + return $resolve->toArray(); + } else if (is_object($resolve)) { + return get_object_vars($resolve); + } else { + return $resolve; + } + } - /** - * @return array - * @throws Exception - */ - public function toArray(): array - { - $data = $this->_attributes; + /** + * @return array + * @throws Exception + */ + public function toArray(): array + { + $data = $this->_attributes; - $lists = Snowflake::getAnnotation()->getGets(static::class); - foreach ($lists as $key => $item) { - $data[$key] = $this->{$item}($data[$key] ?? null); - } - $data = array_merge($data, $this->runRelate()); + $lists = Snowflake::getAnnotation()->getGets(static::class); + foreach ($lists as $key => $item) { + $data[$key] = $this->{$item}($data[$key] ?? null); + } + $data = array_merge($data, $this->runRelate()); - $class = Snowflake::app()->getChannel(); - $class->push($this, static::class); + $class = Snowflake::app()->getChannel(); + $class->push($this, static::class); - return $data; - } + return $data; + } - /** - * @return array - * @throws Exception - */ - private function runRelate(): array - { - $relates = []; - if (empty($with = $this->getWith())) { - return $relates; - } - foreach ($with as $val) { - $relates[$val] = $this->resolveObject($val); - } - return $relates; - } + /** + * @return array + * @throws Exception + */ + private function runRelate(): array + { + $relates = []; + if (empty($with = $this->getWith())) { + return $relates; + } + foreach ($with as $val) { + $relates[$val] = $this->resolveObject($val); + } + return $relates; + } - /** - * @param string $modelName - * @param $foreignKey - * @param $localKey - * @return HasOne|ActiveQuery - * @throws Exception - */ - public function hasOne(string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery - { - if (!$this->has($localKey)) { - throw new Exception("Need join table primary key."); - } + /** + * @param string $modelName + * @param $foreignKey + * @param $localKey + * @return HasOne|ActiveQuery + * @throws Exception + */ + public function hasOne(string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery + { + if (($value = $this->getAttribute($localKey)) === null) { + throw new Exception("Need join table primary key."); + } - $value = $this->getAttribute($localKey); + $relation = $this->getRelation(); - $relation = $this->getRelation(); - - return new HasOne($modelName, $foreignKey, $value, $relation); - } + return new HasOne($modelName, $foreignKey, $value, $relation); + } - /** - * @param $modelName - * @param $foreignKey - * @param $localKey - * @return ActiveQuery - * @throws Exception - */ - public function hasCount($modelName, $foreignKey, $localKey): mixed - { - if (!$this->has($localKey)) { - throw new Exception("Need join table primary key."); - } + /** + * @param $modelName + * @param $foreignKey + * @param $localKey + * @return ActiveQuery + * @throws Exception + */ + public function hasCount($modelName, $foreignKey, $localKey): mixed + { + if (($value = $this->getAttribute($localKey)) === null) { + throw new Exception("Need join table primary key."); + } - $value = $this->getAttribute($localKey); + $relation = $this->getRelation(); - $relation = $this->getRelation(); - - return new HasCount($modelName, $foreignKey, $value, $relation); - } + return new HasCount($modelName, $foreignKey, $value, $relation); + } - /** - * @param $modelName - * @param $foreignKey - * @param $localKey - * @return ActiveQuery - * @throws Exception - */ - public function hasMany($modelName, $foreignKey, $localKey): mixed - { - if (!$this->has($localKey)) { - throw new Exception("Need join table primary key."); - } + /** + * @param $modelName + * @param $foreignKey + * @param $localKey + * @return ActiveQuery + * @throws Exception + */ + public function hasMany($modelName, $foreignKey, $localKey): mixed + { + if (($value = $this->getAttribute($localKey)) === null) { + throw new Exception("Need join table primary key."); + } - $value = $this->getAttribute($localKey); + $relation = $this->getRelation(); - $relation = $this->getRelation(); + return new HasMany($modelName, $foreignKey, $value, $relation); + } - return new HasMany($modelName, $foreignKey, $value, $relation); - } + /** + * @param $modelName + * @param $foreignKey + * @param $localKey + * @return ActiveQuery + * @throws Exception + */ + public function hasIn($modelName, $foreignKey, $localKey): mixed + { + if (($value = $this->getAttribute($localKey)) === null) { + throw new Exception("Need join table primary key."); + } - /** - * @param $modelName - * @param $foreignKey - * @param $localKey - * @return ActiveQuery - * @throws Exception - */ - public function hasIn($modelName, $foreignKey, $localKey): mixed - { - if (!$this->has($localKey)) { - throw new Exception("Need join table primary key."); - } + $relation = $this->getRelation(); - $value = $this->getAttribute($localKey); + return new HasMany($modelName, $foreignKey, $value, $relation); + } - $relation = $this->getRelation(); + /** + * @return bool + * @throws Exception + */ + public function afterDelete(): bool + { + if (!$this->hasPrimary()) { + return TRUE; + } + $value = $this->getPrimaryValue(); + if (empty($value)) { + return TRUE; + } + return TRUE; + } - return new HasMany($modelName, $foreignKey, $value, $relation); - } - - /** - * @return bool - * @throws Exception - */ - public function afterDelete(): bool - { - if (!$this->hasPrimary()) { - return TRUE; - } - $value = $this->getPrimaryValue(); - if (empty($value)) { - return TRUE; - } - return TRUE; - } - - /** - * @return bool - * @throws Exception - */ - public function beforeDelete(): bool - { - if (!$this->hasPrimary()) { - return TRUE; - } - $value = $this->getPrimaryValue(); - if (empty($value)) { - return TRUE; - } - return TRUE; - } + /** + * @return bool + * @throws Exception + */ + public function beforeDelete(): bool + { + if (!$this->hasPrimary()) { + return TRUE; + } + $value = $this->getPrimaryValue(); + if (empty($value)) { + return TRUE; + } + return TRUE; + } } diff --git a/Database/Base/BaseActiveRecord.php b/Database/Base/BaseActiveRecord.php index 4715f4fe..de233768 100644 --- a/Database/Base/BaseActiveRecord.php +++ b/Database/Base/BaseActiveRecord.php @@ -968,7 +968,7 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess */ public function offsetExists(mixed $offset): bool { - return $this->has($offset); + return isset($this->_attributes[$offset]) || isset($this->_oldAttributes[$offset]); } /** @@ -997,7 +997,8 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess */ public function offsetUnset(mixed $offset) { - if (!$this->has($offset)) { + if (!isset($this->_attributes[$offset]) + && !isset($this->_oldAttributes[$offset])) { return; } unset($this->_attributes[$offset]); diff --git a/Database/Command.php b/Database/Command.php index f400a11f..2eaef4ee 100644 --- a/Database/Command.php +++ b/Database/Command.php @@ -121,15 +121,11 @@ class Command extends Component private function execute($type, $isInsert = null, $hasAutoIncrement = null): int|bool|array|string|null { try { - $time = microtime(true); if ($type === static::EXECUTE) { $result = $this->insert_or_change($isInsert, $hasAutoIncrement); } else { $result = $this->search($type); } - if (microtime(true) - $time >= 0.03) { - $this->warning('execute sql Worker.' . env('worker') . '.' . Coroutine::getCid() . '`' . $this->sql . '` use time ' . (microtime(true) - $time)); - } return $result; } catch (\Throwable $exception) { return $this->addError($this->sql . '. error: ' . $exception->getMessage(), 'mysql'); @@ -144,11 +140,7 @@ class Command extends Component */ private function search($type): mixed { - $time = microtime(true); $connect = $this->db->getConnect($this->sql); - if (microtime(true) - $time > 0.02) { - $this->error('get connect time:' . $this->sql . '; ' . (microtime(true) - $time)); - } if (!($query = $connect?->query($this->sql))) { return $this->addError($connect->errorInfo()[2] ?? '数据库异常, 请稍后再试.'); } diff --git a/HttpServer/Events/OnWorkerStart.php b/HttpServer/Events/OnWorkerStart.php index 8c47ad1a..7e992c3e 100644 --- a/HttpServer/Events/OnWorkerStart.php +++ b/HttpServer/Events/OnWorkerStart.php @@ -9,6 +9,7 @@ use HttpServer\Abstracts\Callback; use Snowflake\Event; use Snowflake\Exception\ConfigException; use Snowflake\Snowflake; +use Swoole\Coroutine; use Swoole\Coroutine\System; use Swoole\Server; @@ -32,10 +33,7 @@ class OnWorkerStart extends Callback putenv('state=start'); putenv('worker=' . $worker_id); - $content = System::readFile(storage('runtime.php')); - - $annotation = Snowflake::app()->getAnnotation(); - $annotation->setLoader(unserialize($content)); + $annotation = $this->settings(); if ($worker_id < $server->setting['worker_num']) { $this->onWorker($server, $annotation); } else { @@ -44,6 +42,21 @@ class OnWorkerStart extends Callback } + /** + * @return \Annotation\Annotation + * @throws \Exception + */ + private function settings(): Annotation + { + $content = System::readFile(storage('runtime.php')); + + $annotation = Snowflake::app()->getAnnotation(); + $annotation->setLoader(unserialize($content)); + + return $annotation; + } + + /** * @param Server $server * @param int $worker_id diff --git a/HttpServer/Http/Context.php b/HttpServer/Http/Context.php index 32b2014d..839162d5 100644 --- a/HttpServer/Http/Context.php +++ b/HttpServer/Http/Context.php @@ -13,239 +13,233 @@ use Swoole\Coroutine; class Context extends BaseContext { - protected static array $_contents = []; + protected static array $_contents = []; + /** + * @param $id + * @param $context + * @param null $key + * @return mixed + */ + public static function setContext($id, $context, $key = null): mixed + { + if (!static::inCoroutine()) { + return static::setStatic($id, $context, $key); + } + return self::setCoroutine($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 array + */ + private static function setStatic($id, $context, $key = null): mixed + { + if (empty($key)) { + return static::$_contents[$id] = $context; + } + if (!is_array(static::$_contents[$id])) { + static::$_contents[$id] = [$key => $context]; + } else { + static::$_contents[$id][$key] = $context; + } + return $context; + } - /** - * @param $id - * @param $context - * @param null $key - * @return array - */ - private static function setStatic($id, $context, $key = null): mixed - { - if (empty($key)) { - return static::$_contents[$id] = $context; - } - if (!is_array(static::$_contents[$id])) { - static::$_contents[$id] = [$key => $context]; - } else { - static::$_contents[$id][$key] = $context; - } - return $context; - } + /** + * @param $id + * @param $context + * @param null $key + * @return mixed + */ + private static function setCoroutine($id, $context, $key = null): mixed + { + if (empty($key)) { + return Coroutine::getContext()[$id] = $context; + } + if (!is_array(Coroutine::getContext()[$id])) { + Coroutine::getContext()[$id] = [$key => $context]; + } else { + Coroutine::getContext()[$id][$key] = $context; + } + return $context; + } - /** - * @param $id - * @param $context - * @param null $key - * @return mixed - */ - private static function setCoroutine($id, $context, $key = null): mixed - { - if (empty($key)) { - return Coroutine::getContext()[$id] = $context; - } - if (!is_array(Coroutine::getContext()[$id])) { - Coroutine::getContext()[$id] = [$key => $context]; - } else { - Coroutine::getContext()[$id][$key] = $context; - } - return $context; - } + /** + * @param $id + * @param null $key + * @param int $value + * @return bool|int + */ + public static function increment($id, $key = null, $value = 1): bool|int + { + if (!isset(Coroutine::getContext()[$id][$key])) { + return false; + } + return Coroutine::getContext()[$id][$key] += $value; + } - /** - * @param $id - * @param null $key - * @param int $value - * @return bool|int - */ - public static function increment($id, $key = null, $value = 1): bool|int - { - if (!static::inCoroutine()) { - return false; - } - if (!isset(Coroutine::getContext()[$id][$key])) { - return false; - } - return Coroutine::getContext()[$id][$key] += $value; - } + /** + * @param $id + * @param null $key + * @param int $value + * @return bool|int + */ + public static function decrement($id, $key = null, $value = 1): bool|int + { + if (!static::hasContext($id)) { + return false; + } + if (!isset(Coroutine::getContext()[$id][$key])) { + return false; + } + return Coroutine::getContext()[$id][$key] -= $value; + } - /** - * @param $id - * @param null $key - * @param int $value - * @return bool|int - */ - public static function decrement($id, $key = null, $value = 1): bool|int - { - if (!static::inCoroutine() || !static::hasContext($id)) { - return false; - } - if (!isset(Coroutine::getContext()[$id][$key])) { - return false; - } - return Coroutine::getContext()[$id][$key] -= $value; - } - - /** - * @param $id - * @param null $key - * @return mixed - */ - public static function getContext($id, $key = null): mixed - { - if (!static::hasContext($id)) { - return null; - } - if (static::inCoroutine()) { - return static::loadByContext($id, $key); - } else { - return static::loadByStatic($id, $key); - } - } + /** + * @param $id + * @param null $key + * @return mixed + */ + public static function getContext($id, $key = null): mixed + { + if (!static::inCoroutine()) { + return static::loadByStatic($id, $key); + } + return static::loadByContext($id, $key); + } - /** - * @param $id - * @param null $key - * @return mixed - */ - private static function loadByContext($id, $key = null): mixed - { - $data = Coroutine::getContext()[$id] ?? null; - if ($data === null) { - return null; - } - if ($key !== null) { - return $data[$key] ?? null; - } - return $data; - } + /** + * @param $id + * @param null $key + * @return mixed + */ + private static function loadByContext($id, $key = null): mixed + { + $data = Coroutine::getContext()[$id] ?? null; + if ($data === null) { + return null; + } + if ($key !== null) { + return $data[$key] ?? null; + } + return $data; + } - /** - * @param $id - * @param null $key - * @return mixed - */ - private static function loadByStatic($id, $key = null): mixed - { - $data = static::$_contents[$id] ?? null; - if ($data === null) { - return null; - } - if ($key !== null) { - return $data[$key] ?? null; - } - return $data; - } + /** + * @param $id + * @param null $key + * @return mixed + */ + private static function loadByStatic($id, $key = null): mixed + { + $data = static::$_contents[$id] ?? null; + if ($data === null) { + return null; + } + if ($key !== null) { + return $data[$key] ?? null; + } + return $data; + } - /** - * @return mixed - */ - public static function getAllContext(): mixed - { - if (static::inCoroutine()) { - return Coroutine::getContext() ?? []; - } else { - return static::$_contents ?? []; - } - } + /** + * @return mixed + */ + public static function getAllContext(): mixed + { + if (static::inCoroutine()) { + return Coroutine::getContext() ?? []; + } else { + return static::$_contents ?? []; + } + } - /** - * @param string $id - * @param string|null $key - */ - public static function remove(string $id, string $key = null) - { - if (!static::hasContext($id, $key)) { - return; - } - if (static::inCoroutine()) { - unset(static::$_contents[$id]); - return; - } - if (!empty($key)) { - unset(Coroutine::getContext()[$id][$key]); - } else { - unset(Coroutine::getContext()[$id]); - } - } + /** + * @param string $id + * @param string|null $key + */ + public static function remove(string $id, string $key = null) + { + if (!static::hasContext($id, $key)) { + return; + } + if (!static::inCoroutine()) { + if (!empty($key)) { + unset(static::$_contents[$id][$key]); + } else { + unset(static::$_contents[$id]); + } + } else { + if (!empty($key)) { + unset(Coroutine::getContext()[$id][$key]); + } else { + unset(Coroutine::getContext()[$id]); + } + } + } - /** - * @param $id - * @param null $key - * @return bool - */ - public static function hasContext($id, $key = null): bool - { - if (!static::inCoroutine()) { - return static::searchByStatic($id, $key); - } else { - return static::searchByCoroutine($id, $key); - } - } + /** + * @param $id + * @param null $key + * @return bool + */ + public static function hasContext($id, $key = null): bool + { + if (!static::inCoroutine()) { + return static::searchByStatic($id, $key); + } + return static::searchByCoroutine($id, $key); + } - /** - * @param $id - * @param null $key - * @return bool - */ - private static function searchByStatic($id, $key = null): bool - { - if (!isset(static::$_contents[$id])) { - return false; - } - if (!empty($key) && !isset(static::$_contents[$id][$key])) { - return false; - } - return true; - } + /** + * @param $id + * @param null $key + * @return bool + */ + private static function searchByStatic($id, $key = null): bool + { + if (!isset(static::$_contents[$id])) { + return false; + } + if (!empty($key) && !isset(static::$_contents[$id][$key])) { + return false; + } + return true; + } - /** - * @param $id - * @param null $key - * @return bool - */ - private static function searchByCoroutine($id, $key = null): bool - { - if (!isset(Coroutine::getContext()[$id])) { - return false; - } - if ($key !== null) { - return isset((Coroutine::getContext()[$id] ?? [])[$key]); - } - return true; - } + /** + * @param $id + * @param null $key + * @return bool + */ + private static function searchByCoroutine($id, $key = null): bool + { + if (!isset(Coroutine::getContext()[$id])) { + return false; + } + if ($key !== null) { + return isset((Coroutine::getContext()[$id] ?? [])[$key]); + } + return true; + } - /** - * @return bool - */ - public static function inCoroutine(): bool - { - return Coroutine::getCid() > 0; - } + /** + * @return bool + */ + public static function inCoroutine(): bool + { + return Coroutine::getCid() !== -1; + } } diff --git a/HttpServer/Server.php b/HttpServer/Server.php index 0a19bb7d..db90cb5a 100644 --- a/HttpServer/Server.php +++ b/HttpServer/Server.php @@ -115,7 +115,11 @@ class Server extends HttpService Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_BLOCKING_FUNCTION); - Coroutine::set(['enable_deadlock_check' => false]); + $settings['enable_deadlock_check'] = false; + $settings['exit_condition'] = function () { + return Coroutine::stats()['coroutine_num'] === 0; + }; + Coroutine::set($settings); return $this->execute($baseServer); } diff --git a/System/Abstracts/Pool.php b/System/Abstracts/Pool.php index 249d218a..e5d2caa1 100644 --- a/System/Abstracts/Pool.php +++ b/System/Abstracts/Pool.php @@ -174,11 +174,7 @@ abstract class Pool extends Component if ($this->_items[$name]->isEmpty()) { $this->createByCallback($name, $callback); } - $time = microtime(true); $connection = $this->_items[$name]->pop(0.002); - if (($end = microtime(true) - $time) >= 0.01) { - $this->error('waite channel connect use time.' . $end); - } if (!$this->checkCanUse($name, $connection)) { return $this->createClient($name, $callback); } else { diff --git a/System/Channel.php b/System/Channel.php index 8e3c764f..bda439ab 100644 --- a/System/Channel.php +++ b/System/Channel.php @@ -29,6 +29,9 @@ class Channel extends Component public function push(mixed $value, string $name = ''): void { $channel = $this->channelInit($name); + if ($channel->count() >= 100) { + return; + } $channel->enqueue($value); } @@ -71,21 +74,13 @@ class Channel extends Component * @return mixed * @throws Exception */ - public function pop(string $name, Closure $closure, int|float $timeout = null): mixed + public function pop(string $name, Closure $closure): mixed { - if (($channel = $this->channelInit($name)) == false) { - return $this->addError('Channel is full.'); + $channel = $this->channelInit($name); + if ($channel->isEmpty()) { + return call_user_func($closure); } - if (!$channel->isEmpty()) { - return $channel->shift(); - } - if ($timeout !== null) { - $data = $channel->dequeue(); - } - if (empty($data)) { - $data = call_user_func($closure); - } - return $data; + return $channel->dequeue(); } diff --git a/System/Jwt/Jwt.php b/System/Jwt/Jwt.php index 435940ea..5b3589eb 100644 --- a/System/Jwt/Jwt.php +++ b/System/Jwt/Jwt.php @@ -467,6 +467,9 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY= if (!empty($source)) { $this->data['source'] = $source; } + if (!isset($this->data['token'])) { + return; + } $key = $this->authKey($this->getSource(), $this->data['token']); $this->getRedis()->expire($key, $this->timeout); } diff --git a/System/Pool/Connection.php b/System/Pool/Connection.php index 4103c7e7..ac207990 100644 --- a/System/Pool/Connection.php +++ b/System/Pool/Connection.php @@ -19,225 +19,226 @@ class Connection extends Pool { - public int $timeout = 1900; + public int $timeout = 1900; - /** - * @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::increment('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::increment('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::decrement('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::decrement('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::decrement('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::decrement('begin_' . $coroutineName) > 0) { + return; + } + if (($connection = Context::getContext($coroutineName)) instanceof PDO) { + if ($connection->inTransaction()) { + $connection->rollBack(); + } + } + Context::setContext('begin_' . $coroutineName, 0); + } - /** - * @param mixed $config - * @param bool $isMaster - * @return mixed - * @throws Exception - */ - public function get(mixed $config, $isMaster = false): mixed - { - $coroutineName = $this->name('mysql', $config['cds'], $isMaster); - if (($pdo = Context::getContext($coroutineName)) instanceof PDO) { - return $pdo; - } - $connections = $this->getFromChannel($coroutineName, $config); - if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) { - $number > 0 && $connections->beginTransaction(); - } - return Context::setContext($coroutineName, $connections); - } + /** + * @param mixed $config + * @param bool $isMaster + * @return mixed + * @throws Exception + */ + public function get(mixed $config, $isMaster = false): mixed + { + $coroutineName = $this->name('mysql', $config['cds'], $isMaster); + if (($pdo = Context::getContext($coroutineName)) instanceof PDO) { + return $pdo; + } + $connections = $this->getFromChannel($coroutineName, $config); + if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) { + $number > 0 && $connections->beginTransaction(); + } + return Context::setContext($coroutineName, $connections); + } - /** - * @param string $name - * @param mixed $config - * @return PDO - * @throws Exception - */ - public function createClient(string $name, mixed $config): PDO - { - $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, - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . ($config['charset'] ?? 'utf8mb4') - ]); - $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); - return $link; - } + /** + * @param string $name + * @param mixed $config + * @return PDO + * @throws Exception + */ + public function createClient(string $name, mixed $config): PDO + { + $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, + PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . ($config['charset'] ?? 'utf8mb4') + ]); + $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); + return $link; + } - /** - * @param $coroutineName - * @param $isMaster - * @throws Exception - */ - public function release($coroutineName, $isMaster) - { - $coroutineName = $this->name('mysql', $coroutineName, $isMaster); + /** + * @param $coroutineName + * @param $isMaster + * @throws Exception + */ + public function release($coroutineName, $isMaster) + { + $coroutineName = $this->name('mysql', $coroutineName, $isMaster); - /** @var PDO $client */ - if (!($client = Context::getContext($coroutineName)) instanceof PDO) { - return; - } - if ($client->inTransaction()) { - $client->commit(); - } - $this->push($coroutineName, $client); - $this->lastTime = time(); - } + /** @var PDO $client */ + if (!($client = Context::getContext($coroutineName)) instanceof PDO) { + return; + } + if ($client->inTransaction()) { + $client->commit(); + } + $this->push($coroutineName, $client); + $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 - * @throws Exception - */ - public function connection_clear() - { - $this->flush(0); - } + /** + * batch release + * @throws Exception + */ + public function connection_clear() + { + $this->flush(0); + } - /** - * @param string $name - * @param mixed $client - * @return bool - * @throws Exception - */ - public function checkCanUse(string $name, mixed $client): bool - { - try { - if (empty($client) || !($client instanceof PDO)) { - $result = false; - } else { - $result = true; - } - } catch (Error | Throwable $exception) { - $result = $this->addError($exception, 'mysql'); - } finally { - if (!$result) { - $this->decrement($name); - } - return $result; - } - } + /** + * @param string $name + * @param mixed $client + * @return bool + * @throws Exception + */ + public function checkCanUse(string $name, mixed $client): bool + { + try { + if (empty($client) || !($client instanceof PDO)) { + $result = false; + } else { + $result = true; + } + } catch (Error | Throwable $exception) { + $result = $this->addError($exception, 'mysql'); + } finally { + if (!$result) { + $this->decrement($name); + } + return $result; + } + } - /** - * @param $coroutineName - * @param bool $isMaster - * @throws Exception - */ - public function disconnect($coroutineName, $isMaster = false) - { - $coroutineName = $this->name($coroutineName, $isMaster); - $this->clean($coroutineName); - } + /** + * @param $coroutineName + * @param bool $isMaster + * @throws Exception + */ + public function disconnect($coroutineName, $isMaster = false) + { + $coroutineName = $this->name($coroutineName, $isMaster); + $this->clean($coroutineName); + } }