This commit is contained in:
as2252258@163.com
2021-05-02 13:52:28 +08:00
11 changed files with 803 additions and 907 deletions
+9 -104
View File
@@ -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]);
}
}
}
}
}
}
+355 -363
View File
@@ -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;
}
}
+3 -2
View File
@@ -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]);
-8
View File
@@ -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] ?? '数据库异常, 请稍后再试.');
}
+17 -4
View File
@@ -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
+206 -212
View File
@@ -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;
}
}
+5 -1
View File
@@ -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);
}
-4
View File
@@ -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 {
+8 -13
View File
@@ -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();
}
+3
View File
@@ -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);
}
+197 -196
View File
@@ -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);
}
}