Merge branch 'master' of https://gitee.com/dreamwithouttrace/snowflake into v1.0
This commit is contained in:
+9
-104
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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] ?? '数据库异常, 请稍后再试.');
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user