Compare commits

..

175 Commits

Author SHA1 Message Date
as2252258 c37c11a768 改名 2021-07-06 18:30:04 +08:00
as2252258 51a2f448fd 改名 2021-07-06 18:07:41 +08:00
as2252258 eb6aaf3509 改名 2021-07-06 18:00:37 +08:00
as2252258 12766a3b74 改名 2021-07-06 18:00:01 +08:00
as2252258 ec00c2d104 改名 2021-07-06 17:58:53 +08:00
as2252258 40a2331626 改名 2021-07-06 17:57:03 +08:00
as2252258 d528e4d603 改名 2021-07-06 17:45:26 +08:00
as2252258 39865db17a 改名 2021-07-06 17:36:26 +08:00
as2252258 04434f72d4 改名 2021-07-06 17:21:21 +08:00
as2252258 f95f576a52 改名 2021-07-06 17:18:25 +08:00
as2252258 7fde689244 改名 2021-07-06 17:11:59 +08:00
as2252258 b083984efd 改名 2021-07-06 16:54:16 +08:00
as2252258 f83538b687 改名 2021-07-06 16:31:51 +08:00
as2252258 d0c579455d 改名 2021-07-06 16:30:17 +08:00
as2252258 5aae1f0ba4 改名 2021-07-06 16:29:35 +08:00
as2252258 ca874beaaf 改名 2021-07-06 16:27:28 +08:00
as2252258 15e8d7a5a7 改名 2021-07-06 16:25:13 +08:00
as2252258 2959115a23 改名 2021-07-06 16:15:27 +08:00
as2252258 b661581baf 改名 2021-07-06 15:41:22 +08:00
as2252258 ab8a7d7fff 改名 2021-07-06 15:38:57 +08:00
as2252258 31a5053bed 改名 2021-07-05 17:02:40 +08:00
as2252258 be9c469a0f 改名 2021-07-05 16:57:00 +08:00
as2252258 3c3ba68aba 改名 2021-07-05 16:55:43 +08:00
as2252258 4d2b462676 改名 2021-07-05 16:52:53 +08:00
as2252258 c075662c59 改名 2021-07-05 16:34:55 +08:00
as2252258 35ce80c19b 改名 2021-07-05 16:33:32 +08:00
as2252258 3345ff697b 改名 2021-07-05 16:31:35 +08:00
as2252258 2ea7289c43 改名 2021-07-05 16:29:23 +08:00
as2252258 3e53f8d3c2 改名 2021-07-05 16:20:00 +08:00
as2252258 af3b482c1f 改名 2021-07-05 16:18:02 +08:00
as2252258 cf8b25d7db 改名 2021-07-05 16:15:45 +08:00
as2252258 0ba9fc0ce7 改名 2021-07-05 16:12:07 +08:00
as2252258 a03c28d7e5 改名 2021-07-05 16:10:13 +08:00
as2252258 ab32584cf2 改名 2021-07-05 16:07:58 +08:00
as2252258 423d406f3e 改名 2021-07-05 16:00:25 +08:00
as2252258 c545686b8f 改名 2021-07-05 15:57:44 +08:00
as2252258 7246d88e44 改名 2021-07-05 15:57:21 +08:00
as2252258 1aef68902b 改名 2021-07-05 15:55:53 +08:00
as2252258 41ee154c90 改名 2021-07-05 15:55:26 +08:00
as2252258 37b745b659 改名 2021-07-05 15:51:39 +08:00
as2252258 88cdf3a547 改名 2021-07-05 15:50:01 +08:00
as2252258 1a012150ce 改名 2021-07-05 15:49:37 +08:00
as2252258 74bcdf257e 改名 2021-07-05 15:42:44 +08:00
as2252258 d3fd4385e6 改名 2021-07-05 11:58:57 +08:00
as2252258 e94b3ca1d9 改名 2021-07-05 11:31:14 +08:00
as2252258 2ca845a65c 改名 2021-07-05 11:23:57 +08:00
as2252258 ee23b78872 改名 2021-07-05 11:14:03 +08:00
as2252258 bccf0e2a1e 改名 2021-07-05 11:08:18 +08:00
as2252258 d98392b6af 改名 2021-07-05 11:07:18 +08:00
as2252258 c17e829f75 改名 2021-07-05 11:06:39 +08:00
as2252258 216bc1d894 改名 2021-07-05 11:05:19 +08:00
as2252258 77b457b620 改名 2021-07-05 11:04:40 +08:00
as2252258 6cdf8052e6 改名 2021-07-05 11:03:34 +08:00
as2252258 9ea0b9d34b 改名 2021-07-05 11:00:09 +08:00
as2252258 f91194b5c8 改名 2021-07-05 10:52:26 +08:00
as2252258 a671719896 改名 2021-07-05 10:37:29 +08:00
as2252258@163.com 6612040b3a modify 2021-07-03 21:12:21 +08:00
as2252258@163.com 4c2068482a modify 2021-07-03 21:10:13 +08:00
as2252258@163.com d762d392e8 modify 2021-07-03 16:53:53 +08:00
as2252258@163.com 3399c31e70 modify 2021-07-03 16:42:01 +08:00
as2252258@163.com 5e8676b844 modify 2021-07-03 16:39:50 +08:00
as2252258@163.com 9b9a6233dc modify 2021-07-03 16:38:45 +08:00
as2252258@163.com a233ff72ab modify 2021-07-03 16:34:10 +08:00
as2252258@163.com 8999b7ad3f modify 2021-07-03 16:24:22 +08:00
as2252258@163.com 36db8aa4a8 modify 2021-07-03 16:22:50 +08:00
as2252258@163.com d47e1309a9 modify 2021-07-03 16:20:37 +08:00
as2252258@163.com a77d138898 modify 2021-07-03 16:20:01 +08:00
as2252258@163.com 0466268ac8 modify 2021-07-03 16:18:20 +08:00
as2252258@163.com 2c37c5c494 modify 2021-07-03 16:17:37 +08:00
as2252258@163.com 42db5c83dc modify 2021-07-03 16:16:45 +08:00
as2252258@163.com c439e9949c modify 2021-07-03 16:16:02 +08:00
as2252258@163.com d0f3469997 modify 2021-07-03 16:14:57 +08:00
as2252258@163.com 1fad90e1e7 modify 2021-07-03 15:57:56 +08:00
as2252258@163.com 968be07fbb modify 2021-07-03 14:23:15 +08:00
as2252258@163.com f0fe2c1c11 modify 2021-07-03 14:20:01 +08:00
as2252258@163.com b66b2867ab modify 2021-07-03 14:19:10 +08:00
as2252258@163.com 956a68bbff modify 2021-07-03 14:17:06 +08:00
as2252258@163.com bcf865ff34 modify 2021-07-03 14:16:01 +08:00
as2252258@163.com de475736ba modify 2021-07-03 14:14:46 +08:00
as2252258@163.com 7a39375657 modify 2021-07-03 14:08:12 +08:00
as2252258@163.com 8e700e4086 modify 2021-07-03 13:43:17 +08:00
as2252258@163.com 19bd6882d1 modify 2021-07-03 13:41:45 +08:00
as2252258@163.com 40f315f4d9 modify 2021-07-03 13:40:40 +08:00
as2252258@163.com 632d96a197 modify 2021-07-03 13:39:51 +08:00
as2252258@163.com 2e32dea501 modify 2021-07-03 13:39:32 +08:00
as2252258@163.com 4df34aac0b modify 2021-07-03 13:39:10 +08:00
as2252258@163.com 3dff8272ea modify 2021-07-03 13:39:01 +08:00
as2252258@163.com 5c3a197b52 modify 2021-07-03 13:38:36 +08:00
as2252258@163.com 8ebfb295ab modify 2021-07-03 13:37:26 +08:00
as2252258@163.com 49892feff4 modify 2021-07-03 13:31:33 +08:00
as2252258@163.com 7fcf535617 modify 2021-07-03 13:31:07 +08:00
as2252258@163.com ccc9f9bbf1 modify 2021-07-03 13:30:37 +08:00
as2252258@163.com e2e43959a8 modify 2021-07-03 13:25:29 +08:00
as2252258@163.com 382a6ff1b5 modify 2021-07-03 13:24:14 +08:00
as2252258@163.com 9feebc2b73 modify 2021-07-03 13:13:08 +08:00
as2252258@163.com 3f9a7b98e8 modify 2021-07-03 13:12:21 +08:00
as2252258@163.com 1f9116c9c0 modify 2021-07-03 13:08:35 +08:00
as2252258@163.com c0f9506dc6 modify 2021-07-03 13:07:43 +08:00
as2252258@163.com 65ff89e3ed modify 2021-07-03 13:06:45 +08:00
as2252258@163.com 058beb2c26 modify 2021-07-03 13:06:18 +08:00
as2252258@163.com 2036d4ebd9 modify 2021-07-03 13:05:17 +08:00
as2252258@163.com 1f7403b8c0 Merge branch 'v1.0' 2021-07-03 13:01:49 +08:00
as2252258@163.com d7b84a804d modify 2021-07-03 12:57:06 +08:00
as2252258@163.com 4096050303 modify 2021-07-03 12:51:36 +08:00
as2252258@163.com b23cf6187c modify 2021-07-02 21:20:35 +08:00
as2252258 6f0e423773 改名 2021-07-02 15:14:10 +08:00
as2252258 f8a28967d5 改名 2021-06-30 11:40:15 +08:00
as2252258 a3f02701ca 改名 2021-06-29 14:40:12 +08:00
as2252258 2e6ca9b4fa 改名 2021-06-29 14:36:45 +08:00
as2252258 c3d8a92b33 改名 2021-06-29 14:26:31 +08:00
as2252258 ba9086b56b 改名 2021-06-29 14:09:45 +08:00
as2252258 d34eb2bf53 改名 2021-06-29 14:09:11 +08:00
as2252258 c4c6d9a58e 改名 2021-06-29 14:00:47 +08:00
as2252258 ee255c02f9 改名 2021-06-29 12:01:06 +08:00
as2252258 e4c65484fe 改名 2021-06-29 10:57:39 +08:00
as2252258 a70e080153 改名 2021-06-28 16:05:35 +08:00
as2252258 b5bd2d12f8 改名 2021-06-28 14:58:21 +08:00
as2252258 c4cf051139 改名 2021-06-28 14:56:16 +08:00
as2252258@163.com 2f17c40444 modify 2021-06-26 02:48:11 +08:00
as2252258 84d120de92 改名 2021-06-25 11:28:34 +08:00
as2252258 89e7f2d7bc 改名 2021-06-25 11:27:25 +08:00
as2252258 0db42d3a38 改名 2021-06-25 11:26:23 +08:00
as2252258 aa72ac2eb9 改名 2021-06-25 11:20:38 +08:00
as2252258 fbe83aff27 改名 2021-06-24 18:12:45 +08:00
as2252258 7e7652795d 改名 2021-06-09 15:41:13 +08:00
as2252258 15da06a63d 改名 2021-06-09 15:40:23 +08:00
as2252258 db65cb46c2 改名 2021-06-09 15:37:23 +08:00
as2252258 f3f29c1342 改名 2021-06-08 16:09:25 +08:00
as2252258 0436076614 改名 2021-06-08 14:03:26 +08:00
as2252258 53cbc714ed 改名 2021-06-08 13:55:41 +08:00
as2252258 5e9df58276 改名 2021-06-08 13:50:05 +08:00
as2252258 b76c262397 改名 2021-06-08 13:48:30 +08:00
as2252258 e31a66686f 改名 2021-06-08 13:47:14 +08:00
as2252258 a8244921ae 改名 2021-06-08 12:05:00 +08:00
as2252258 164ce98990 改名 2021-06-08 11:58:13 +08:00
as2252258 7e25c361bf 改名 2021-06-08 11:56:40 +08:00
as2252258 557d0fd583 改名 2021-06-08 11:55:19 +08:00
as2252258 9b7e6e1396 改名 2021-06-08 11:54:48 +08:00
as2252258 56df262e56 改名 2021-06-08 11:52:55 +08:00
as2252258 6d49e73ec2 改名 2021-06-08 11:50:54 +08:00
as2252258 f7fb56fc06 改名 2021-06-08 11:50:05 +08:00
as2252258 add59693c1 改名 2021-06-08 11:45:18 +08:00
as2252258 84071fecde 改名 2021-06-08 11:44:38 +08:00
as2252258 4e5787b20d 改名 2021-06-08 11:41:01 +08:00
as2252258 52823100af 改名 2021-06-08 11:40:24 +08:00
as2252258 2b9d09f835 改名 2021-06-08 11:39:27 +08:00
as2252258 e576af2071 改名 2021-06-08 11:38:55 +08:00
as2252258 07c2b3f6cf 改名 2021-06-08 11:38:18 +08:00
as2252258 aed5e9469d 改名 2021-06-08 11:37:17 +08:00
as2252258 9da5d5a332 改名 2021-06-08 11:34:55 +08:00
as2252258 1c48f27e4a 改名 2021-06-07 12:05:39 +08:00
as2252258 760192d63a 改名 2021-06-07 12:05:03 +08:00
as2252258 c786999fe1 改名 2021-06-07 12:03:37 +08:00
as2252258 cd133a8ec7 改名 2021-06-07 12:02:58 +08:00
as2252258 d40d3cc282 改名 2021-06-07 12:02:15 +08:00
as2252258 33508652ad 改名 2021-06-07 12:01:44 +08:00
as2252258 8286e27407 改名 2021-06-07 11:56:55 +08:00
as2252258 188f53d3b0 改名 2021-06-07 11:55:06 +08:00
as2252258 d353e019df 改名 2021-06-07 11:49:24 +08:00
as2252258 e0b3954909 改名 2021-06-07 11:43:01 +08:00
as2252258 b6ac2c75ee 改名 2021-06-04 18:49:31 +08:00
as2252258 558008ad08 改名 2021-06-04 18:33:42 +08:00
as2252258 10805c1022 改名 2021-06-04 18:30:47 +08:00
as2252258 3d9266dc16 改名 2021-06-04 18:22:57 +08:00
as2252258 b80b2c18db 改名 2021-06-04 18:21:48 +08:00
as2252258 a7630df003 改名 2021-06-04 18:20:04 +08:00
as2252258 2cea45051b 改名 2021-06-04 18:16:06 +08:00
as2252258 da703055b3 改名 2021-06-04 18:14:51 +08:00
as2252258 78bc474f2b Merge branch 'master' of https://gitee.com/dreamwithouttrace/snowflake into v1.0 2021-06-04 18:12:19 +08:00
as2252258 1622986699 改名 2021-06-04 18:11:58 +08:00
as2252258 0935f54f06 Merge branch 'master' of https://gitee.com/dreamwithouttrace/snowflake into v1.0 2021-06-03 14:10:37 +08:00
as2252258 894feb3506 改名 2021-06-03 13:57:29 +08:00
as2252258 04ef4473cc 改名 2021-05-28 18:23:58 +08:00
as2252258 ed4051171c Merge branch 'master' of https://gitee.com/dreamwithouttrace/snowflake into v1.0 2021-05-25 15:01:59 +08:00
as2252258 6fb5bb1d41 改名 2021-05-20 18:43:44 +08:00
45 changed files with 4882 additions and 4534 deletions
+3 -10
View File
@@ -7,10 +7,6 @@ namespace Annotation\Route;
use Annotation\Attribute; use Annotation\Attribute;
use Exception; use Exception;
use HttpServer\Route\Router; use HttpServer\Route\Router;
use ReflectionException;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
/** /**
@@ -30,17 +26,14 @@ use Snowflake\Snowflake;
* @param string|null $uri * @param string|null $uri
* @param string $version * @param string $version
*/ */
public function __construct( public function __construct(public string $event, public ?string $uri = null, public string $version = 'v.1.0')
public string $event,
public ?string $uri = null,
public string $version = 'v.1.0'
)
{ {
} }
/** /**
* @param array $handler * @param mixed $class
* @param mixed|null $method
* @return Router * @return Router
* @throws Exception * @throws Exception
*/ */
+1 -1
View File
@@ -132,7 +132,7 @@ class ActiveQuery extends Component implements ISqlBuilder
*/ */
public function execute($sql, $params = []): Command public function execute($sql, $params = []): Command
{ {
return $this->modelClass::getDb()->createCommand($sql, $params); return $this->modelClass::getDb()->createCommand($sql, $this->modelClass::getDbName(), $params);
} }
+2 -1
View File
@@ -15,6 +15,7 @@ use Database\Traits\HasBase;
use Exception; use Exception;
use ReflectionException; use ReflectionException;
use Snowflake\Channel; use Snowflake\Channel;
use Snowflake\Event;
use Snowflake\Exception\NotFindClassException; use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
@@ -195,7 +196,7 @@ class ActiveRecord extends BaseActiveRecord
if (is_bool($create)) { if (is_bool($create)) {
return false; return false;
} }
return static::getDb()->createCommand($create[0], $create[1])->exec(); return static::getDb()->createCommand($create[0], static::getDbName(), $create[1])->exec();
} }
+30 -10
View File
@@ -26,8 +26,10 @@ use Exception;
use HttpServer\Http\Context; use HttpServer\Http\Context;
use ReflectionException; use ReflectionException;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config;
use Snowflake\Abstracts\TraitApplication; use Snowflake\Abstracts\TraitApplication;
use Snowflake\Event as SEvent; use Snowflake\Event as SEvent;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException; use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
use validator\Validator; use validator\Validator;
@@ -433,7 +435,7 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
// $trance = $dbConnection->beginTransaction(); // $trance = $dbConnection->beginTransaction();
try { try {
if (!($lastId = (int)$dbConnection->createCommand($sql, $param)->save(true, $this))) { if (!($lastId = (int)$dbConnection->createCommand($sql, static::getDbName(), $param)->save(true, $this))) {
throw new Exception('保存失败.'); throw new Exception('保存失败.');
} }
// $trance->commit(); // $trance->commit();
@@ -499,7 +501,7 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
} }
// $trance = $command->beginTransaction(); // $trance = $command->beginTransaction();
if (!$command->createCommand(...$generate)->save(false, $this)) { if (!$command->createCommand($generate[0], static::getDbName(), $generate[1])->save(false, $this)) {
// $trance->rollback(); // $trance->rollback();
return false; return false;
} }
@@ -733,16 +735,16 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
} }
if (str_starts_with($table, $tablePrefix)) { if (str_starts_with($table, $tablePrefix)) {
return $table; return '`' . static::getDbName() . '`.' . $table;
} else if (!str_starts_with($table, '{{%')) { } else if (!str_starts_with($table, '{{%')) {
return $table; return '`' . static::getDbName() . '`.' . $table;
} }
$table = trim($table, '{{%}}'); $table = trim($table, '{{%}}');
if ($tablePrefix) { if ($tablePrefix) {
$table = $tablePrefix . $table; $table = $tablePrefix . $table;
} }
return $table; return '`' . static::getDbName() . '`.' . $table;
} }
@@ -769,6 +771,10 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
return true; return true;
} }
private static string $ab_name = '';
/** /**
* @return Connection * @return Connection
* @throws Exception * @throws Exception
@@ -1032,9 +1038,22 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
*/ */
public static function setDatabaseConnect($dbName): Connection public static function setDatabaseConnect($dbName): Connection
{ {
static::$ab_name = $dbName;
return Snowflake::app()->db->get($dbName); return Snowflake::app()->db->get($dbName);
} }
/**
* @return string
* @throws ConfigException
*/
public static function getDbName(): string
{
return Config::get('databases.connections.' . static::$ab_name . '.database');
}
/** /**
* @return Columns * @return Columns
* @throws Exception * @throws Exception
@@ -1053,11 +1072,12 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess
*/ */
public static function populate(array $data): static public static function populate(array $data): static
{ {
$class = Snowflake::app()->getChannel(); // $class = Snowflake::app()->getChannel();
/** @var static $model */ // /** @var static $model */
$model = $class->pop(static::class, function () { // $model = $class->pop(static::class, function () {
return new static(); // return new static();
}); // });
$model = new static();
$model->_attributes = $data; $model->_attributes = $data;
$model->_oldAttributes = $data; $model->_oldAttributes = $data;
$model->setIsCreate(false); $model->setIsCreate(false);
+12 -8
View File
@@ -14,7 +14,7 @@ use Exception;
use PDO; use PDO;
use PDOStatement; use PDOStatement;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Swoole\Coroutine; use Snowflake\Core\Json;
/** /**
* Class Command * Class Command
@@ -56,11 +56,11 @@ class Command extends Component
/** /**
* @param bool $isInsert * @param bool $isInsert
* @param bool $hasAutoIncrement * @param mixed $hasAutoIncrement
* @return int|bool|array|string|null * @return int|bool|array|string|null
* @throws Exception * @throws Exception
*/ */
public function save($isInsert = TRUE, $hasAutoIncrement = null): int|bool|array|string|null public function save(bool $isInsert = TRUE, mixed $hasAutoIncrement = null): int|bool|array|string|null
{ {
return $this->execute(static::EXECUTE, $isInsert, $hasAutoIncrement); return $this->execute(static::EXECUTE, $isInsert, $hasAutoIncrement);
} }
@@ -114,18 +114,22 @@ class Command extends Component
/** /**
* @param $type * @param $type
* @param null $isInsert * @param null $isInsert
* @param bool $hasAutoIncrement * @param bool|null $hasAutoIncrement
* @return int|bool|array|string|null * @return int|bool|array|string|null
* @throws Exception * @throws Exception
*/ */
private function execute($type, $isInsert = null, $hasAutoIncrement = null): int|bool|array|string|null private function execute($type, $isInsert = null, mixed $hasAutoIncrement = null): int|bool|array|string|null
{ {
try { try {
$time = microtime(true);
if ($type === static::EXECUTE) { if ($type === static::EXECUTE) {
$result = $this->insert_or_change($isInsert, $hasAutoIncrement); $result = $this->insert_or_change($isInsert, $hasAutoIncrement);
} else { } else {
$result = $this->search($type); $result = $this->search($type);
} }
if (microtime(true) - $time >= 0.02) {
$this->warning('Mysql:' . Json::encode([$this->sql, $this->params]) . (microtime(true) - $time));
}
if ($this->prepare) { if ($this->prepare) {
$this->prepare->closeCursor(); $this->prepare->closeCursor();
} }
@@ -206,7 +210,7 @@ class Command extends Component
* @param $prepare * @param $prepare
* @return string * @return string
*/ */
private function errorMessage($prepare) private function errorMessage($prepare): string
{ {
return $this->sql . ':' . ($prepare->errorInfo()[2] ?? static::DB_ERROR_MESSAGE); return $this->sql . ':' . ($prepare->errorInfo()[2] ?? static::DB_ERROR_MESSAGE);
} }
@@ -235,7 +239,7 @@ class Command extends Component
* @return bool|int * @return bool|int
* @throws \Exception * @throws \Exception
*/ */
private function checkResponse($prepare, $connect) private function checkResponse($prepare, $connect): bool|int
{ {
$result = $prepare->execute($this->params); $result = $prepare->execute($this->params);
if ($result === false) { if ($result === false) {
@@ -278,7 +282,7 @@ class Command extends Component
* @return int|bool|array|string|null * @return int|bool|array|string|null
* @throws Exception * @throws Exception
*/ */
public function exec($scope = null, $insert = false): int|bool|array|string|null public function exec($scope = null, bool $insert = false): int|bool|array|string|null
{ {
return $this->execute(static::EXECUTE, $insert, $scope); return $this->execute(static::EXECUTE, $insert, $scope);
} }
+21 -8
View File
@@ -17,6 +17,7 @@ use JetBrains\PhpStorm\Pure;
use PDO; use PDO;
use ReflectionException; use ReflectionException;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\NotFindClassException; use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
@@ -37,9 +38,12 @@ class Connection extends Component
public string $charset = 'utf-8'; public string $charset = 'utf-8';
public string $tablePrefix = ''; public string $tablePrefix = '';
public string $database = '';
public int $timeout = 1900; public int $timeout = 1900;
public int $maxNumber = 200; public int $maxNumber = 30;
public int $minNumber = 10;
/** /**
* @var bool * @var bool
@@ -103,9 +107,11 @@ class Connection extends Component
public function fill() public function fill()
{ {
$connections = $this->connections(); $connections = $this->connections();
$connections->initConnections('mysql', $this->cds, true, $this->maxNumber); $pool = Config::get('databases.pool.max', 10);
if (!empty($this->slaveConfig)) {
$connections->initConnections('mysql', $this->slaveConfig['cds'], false, $this->maxNumber); $connections->initConnections('Mysql:' . $this->cds, true, $pool);
if (!empty($this->slaveConfig) && $this->cds != $this->slaveConfig['cds']) {
$connections->initConnections('Mysql:' . $this->slaveConfig['cds'], false, $pool);
} }
} }
@@ -172,7 +178,10 @@ class Connection extends Component
public function masterInstance(): PDO public function masterInstance(): PDO
{ {
return $this->connections()->get([ return $this->connections()->get([
'cds' => $this->cds, 'username' => $this->username, 'password' => $this->password 'cds' => $this->cds,
'username' => $this->username,
'password' => $this->password,
'database' => $this->database
], true); ], true);
} }
@@ -185,6 +194,9 @@ class Connection extends Component
if (empty($this->slaveConfig) || Db::transactionsActive()) { if (empty($this->slaveConfig) || Db::transactionsActive()) {
return $this->masterInstance(); return $this->masterInstance();
} }
if ($this->slaveConfig['cds'] == $this->cds) {
return $this->masterInstance();
}
return $this->connections()->get($this->slaveConfig, false); return $this->connections()->get($this->slaveConfig, false);
} }
@@ -252,12 +264,13 @@ class Connection extends Component
} }
/** /**
* @param $sql * @param null $sql
* @param string $dbname
* @param array $attributes * @param array $attributes
* @return Command * @return Command
* @throws * @throws Exception
*/ */
public function createCommand($sql = null, $attributes = []): Command public function createCommand($sql = null, string $dbname = '', array $attributes = []): Command
{ {
$command = new Command(['db' => $this, 'sql' => $sql]); $command = new Command(['db' => $this, 'sql' => $sql]);
return $command->bindValues($attributes); return $command->bindValues($attributes);
+12 -4
View File
@@ -51,6 +51,8 @@ class DatabasesProviders extends Providers
return $application->get('databases.' . $name); return $application->get('databases.' . $name);
} }
$config = $this->getConfig($name); $config = $this->getConfig($name);
$max = Config::get('databases.pool.max', 30);
return $application->set('databases.' . $name, [ return $application->set('databases.' . $name, [
'class' => Connection::class, 'class' => Connection::class,
'id' => $config['id'], 'id' => $config['id'],
@@ -58,7 +60,8 @@ class DatabasesProviders extends Providers
'username' => $config['username'], 'username' => $config['username'],
'password' => $config['password'], 'password' => $config['password'],
'tablePrefix' => $config['tablePrefix'], 'tablePrefix' => $config['tablePrefix'],
'maxNumber' => $config['maxNumber'], 'maxNumber' => $max,
'database' => $config['database'],
'charset' => $config['charset'] ?? 'utf8mb4', 'charset' => $config['charset'] ?? 'utf8mb4',
'slaveConfig' => $config['slaveConfig'] 'slaveConfig' => $config['slaveConfig']
]); ]);
@@ -71,10 +74,13 @@ class DatabasesProviders extends Providers
*/ */
public function createPool() public function createPool()
{ {
$databases = Config::get('databases', []); $databases = Config::get('databases.connections', []);
if (empty($databases)) { if (empty($databases)) {
return; return;
} }
$max = Config::get('databases.pool', ['max' => 10, 'min' => 10]);
$application = Snowflake::app(); $application = Snowflake::app();
foreach ($databases as $name => $database) { foreach ($databases as $name => $database) {
/** @var Connection $connection */ /** @var Connection $connection */
@@ -85,7 +91,9 @@ class DatabasesProviders extends Providers
'username' => $database['username'], 'username' => $database['username'],
'password' => $database['password'], 'password' => $database['password'],
'tablePrefix' => $database['tablePrefix'], 'tablePrefix' => $database['tablePrefix'],
'maxNumber' => $database['maxNumber'], 'database' => $database['database'],
'maxNumber' => $max['max'],
'minNumber' => $max['min'],
'charset' => $database['charset'] ?? 'utf8mb4', 'charset' => $database['charset'] ?? 'utf8mb4',
'slaveConfig' => $database['slaveConfig'] 'slaveConfig' => $database['slaveConfig']
]); ]);
@@ -101,7 +109,7 @@ class DatabasesProviders extends Providers
*/ */
public function getConfig($name): mixed public function getConfig($name): mixed
{ {
return Config::get('databases.' . $name,null, true); return Config::get('databases.connections.' . $name, null, true);
} }
+1 -3
View File
@@ -7,8 +7,6 @@ namespace Database;
use Closure; use Closure;
use Exception; use Exception;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Snowflake\Event;
use Swoole\Coroutine;
/** /**
* Class Pagination * Class Pagination
@@ -190,7 +188,7 @@ class Pagination extends Component
*/ */
private function get(): Collection|array private function get(): Collection|array
{ {
if ($this->_length + $this->_limit > $this->_max) { if ($this->_max > 0 && $this->_length + $this->_limit > $this->_max) {
$this->_limit = $this->_length + $this->_limit - $this->_max; $this->_limit = $this->_length + $this->_limit - $this->_max;
} }
$data = $this->activeQuery->limit($this->_offset, $this->_limit)->get(); $data = $this->activeQuery->limit($this->_offset, $this->_limit)->get();
+31 -8
View File
@@ -74,7 +74,7 @@ class SqlBuilder extends Component
* @return bool|array * @return bool|array
* @throws Exception * @throws Exception
*/ */
public function mathematics(array $attributes, $opera = '+'): bool|array public function mathematics(array $attributes, string $opera = '+'): bool|array
{ {
$string = $array = []; $string = $array = [];
@@ -104,7 +104,7 @@ class SqlBuilder extends Component
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
public function insert(array $attributes, $isBatch = false): array public function insert(array $attributes, bool $isBatch = false): array
{ {
$update = sprintf('INSERT INTO %s', $this->tableName()); $update = sprintf('INSERT INTO %s', $this->tableName());
if ($isBatch === false) { if ($isBatch === false) {
@@ -156,16 +156,39 @@ class SqlBuilder extends Component
* @return array[] * @return array[]
* a=:b, * a=:b,
*/ */
private function builderParams(array $attributes, bool $isInsert = false, $params = [], $order = 0): array #[Pure] private function builderParams(array $attributes, bool $isInsert = false, array $params = [], int $order = 0): array
{ {
$keys = []; $keys = [];
foreach ($attributes as $key => $value) { foreach ($attributes as $key => $value) {
if ($isInsert === true) { if ($isInsert === true) {
$keys[] = ':' . $key . $order; $keys[] = ':' . $key . $order;
} else {
$keys[] = $key . '=:' . $key . $order;
}
$params[$key . $order] = $value; $params[$key . $order] = $value;
} else {
[$keys, $params] = $this->resolveParams($key, $value, $order, $params, $keys);
}
}
return [$keys, $params];
}
/**
* @param string $key
* @param mixed $value
* @param int $order
* @param array $params
* @param array $keys
* @return array
*/
private function resolveParams(string $key, mixed $value, int $order, array $params, array $keys): array
{
if (
str_starts_with($value, '+ ') ||
str_starts_with($value, '- ')
) {
$keys[] = $key . '=' . $key . $value;
} else {
$params[$key . $order] = $value;
$keys[] = $key . '=:' . $key . $order;
} }
return [$keys, $params]; return [$keys, $params];
} }
@@ -226,7 +249,7 @@ class SqlBuilder extends Component
* @return string * @return string
* @throws Exception * @throws Exception
*/ */
private function _prefix($hasOrder = false): string private function _prefix(bool $hasOrder = false): string
{ {
$select = ''; $select = '';
if (!empty($this->query->from)) { if (!empty($this->query->from)) {
@@ -286,7 +309,7 @@ class SqlBuilder extends Component
* @return string * @return string
* @throws Exception * @throws Exception
*/ */
public function get($isCount = false): string public function get(bool $isCount = false): string
{ {
if ($isCount === false) { if ($isCount === false) {
return $this->all(); return $this->all();
-1
View File
@@ -16,7 +16,6 @@ use Database\ActiveRecord;
use Database\Condition\MathematicsCondition; use Database\Condition\MathematicsCondition;
use Database\Query; use Database\Query;
use Exception; use Exception;
use JetBrains\PhpStorm\Pure;
use ReflectionException; use ReflectionException;
use Snowflake\Exception\NotFindClassException; use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
+11 -48
View File
@@ -6,20 +6,10 @@ namespace HttpServer\Abstracts;
use Database\Connection; use Database\Connection;
use Exception; use Exception;
use HttpServer\Http\Request;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use ReflectionException;
use Snowflake\Abstracts\Config; use Snowflake\Abstracts\Config;
use Snowflake\Core\Json;
use Snowflake\Error\LoggerProcess;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException; use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
use Swoole\Process;
use Swoole\Server;
/** /**
@@ -30,7 +20,6 @@ abstract class Callback extends HttpService
{ {
const EVENT_ERROR = 'WORKER:ERROR'; const EVENT_ERROR = 'WORKER:ERROR';
const EVENT_STOP = 'WORKER:STOP'; const EVENT_STOP = 'WORKER:STOP';
const EVENT_EXIT = 'WORKER:EXIT'; const EVENT_EXIT = 'WORKER:EXIT';
@@ -42,43 +31,6 @@ abstract class Callback extends HttpService
self::EVENT_EXIT => 'The server exit. at No.', self::EVENT_EXIT => 'The server exit. at No.',
]; ];
/**
* @return PHPMailer
* @throws \PHPMailer\PHPMailer\Exception
* @throws ConfigException
*/
private function createEmail(): PHPMailer
{
$mail = new PHPMailer(true);
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = Config::get('email.host'); // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Debugoutput = false; // Enable SMTP authentication
$mail->CharSet = "UTF8"; // Enable SMTP authentication
$mail->Username = Config::get('email.username'); // SMTP username
$mail->Password = Config::get('email.password'); // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = Config::get('email.port'); // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
$mail->setFrom(Config::get('email.send.address'), Config::get('email.send.nickname'));
return $mail;
}
/**
* @param $fd
* @param $data
* @param $reID
* @return Request
* @throws Exception
*/
protected function _request($fd, $data, $reID): Request
{
return Request::createListenRequest($fd, $data, $reID);
}
/** /**
* @param $messageContent * @param $messageContent
* @throws Exception * @throws Exception
@@ -132,6 +84,17 @@ abstract class Callback extends HttpService
} }
/**
* @param array $clientInfo
* @param string $event
* @return string
*/
protected function getName(array $clientInfo, string $event): string
{
return 'listen ' . $clientInfo['server_port'] . ' ' . Event::SERVER_CONNECT;
}
/** /**
* @throws ConfigException * @throws ConfigException
* @throws Exception * @throws Exception
+2 -16
View File
@@ -7,7 +7,6 @@ namespace HttpServer\Events;
use Exception; use Exception;
use HttpServer\Abstracts\Callback; use HttpServer\Abstracts\Callback;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server; use Swoole\Server;
/** /**
@@ -28,24 +27,11 @@ class OnClose extends Callback
{ {
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
$clientInfo = $server->getClientInfo($fd);
if (!Event::exists(($name = $this->getName($clientInfo)))) { Event::trigger(Event::SERVER_CLIENT_CLOSE, [$server, $fd]);
return;
}
Event::trigger($name, [$server, $fd]);
} catch (\Throwable $exception) { } catch (\Throwable $exception) {
$this->addError($exception, 'throwable'); $this->addError($exception, 'throwable');
} }
} }
/**
* @param $server_port
* @return string
*/
private function getName($server_port): string
{
return 'listen ' . $server_port['server_port'] . ' ' . Event::SERVER_CLIENT_CLOSE;
}
} }
+4 -12
View File
@@ -27,25 +27,17 @@ class OnConnect extends Callback
{ {
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
if (($clientInfo = $server->getClientInfo($fd, $reactorId)) === false) { if (($clientInfo = $server->getClientInfo($fd, $reactorId)) === false) {
return; return;
} }
fire($this->getName($clientInfo), [$server, $fd, $reactorId]); if (isset($clientInfo['websocket_status'])) {
return;
}
fire($this->getName($clientInfo, Event::SERVER_CONNECT), [$server, $fd, $reactorId]);
} catch (\Throwable $throwable) { } catch (\Throwable $throwable) {
$this->addError($throwable, 'connect'); $this->addError($throwable, 'connect');
} }
} }
/**
* @param array $clientInfo
* @return string
*/
private function getName(array $clientInfo): string
{
return 'listen ' . $clientInfo['server_port'] . ' ' . Event::SERVER_CONNECT;
}
} }
+18 -41
View File
@@ -11,6 +11,7 @@ use HttpServer\Http\HttpHeaders;
use HttpServer\Http\HttpParams; use HttpServer\Http\HttpParams;
use HttpServer\Http\Request; use HttpServer\Http\Request;
use HttpServer\Http\Response; use HttpServer\Http\Response;
use HttpServer\Route\Router;
use ReflectionException; use ReflectionException;
use Snowflake\Core\ArrayAccess; use Snowflake\Core\ArrayAccess;
use Snowflake\Event; use Snowflake\Event;
@@ -32,9 +33,10 @@ class OnHandshake extends Callback
/** /**
* @param $request * @param $request
* @param $response * @param $response
* @return Router
* @throws Exception * @throws Exception
*/ */
private function resolveParse($request, $response) private function _protocol($request, $response): Router
{ {
/** @var Server $server */ /** @var Server $server */
$secWebSocketKey = $request->header['sec-websocket-key']; $secWebSocketKey = $request->header['sec-websocket-key'];
@@ -55,36 +57,23 @@ class OnHandshake extends Callback
foreach ($headers as $key => $val) { foreach ($headers as $key => $val) {
$response->header($key, $val); $response->header($key, $val);
} }
return Snowflake::app()->getRouter();
} }
/** /**
* @param SResponse $response * @param SResponse $response
* @param int $code * @param int $code
* @return false * @return void
*/ */
private function disconnect(SResponse $response, $code = 500): bool private function disconnect(SResponse $response, int $code = 500): void
{ {
$server = Snowflake::getWebSocket(); $server = Snowflake::getWebSocket();
if (!$server->exist($response->fd)) { if (!$server->isEstablished($response->fd)) {
return false; return;
} }
$response->status($code); $response->status($code);
$response->end(); $response->end();
return false;
}
/**
* @param $response
* @param int $code
* @return false
*/
private function connect($response, $code = 101): bool
{
$response->status($code);
$response->end();
return false;
} }
@@ -99,7 +88,15 @@ class OnHandshake extends Callback
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
$this->execute($request, $response); $router = $this->_protocol($request, $response);
[$sRequest, $sResponse] = $this->sRequest($request, $response);
if (($node = $router->find_path($sRequest)) !== null) {
$node->dispatch($sRequest, $sResponse);
} else {
$this->disconnect($response, 404);
}
} catch (\Throwable $exception) { } catch (\Throwable $exception) {
$this->addError($exception, 'throwable'); $this->addError($exception, 'throwable');
$response->status(500); $response->status(500);
@@ -108,33 +105,13 @@ class OnHandshake extends Callback
} }
/**
* @param SRequest $request
* @param SResponse $response
* @return mixed
* @throws Exception
*/
private function execute(SRequest $request, SResponse $response): mixed
{
$this->resolveParse($request, $response);
$router = Snowflake::app()->getRouter();
[$sRequest, $sResponse] = $this->sRequest($request, $response);
if (($node = $router->find_path($sRequest)) !== null) {
return $node->dispatch($sRequest, $sResponse);
}
return $this->disconnect($response, 404);
}
/** /**
* @param $request * @param $request
* @param SResponse $response * @param SResponse $response
* @return array * @return array
* @throws NotFindClassException * @throws NotFindClassException
* @throws ReflectionException * @throws ReflectionException
* @throws Exception
*/ */
private function sRequest($request, SResponse $response): array private function sRequest($request, SResponse $response): array
{ {
+1 -1
View File
@@ -18,7 +18,7 @@ class OnManagerStop extends Callback
{ {
/** /**
* @param $server * @param Server $server
* @throws Exception * @throws Exception
*/ */
public function onHandler(Server $server) public function onHandler(Server $server)
+4 -27
View File
@@ -4,22 +4,8 @@ declare(strict_types=1);
namespace HttpServer\Events; namespace HttpServer\Events;
use Annotation\Route\Socket;
use Exception;
use HttpServer\Abstracts\Callback; use HttpServer\Abstracts\Callback;
use HttpServer\Http\Context;
use HttpServer\Http\HttpHeaders;
use HttpServer\Http\HttpParams;
use HttpServer\Http\Request;
use ReflectionException;
use Snowflake\Abstracts\Config;
use Snowflake\Core\Json;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Coroutine;
use Swoole\WebSocket\Frame; use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
@@ -42,7 +28,10 @@ class OnMessage extends Callback
if ($frame->opcode === 0x08) { if ($frame->opcode === 0x08) {
return; return;
} }
Event::trigger($this->getName($server, $frame), [$frame, $server]);
$clientInfo = $this->getName($server->getClientInfo($frame->fd), Event::SERVER_MESSAGE);
Event::trigger($clientInfo, [$frame, $server]);
} catch (\Throwable $exception) { } catch (\Throwable $exception) {
$this->addError($exception, 'websocket'); $this->addError($exception, 'websocket');
if (!swoole()->isEstablished($frame->fd)) { if (!swoole()->isEstablished($frame->fd)) {
@@ -52,16 +41,4 @@ class OnMessage extends Callback
} }
} }
/**
* @param $clientInfo
* @return string
*/
private function getName(Server $server, Frame $frame): string
{
$clientInfo = $server->getClientInfo($frame->fd);
return 'listen ' . $clientInfo['server_port'] . ' ' . Event::SERVER_MESSAGE;
}
} }
+13 -29
View File
@@ -8,7 +8,6 @@ use Exception;
use HttpServer\Abstracts\Callback; use HttpServer\Abstracts\Callback;
use Snowflake\Core\Json; use Snowflake\Core\Json;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server; use Swoole\Server;
/** /**
@@ -18,45 +17,30 @@ use Swoole\Server;
class OnPacket extends Callback class OnPacket extends Callback
{ {
public int $port = 0;
public string $host = '';
/** /**
* @param Server $server * @param Server $server
* @param $data * @param string $data
* @param $clientInfo * @param array $client
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
public function onHandler(Server $server, string $data, array $clientInfo): mixed public function onHandler(Server $server, string $data, array $client): mixed
{ {
[$host, $port] = [$clientInfo['address'], $clientInfo['port']];
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
$request = $this->_request($clientInfo, $server, $data); $client['server_port'] = $client['port'];
$name = $this->getName($client, Event::SERVER_RECEIVE);
$router = Snowflake::app()->getRouter(); $result = Event::trigger($name, [$server, $data, $client]);
if (($node = $router->find_path($request)) === null) {
return $server->sendto($host, $port, Json::encode(['state' => 404]));
}
$dispatch = $node->dispatch();
if (!is_string($dispatch)) $dispatch = Json::encode($dispatch);
if (empty($dispatch)) {
$dispatch = Json::encode(['state' => 0, 'message' => 'ok']);
}
return $server->sendto($host, $port, $dispatch);
} catch (\Throwable $exception) { } catch (\Throwable $exception) {
$this->addError($exception, 'packet'); $result = logger()->exception($exception);
} finally {
$response = Json::encode(['state' => 500, 'message' => $exception->getMessage()]); if (is_array($result) || is_object($result)) {
$result = Json::encode($result);
return $server->sendto($host, $port, $response); }
$sendData = [$client['address'], $client['port'], $result];
return $server->sendto(...$sendData);
} }
} }
+13 -36
View File
@@ -7,12 +7,9 @@ namespace HttpServer\Events;
use Exception; use Exception;
use HttpServer\Abstracts\Callback; use HttpServer\Abstracts\Callback;
use HttpServer\Http\Request; use HttpServer\Http\Request;
use HttpServer\Route\Router; use Snowflake\Abstracts\Config;
use ReflectionException;
use Snowflake\Core\Json; use Snowflake\Core\Json;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Server; use Swoole\Server;
/** /**
@@ -22,21 +19,6 @@ use Swoole\Server;
class OnReceive extends Callback class OnReceive extends Callback
{ {
public int $port = 0;
public string $host = '';
private Router $router;
public function init()
{
$this->router = Snowflake::app()->getRouter();
}
/** /**
* @param Server $server * @param Server $server
* @param int $fd * @param int $fd
@@ -50,26 +32,21 @@ class OnReceive extends Callback
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
$request = $this->_request($fd, $data, $reID); $client = $server->getClientInfo($fd, $reID);
if (($node = $this->router->find_path($request)) === null) { $name = $this->getName($client, Event::SERVER_RECEIVE);
return $server->send($fd, Json::encode(['state' => 404]));
if (Config::get('rpc.port', 0) == $client['server_port']) {
$result = router()->find_path(Request::rpcRequest($fd, $data, $reID))?->dispatch();
} else {
$result = Event::trigger($name, [$server, $data, $client]);
} }
$dispatch = $node->dispatch(); if (is_array($result) || is_object($result)) {
if (!is_string($dispatch)) $dispatch = Json::encode($dispatch); $result = Json::encode($result);
if (empty($dispatch)) {
$dispatch = Json::encode(['state' => 0, 'message' => 'ok']);
} }
if ($server->exist($fd)) {
return $server->send($fd, $dispatch);
}
return $dispatch;
} catch (\Throwable $exception) { } catch (\Throwable $exception) {
$this->addError($exception, 'receive'); $result = logger()->exception($exception);
$error = ['state' => 500, 'message' => $exception->getMessage()]; } finally {
if ($server->exist($fd)) { return $server->send($fd, $result);
return $server->send($fd, Json::encode($error));
}
return Json::encode($error);
} }
} }
+6 -3
View File
@@ -16,6 +16,8 @@ use Snowflake\Snowflake;
use Swoole\Error; use Swoole\Error;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\Http\Response; use Swoole\Http\Response;
use Swoole\Http\Status;
use Throwable;
/** /**
* Class OnRequest * Class OnRequest
@@ -59,7 +61,7 @@ class OnRequest extends Callback
return $response->close(404); return $response->close(404);
} }
return $this->router->dispatch(); return $this->router->dispatch();
} catch (ExitException | Error | \Throwable $exception) { } catch (ExitException | Error | Throwable $exception) {
$this->addError($exception, 'throwable'); $this->addError($exception, 'throwable');
return $this->sendErrorMessage($request, $response, $exception); return $this->sendErrorMessage($request, $response, $exception);
} }
@@ -81,11 +83,11 @@ class OnRequest extends Callback
/** /**
* @param $sRequest * @param $sRequest
* @param $sResponse * @param $sResponse
* @param $exception * @param Throwable $exception
* @return bool|string * @return bool|string
* @throws Exception * @throws Exception
*/ */
protected function sendErrorMessage($sRequest, $sResponse, $exception): bool|string protected function sendErrorMessage($sRequest, $sResponse, Throwable $exception): bool|string
{ {
$this->addError($exception, 'throwable'); $this->addError($exception, 'throwable');
if ($sResponse instanceof Response) { if ($sResponse instanceof Response) {
@@ -95,6 +97,7 @@ class OnRequest extends Callback
$headers = $sRequest->headers->get('access-control-request-headers'); $headers = $sRequest->headers->get('access-control-request-headers');
$methods = $sRequest->headers->get('access-control-request-method'); $methods = $sRequest->headers->get('access-control-request-method');
/** @var HResponse $sResponse */
$sResponse->addHeader('Access-Control-Allow-Origin', '*'); $sResponse->addHeader('Access-Control-Allow-Origin', '*');
$sResponse->addHeader('Access-Control-Allow-Headers', $headers); $sResponse->addHeader('Access-Control-Allow-Headers', $headers);
$sResponse->addHeader('Access-Control-Request-Method', $methods); $sResponse->addHeader('Access-Control-Request-Method', $methods);
+1 -1
View File
@@ -102,7 +102,7 @@ class OnTask extends Callback
private function runTaskHandler($data): ?array private function runTaskHandler($data): ?array
{ {
try { try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); defer(fn() => fire(Event::SYSTEM_RESOURCE_CLEAN));
$serialize = $this->before($data); $serialize = $this->before($data);
if ($serialize === null) { if ($serialize === null) {
-2
View File
@@ -6,9 +6,7 @@ namespace HttpServer\Events;
use Exception; use Exception;
use HttpServer\Abstracts\Callback; use HttpServer\Abstracts\Callback;
use Snowflake\Error\Logger;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Timer; use Swoole\Timer;
/** /**
+1 -1
View File
@@ -23,7 +23,7 @@ use HttpServer\IInterface\IFormatter;
class HtmlFormatter extends HttpService implements IFormatter class HtmlFormatter extends HttpService implements IFormatter
{ {
public $data; public mixed $data;
/** @var Response */ /** @var Response */
public Response $status; public Response $status;
+16 -31
View File
@@ -415,10 +415,10 @@ class Request extends HttpService
{ {
$mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳 $mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳
$timestamp = floor($mainstay); // 时间戳 $timestamp = floatval($mainstay); // 时间戳
$milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒 $milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒
$datetime = date("Y-m-d H:i:s", $timestamp) . '.' . $milliseconds; $datetime = date("Y-m-d H:i:s", (int)$timestamp) . '.' . $milliseconds;
$tmp = [ $tmp = [
'[Debug ' . $datetime . '] ', '[Debug ' . $datetime . '] ',
@@ -427,7 +427,6 @@ class Request extends HttpService
'`' . $this->headers->getHeader('user-agent') . '`', '`' . $this->headers->getHeader('user-agent') . '`',
$this->getRuntime() $this->getRuntime()
]; ];
return implode(' ', $tmp); return implode(' ', $tmp);
} }
@@ -466,7 +465,7 @@ class Request extends HttpService
$sRequest->params->setPosts($request->post ?? []); $sRequest->params->setPosts($request->post ?? []);
} }
$sRequest->headers = new HttpHeaders(ArrayAccess::merge($request->server, $request->header)); $sRequest->headers = new HttpHeaders(array_merge($request->server, $request->header));
$sRequest->uri = $sRequest->headers->get('request_uri'); $sRequest->uri = $sRequest->headers->get('request_uri');
$sRequest->parseUri(); $sRequest->parseUri();
@@ -476,11 +475,11 @@ class Request extends HttpService
/** /**
* @param $frame * @param $frame
* @param $route * @param string $route
* @param string $event * @param string $event
* @return Request * @return Request
*/ */
public static function socketQuery($frame, $event = Socket::MESSAGE, $route = 'event'): Request public static function socketQuery($frame, string $event = Socket::MESSAGE, string $route = 'event'): Request
{ {
$sRequest = new Request(); $sRequest = new Request();
$sRequest->fd = $frame->fd; $sRequest->fd = $frame->fd;
@@ -500,10 +499,11 @@ class Request extends HttpService
* @param $fd * @param $fd
* @param $data * @param $data
* @param int $reID * @param int $reID
* @return Request * @return mixed|null
* @throws ConfigException
* @throws Exception * @throws Exception
*/ */
public static function createListenRequest($fd, $data, $reID = 0): Request public static function rpcRequest($fd, $data, int $reID = 0): Request|null
{ {
$sRequest = new Request(); $sRequest = new Request();
@@ -514,28 +514,11 @@ class Request extends HttpService
$sRequest->params = new HttpParams($data, [], []); $sRequest->params = new HttpParams($data, [], []);
$port = $sRequest->clientInfo['server_port']; $port = $sRequest->clientInfo['server_port'];
$sRequest->headers->setRequestUri('add-port-listen/port_' . $port);
$sRequest->headers->setRequestMethod(self::HTTP_LISTEN);
$sRequest->checkIsRpcClient()->parseUri();
return Context::setContext('request', $sRequest);
}
/**
* @throws ConfigException
* @throws Exception
*/
private function checkIsRpcClient(): static
{
$port = $this->clientInfo['server_port'];
if (($rpc = Config::get('rpc.port', 0)) !== $port) { if (($rpc = Config::get('rpc.port', 0)) !== $port) {
return $this; return null;
} }
[$cmd, $repeat, $body] = explode("\n", $this->params->getBody()); [$cmd, $repeat, $body] = explode("\n", $sRequest->params->getBody());
if (is_null($body) || is_null($cmd) || !empty($repeat)) { if (is_null($body) || is_null($cmd) || !empty($repeat)) {
throw new Exception('Protocol format error.'); throw new Exception('Protocol format error.');
} }
@@ -543,10 +526,12 @@ class Request extends HttpService
if (is_string($body) && is_null($data = Json::decode($body))) { if (is_string($body) && is_null($data = Json::decode($body))) {
throw new Exception('Protocol format error.'); throw new Exception('Protocol format error.');
} }
$this->headers->setRequestUri('rpc/p' . $rpc . '/' . ltrim($cmd, '/'));
$this->headers->setRequestMethod(Request::HTTP_CMD);
return $this; $sRequest->params->setPosts($data);
$sRequest->headers->setRequestUri('rpc/p' . $rpc . '/' . ltrim($cmd, '/'));
$sRequest->headers->setRequestMethod(Request::HTTP_CMD);
return Context::setContext('request', $sRequest);
} }
@@ -556,7 +541,7 @@ class Request extends HttpService
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
private static function getClientInfo($fd, $re = 0): mixed private static function getClientInfo($fd, int $re = 0): mixed
{ {
$server = Snowflake::app()->getSwoole(); $server = Snowflake::app()->getSwoole();
if (!is_array($fd)) { if (!is_array($fd)) {
+12 -13
View File
@@ -20,6 +20,7 @@ use Snowflake\Core\Json;
use Snowflake\Snowflake; use Snowflake\Snowflake;
use Swoole\Http\Response as SResponse; use Swoole\Http\Response as SResponse;
use Swoole\Http2\Response as S2Response; use Swoole\Http2\Response as S2Response;
use Swoole\WebSocket\Server;
/** /**
* Class Response * Class Response
@@ -149,12 +150,12 @@ class Response extends HttpService
} }
/** /**
* @param string $context * @param string|null $context
* @param int $statusCode * @param int $statusCode
* @return bool * @return bool
* @throws Exception * @throws Exception
*/ */
public function send($context = '', $statusCode = 200): mixed public function send(?string $context = '', int $statusCode = 200): mixed
{ {
$sendData = $this->parseData($context); $sendData = $this->parseData($context);
@@ -191,19 +192,18 @@ class Response extends HttpService
/** /**
* @param $result * @param $result
* @return string * @return void
* @throws Exception * @throws Exception
*/ */
private function printResult($result): string private function printResult($result): void
{ {
$result = Help::toString($result); $result = Help::toString($result);
$string = PHP_EOL . 'Command Result: ' . PHP_EOL . PHP_EOL; $string = PHP_EOL . 'Command Result: ' . PHP_EOL . PHP_EOL;
fire('CONSOLE_END'); fire('CONSOLE_END');
if (str_contains((string)$result, 'Event::rshutdown(): Event::wait()')) { if (str_contains((string)$result, 'Event::rshutdown(): Event::wait()')) {
return (string)$result; return;
} }
if (empty($result)) { if (empty($result)) {
$string .= 'success!' . PHP_EOL . PHP_EOL; $string .= 'success!' . PHP_EOL . PHP_EOL;
} else { } else {
@@ -211,8 +211,6 @@ class Response extends HttpService
} }
$string .= 'Command End!' . PHP_EOL . PHP_EOL; $string .= 'Command End!' . PHP_EOL . PHP_EOL;
print_r($string); print_r($string);
return (string)$result;
} }
/** /**
@@ -223,7 +221,8 @@ class Response extends HttpService
*/ */
private function sendData($response, $sendData, $status): void private function sendData($response, $sendData, $status): void
{ {
if (!Snowflake::getWebSocket()->exist($response->fd)) { $server = Snowflake::app()->getSwoole();
if (!$server->exist($response->fd)) {
return; return;
} }
if (is_array($sendData)) { if (is_array($sendData)) {
@@ -248,7 +247,7 @@ class Response extends HttpService
return $response; return $response;
} }
foreach ($this->headers as $key => $header) { foreach ($this->headers as $key => $header) {
$response->header($key, $header, true); $response->header($key, $header);
} }
$this->headers = []; $this->headers = [];
return $response; return $response;
@@ -295,7 +294,7 @@ class Response extends HttpService
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
public function close($statusCode = 200, $message = ''): mixed public function close(int $statusCode = 200, string $message = ''): mixed
{ {
return $this->send($message, $statusCode); return $this->send($message, $statusCode);
} }
@@ -307,7 +306,7 @@ class Response extends HttpService
* @param string $message * @param string $message
* @return mixed * @return mixed
*/ */
public function closeClient($clientId, $statusCode = 200, $message = ''): mixed public function closeClient($clientId,int $statusCode = 200,string $message = ''): mixed
{ {
$socket = Snowflake::getWebSocket(); $socket = Snowflake::getWebSocket();
if (!$socket->exist($clientId)) { if (!$socket->exist($clientId)) {
@@ -324,7 +323,7 @@ class Response extends HttpService
* @param int $sleep * @param int $sleep
* @return string * @return string
*/ */
public function sendFile(string $path, $offset = 0, $limit = 1024000, $sleep = 0): string public function sendFile(string $path, int $offset = 0, int $limit = 1024000, int $sleep = 0): string
{ {
$open = fopen($path, 'r'); $open = fopen($path, 'r');
+1 -7
View File
@@ -16,12 +16,10 @@ use HttpServer\Abstracts\HttpService;
use HttpServer\Controller; use HttpServer\Controller;
use HttpServer\Http\Context; use HttpServer\Http\Context;
use HttpServer\Http\Request; use HttpServer\Http\Request;
use HttpServer\HttpFilter;
use JetBrains\PhpStorm\Pure; use JetBrains\PhpStorm\Pure;
use Snowflake\Core\Json; use Snowflake\Core\Json;
use Snowflake\Snowflake; use Snowflake\Snowflake;
use Throwable; use Throwable;
use function Input;
/** /**
* Class Node * Class Node
@@ -449,15 +447,11 @@ class Node extends HttpService
if (empty($this->childes)) { if (empty($this->childes)) {
return null; return null;
} }
if (isset($this->childes[$search])) { if (isset($this->childes[$search])) {
return $this->childes[$search]; return $this->childes[$search];
} }
$_searchMatch = '/<(\w+)?:(.+)?>/';
foreach ($this->childes as $key => $val) { foreach ($this->childes as $key => $val) {
if (preg_match($_searchMatch, (string)$key, $match)) { if ($search == $key) {
Input()->addGetParam($match[1] ?? '--', $search);
return $this->childes[$key]; return $this->childes[$key];
} }
} }
+19 -3
View File
@@ -7,7 +7,10 @@ use Closure;
use Exception; use Exception;
use HttpServer\Abstracts\HttpService; use HttpServer\Abstracts\HttpService;
use HttpServer\Controller; use HttpServer\Controller;
use HttpServer\Exception\RequestException;
use HttpServer\Http\Context;
use HttpServer\Http\Request; use HttpServer\Http\Request;
use HttpServer\Http\Response;
use HttpServer\IInterface\Middleware; use HttpServer\IInterface\Middleware;
use HttpServer\IInterface\RouterInterface; use HttpServer\IInterface\RouterInterface;
use JetBrains\PhpStorm\Pure; use JetBrains\PhpStorm\Pure;
@@ -34,7 +37,7 @@ class Router extends HttpService implements RouterInterface
const NOT_FOUND = 'Page not found or method not allowed.'; const NOT_FOUND = 'Page not found or method not allowed.';
/** @var string[] */ /** @var string[] */
public array $methods = ['get', 'post', 'options', 'put', 'delete', 'receive']; public array $methods = ['get', 'post', 'options', 'put', 'delete', 'receive', 'head'];
public ?Closure $middleware = null; public ?Closure $middleware = null;
@@ -261,7 +264,7 @@ class Router extends HttpService implements RouterInterface
public function any($route, $handler): Any public function any($route, $handler): Any
{ {
$nodes = []; $nodes = [];
foreach (['get', 'post', 'options', 'put', 'delete'] as $method) { foreach (['get', 'post', 'options', 'put', 'delete', 'head'] as $method) {
$nodes[] = $this->addRoute($route, $handler, $method); $nodes[] = $this->addRoute($route, $handler, $method);
} }
return new Any($nodes); return new Any($nodes);
@@ -278,6 +281,19 @@ class Router extends HttpService implements RouterInterface
return $this->addRoute($route, $handler, 'delete'); return $this->addRoute($route, $handler, 'delete');
} }
/**
* @param $route
* @param $handler
* @return \HttpServer\Route\Node|null
* @throws \Exception
*/
public function head($route, $handler): ?Node
{
return $this->addRoute($route, $handler, 'head');
}
/** /**
* @param $route * @param $route
* @param $handler * @param $handler
@@ -490,7 +506,7 @@ class Router extends HttpService implements RouterInterface
{ {
$node = $this->find_path(\request()); $node = $this->find_path(\request());
if (!($node instanceof Node)) { if (!($node instanceof Node)) {
return send(self::NOT_FOUND); throw new RequestException(self::NOT_FOUND, 404);
} }
send(($response = $node->dispatch()), 200); send(($response = $node->dispatch()), 200);
if (!$node->hasAfter()) { if (!$node->hasAfter()) {
+4
View File
@@ -304,9 +304,13 @@ class Server extends HttpService
return; return;
} }
foreach ($config['events'] as $name => $_event) { foreach ($config['events'] as $name => $_event) {
if ($name === Event::SERVER_CLIENT_CLOSE) {
Event::on($name, $_event);
}else{
Event::on('listen ' . $config['port'] . ' ' . $name, $_event); Event::on('listen ' . $config['port'] . ' ' . $name, $_event);
} }
} }
}
/** /**
* @param $config * @param $config
+49 -17
View File
@@ -6,7 +6,6 @@ namespace HttpServer;
use Exception; use Exception;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Snowflake\Exception\ConfigException;
/** /**
@@ -51,7 +50,7 @@ class Shutdown extends Component
$master_pid = Server()->setting['pid_file'] ?? PID_PATH; $master_pid = Server()->setting['pid_file'] ?? PID_PATH;
if (file_exists($master_pid)) { if (file_exists($master_pid)) {
$this->close($master_pid); $this->close(file_get_contents($master_pid));
} }
$this->closeOther(); $this->closeOther();
} }
@@ -109,33 +108,66 @@ class Shutdown extends Component
*/ */
public function directoryCheck(string $path): bool public function directoryCheck(string $path): bool
{ {
$dir = new \DirectoryIterator($path); $values = $this->getProcessPidS($path);
if ($dir->getSize() < 1) { if (empty($values)) return false;
return true;
}
foreach ($dir as $value) {
if ($value->isDot()) continue;
if (!$value->valid()) continue; $diff = array_diff($values, $this->getPidS());
foreach ($diff as $value) {
$this->close($value->getRealPath()); $this->pidIsExists($value);
} }
return false; return false;
} }
/** /**
* @param string $value * @param $path
* @return array|bool
*/ */
public function close(string $value) private function getProcessPidS($path): bool|array
{ {
$content = file_get_contents($value); $values = [];
$dir = new \DirectoryIterator($path);
if ($dir->getSize() < 1) {
return $values;
}
foreach ($dir as $value) {
if ($value->isDot()) continue;
while ($this->pidIsExists($content)) { if (!$value->valid()) continue;
exec('kill -15 ' . $content);
sleep(1); $_value = file_get_contents($value->getRealPath());
if (empty($_value)) {
continue;
}
$values[] = intval($_value);
@unlink($value->getRealPath());
}
return $values;
} }
/**
* @return array
*/
private function getPidS(): array
{
exec('ps -eo pid', $output);
return array_filter($output, function ($value) {
return intval($value);
});
}
/**
* @param string $value
*/
public function close(mixed $value)
{
while ($this->pidIsExists($value)) {
exec('kill -15 ' . $value);
usleep(100);
}
clearstatcache($value); clearstatcache($value);
if (file_exists($value)) { if (file_exists($value)) {
@unlink($value); @unlink($value);
+12
View File
@@ -38,6 +38,7 @@ use Snowflake\Event;
use Snowflake\Exception\InitException; use Snowflake\Exception\InitException;
use Snowflake\Exception\NotFindClassException; use Snowflake\Exception\NotFindClassException;
use Snowflake\Jwt\Jwt; use Snowflake\Jwt\Jwt;
use Snowflake\Pool\ClientsPool;
use Snowflake\Pool\Connection; use Snowflake\Pool\Connection;
use Snowflake\Pool\Pool as SPool; use Snowflake\Pool\Pool as SPool;
use Snowflake\Pool\Redis as SRedis; use Snowflake\Pool\Redis as SRedis;
@@ -434,6 +435,16 @@ abstract class BaseApplication extends Service
} }
/**
* @return ClientsPool
* @throws Exception
*/
public function getClientsPool(): ClientsPool
{
return $this->get('clientsPool');
}
/** /**
* @throws Exception * @throws Exception
*/ */
@@ -444,6 +455,7 @@ abstract class BaseApplication extends Service
'connections' => ['class' => Connection::class], 'connections' => ['class' => Connection::class],
'redis_connections' => ['class' => SRedis::class], 'redis_connections' => ['class' => SRedis::class],
'pool' => ['class' => SPool::class], 'pool' => ['class' => SPool::class],
'clientsPool' => ['class' => ClientsPool::class],
'config' => ['class' => Config::class], 'config' => ['class' => Config::class],
'logger' => ['class' => Logger::class], 'logger' => ['class' => Logger::class],
'annotation' => ['class' => SAnnotation::class], 'annotation' => ['class' => SAnnotation::class],
+3 -4
View File
@@ -11,7 +11,6 @@ namespace Snowflake\Abstracts;
use Exception; use Exception;
use JetBrains\PhpStorm\Pure; use JetBrains\PhpStorm\Pure;
use Snowflake\Core\Json;
use Snowflake\Snowflake; use Snowflake\Snowflake;
use Swoole\Coroutine; use Swoole\Coroutine;
@@ -104,7 +103,7 @@ class BaseObject implements Configure
* @return bool * @return bool
* @throws Exception * @throws Exception
*/ */
public function addError($message, $model = 'app'): bool public function addError($message, string $model = 'app'): bool
{ {
if ($message instanceof \Throwable) { if ($message instanceof \Throwable) {
$Throwable = $message; $Throwable = $message;
@@ -218,10 +217,10 @@ class BaseObject implements Configure
} }
$content = (empty($method) ? '' : $method . ': ') . $message; $content = (empty($method) ? '' : $method . ': ') . $message;
$message = "\033[41;37m" . PHP_EOL . "[" . date('Y-m-d H:i:s') . '][ERROR]: ' . $content . PHP_EOL . "\033[0m"; $message = "\033[41;37m[" . date('Y-m-d H:i:s') . '][ERROR]: ' . $content . "\033[0m";
if (!empty($file)) { if (!empty($file)) {
$message .= "\033[41;37m[" . date('Y-m-d H:i:s') . '][ERROR]: ' . $file . "\033[0m"; $message .= PHP_EOL . "\033[41;37m[" . date('Y-m-d H:i:s') . '][ERROR]: ' . $file . "\033[0m";
} }
$socket->output($message . PHP_EOL); $socket->output($message . PHP_EOL);
} }
-4
View File
@@ -57,12 +57,8 @@ class Config extends Component
if (empty($configs)) { if (empty($configs)) {
return; return;
} }
if (!empty($config->data)) {
$config->data = ArrayAccess::merge($config->data, $configs);
} else {
$config->data = $configs; $config->data = $configs;
} }
}
/** /**
* @param $key * @param $key
+48 -57
View File
@@ -73,17 +73,15 @@ abstract class Pool extends Component
/** /**
* @throws Exception * @throws Exception
*/ */
public function Heartbeat_detection() public function Heartbeat_detection($ticker, string $name)
{ {
if (env('state') == 'exit') { if (env('state') == 'exit') {
Timer::clear($this->creates); Timer::clear($this->creates);
$this->creates = -1; $this->creates = -1;
} else if ($this->lastTime != 0) { } else {
[$firstClear, $lastClear] = $this->getClearTime(); $min = Config::get('databases.pool.min', 1);
if ($this->lastTime + $firstClear < time()) { if (($length = $this->getChannel($name)->length()) > $min) {
$this->flush(0); $this->flush($min);
} else if ($this->lastTime + $lastClear < time()) {
$this->flush(2);
} }
} }
} }
@@ -121,12 +119,12 @@ abstract class Pool extends Component
/** /**
* @param $channel * @param Channel $channel
* @param $name * @param $name
* @param $retain_number * @param $retain_number
* @throws Exception * @throws Exception
*/ */
protected function pop($channel, $name, $retain_number): void protected function pop(Channel $channel, $name, $retain_number): void
{ {
if (Coroutine::getCid() === -1) { if (Coroutine::getCid() === -1) {
return; return;
@@ -147,7 +145,7 @@ abstract class Pool extends Component
* @param false $isMaster * @param false $isMaster
* @param int $max * @param int $max
*/ */
public function initConnections($driver, $name, $isMaster = false, $max = 60) public function initConnections($driver, $name, bool $isMaster = false, int $max = 60)
{ {
$name = $this->name($driver, $name, $isMaster); $name = $this->name($driver, $name, $isMaster);
if (isset(static::$_items[$name]) && static::$_items[$name] instanceof Channel) { if (isset(static::$_items[$name]) && static::$_items[$name] instanceof Channel) {
@@ -156,8 +154,28 @@ abstract class Pool extends Component
if (Coroutine::getCid() === -1) { if (Coroutine::getCid() === -1) {
return; return;
} }
static::$_items[$name] = new Channel((int)$max); if ($this->creates === -1) {
$this->max = (int)$max; $this->creates = Timer::tick(1000, [$this, 'Heartbeat_detection'], $name);
}
static::$_items[$name] = new Channel($max);
$this->max = $max;
}
/**
* @param $name
* @return Channel
* @throws ConfigException
*/
private function getChannel($name): Channel
{
if (!isset(static::$_items[$name])) {
static::$_items[$name] = new Channel(Config::get('databases.pool.max', 10));
if ($this->creates === -1) {
$this->creates = Timer::tick(1000, [$this, 'Heartbeat_detection'], $name);
}
}
return static::$_items[$name];
} }
@@ -172,36 +190,23 @@ abstract class Pool extends Component
if (Coroutine::getCid() === -1) { if (Coroutine::getCid() === -1) {
return $this->createClient($name, $callback); return $this->createClient($name, $callback);
} }
$channel = static::$_items[$name] ?? new Channel($this->max);
if (!((static::$_items[$name] ?? null) instanceof Channel)) { $channel = $this->getChannel($name);
static::$_items[$name] = $channel; if (!$channel->isEmpty()) {
}
if ($channel->isEmpty()) {
$this->createByCallback($channel, $name, $callback);
}
$connection = $channel->pop(); $connection = $channel->pop();
if (!$this->checkCanUse($name, $connection)) { if ($this->checkCanUse($name, $connection)) {
return $this->createClient($name, $callback);
} else {
return $connection; return $connection;
} }
} }
return $this->createClient($name, $callback);
}
/** /**
* @param $channel * @param string $name
* @param $name * @param mixed $config
* @param mixed $callback * @return mixed
*/ */
private function createByCallback(Channel $channel, $name, mixed $callback): void
{
if ($this->creates === -1 && !is_callable($callback)) {
$this->creates = Timer::tick(1000, [$this, 'Heartbeat_detection']);
}
$channel->push($this->createClient($name, $callback));
}
abstract public function createClient(string $name, mixed $config): mixed; abstract public function createClient(string $name, mixed $config): mixed;
@@ -211,7 +216,7 @@ abstract class Pool extends Component
* @param false $isMaster * @param false $isMaster
* @return string * @return string
*/ */
#[Pure] public function name($driver, $cds, $isMaster = false): string #[Pure] public function name($driver, $cds, bool $isMaster = false): string
{ {
if ($isMaster === true) { if ($isMaster === true) {
return $cds . '_master'; return $cds . '_master';
@@ -223,7 +228,7 @@ abstract class Pool extends Component
/** /**
* @param string $name * @param string $name
* @param $client * @param mixed $client
* @return bool * @return bool
* 检查连接可靠性 * 检查连接可靠性
*/ */
@@ -235,7 +240,7 @@ abstract class Pool extends Component
/** /**
* @param array $config * @param array $config
* @param $isMaster * @param bool $isMaster
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
@@ -249,19 +254,6 @@ abstract class Pool extends Component
* @param string $name * @param string $name
* @return bool * @return bool
*/ */
public function canCreate(string $name): bool
{
if (!isset(static::$hasCreate[$name])) {
static::$hasCreate[$name] = 0;
}
return static::$hasCreate[$name] < $this->max;
}
/**
* @param $name
* @return bool
*/
public function hasItem(string $name): bool public function hasItem(string $name): bool
{ {
if (isset(static::$_items[$name])) { if (isset(static::$_items[$name])) {
@@ -272,7 +264,7 @@ abstract class Pool extends Component
/** /**
* @param $name * @param string $name
* @return mixed * @return mixed
*/ */
public function size(string $name): mixed public function size(string $name): mixed
@@ -288,18 +280,16 @@ abstract class Pool extends Component
/** /**
* @param $name * @param string $name
* @param $client * @param mixed $client
* @throws ConfigException
*/ */
public function push(string $name, mixed $client) public function push(string $name, mixed $client)
{ {
if (Coroutine::getCid() === -1) { if (Coroutine::getCid() === -1) {
return; return;
} }
$channel = static::$_items[$name] ?? new Channel($this->max); $channel = $this->getChannel($name);
if (!isset(static::$_items[$name])) {
static::$_items[$name] = $channel;
}
if (!$channel->isFull()) { if (!$channel->isFull()) {
$channel->push($client); $channel->push($client);
} }
@@ -321,6 +311,7 @@ abstract class Pool extends Component
if ($this->creates > -1) { if ($this->creates > -1) {
Timer::clear($this->creates); Timer::clear($this->creates);
} }
$channel->close();
static::$_items[$name] = null; static::$_items[$name] = null;
} }
+2
View File
@@ -23,6 +23,7 @@ use Snowflake\Channel;
use Snowflake\Error\Logger; use Snowflake\Error\Logger;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Jwt\Jwt; use Snowflake\Jwt\Jwt;
use Snowflake\Pool\ClientsPool;
use Snowflake\Pool\Connection; use Snowflake\Pool\Connection;
use Snowflake\Pool\Pool as SPool; use Snowflake\Pool\Pool as SPool;
use Rpc\Producer as RPCProducer; use Rpc\Producer as RPCProducer;
@@ -54,6 +55,7 @@ use Rpc\Producer as RPCProducer;
* @property Channel $channel * @property Channel $channel
* @property Shutdown $shutdown * @property Shutdown $shutdown
* @property Emit $emit * @property Emit $emit
* @property ClientsPool $clientsPool
*/ */
trait TraitApplication trait TraitApplication
{ {
+17 -16
View File
@@ -12,6 +12,7 @@ namespace Snowflake\Cache;
use Exception; use Exception;
use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config; use Snowflake\Abstracts\Config;
use Snowflake\Core\Json;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\ConfigException; use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake; use Snowflake\Snowflake;
@@ -20,6 +21,7 @@ use Snowflake\Snowflake;
* Class Redis * Class Redis
* @package Snowflake\Snowflake\Cache * @package Snowflake\Snowflake\Cache
* @see \Redis * @see \Redis
*
*/ */
class Redis extends Component class Redis extends Component
{ {
@@ -51,11 +53,10 @@ class Redis extends Component
$connections = Snowflake::app()->getRedisFromPool(); $connections = Snowflake::app()->getRedisFromPool();
$config = $this->get_config(); $config = $this->get_config();
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
$length = env('REDIS.POOL_LENGTH', 100); $length = (int)env('REDIS.POOL_LENGTH', 100);
$connections->initConnections('redis', 'redis:' . $name, true, $length); $connections->initConnections('Redis:' . $config['host'], true, $length);
} }
@@ -67,11 +68,17 @@ class Redis extends Component
*/ */
public function __call($name, $arguments): mixed public function __call($name, $arguments): mixed
{ {
$time = microtime(true);
if (method_exists($this, $name)) { if (method_exists($this, $name)) {
$data = $this->{$name}(...$arguments); $data = $this->{$name}(...$arguments);
} else { } else {
$data = $this->proxy()->{$name}(...$arguments); $data = $this->proxy()->{$name}(...$arguments);
} }
if (microtime(true) - $time >= 0.02) {
$this->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
}
return $data; return $data;
} }
@@ -82,7 +89,7 @@ class Redis extends Component
* @return bool|int * @return bool|int
* @throws Exception * @throws Exception
*/ */
public function lock($key, $timeout = 5): bool|int public function lock($key, int $timeout = 5): bool|int
{ {
$script = <<<SCRIPT $script = <<<SCRIPT
local _nx = redis.call('setnx',KEYS[1], ARGV[1]) local _nx = redis.call('setnx',KEYS[1], ARGV[1])
@@ -92,7 +99,7 @@ if (_nx ~= 0) then
end end
return 0 return 0
SCRIPT; SCRIPT;
return $this->proxy()->eval($script, [$key, $timeout], 1); return $this->proxy()->eval($script, ['{lock}:' . $key, $timeout], 1);
} }
@@ -104,7 +111,7 @@ SCRIPT;
public function unlock($key): int public function unlock($key): int
{ {
$redis = $this->proxy(); $redis = $this->proxy();
return $redis->del($key); return $redis->del('{lock}:' . $key);
} }
@@ -137,7 +144,9 @@ SCRIPT;
{ {
$connections = Snowflake::app()->getRedisFromPool(); $connections = Snowflake::app()->getRedisFromPool();
$client = $connections->get($this->get_config(), true); $config = $this->get_config();
$client = $connections->get($config, true);
if (!($client instanceof \Redis)) { if (!($client instanceof \Redis)) {
throw new Exception('Redis connections more.'); throw new Exception('Redis connections more.');
} }
@@ -150,15 +159,7 @@ SCRIPT;
*/ */
public function get_config(): array public function get_config(): array
{ {
return Config::get('cache.redis', false, [ return Config::get('cache.redis', null, true);
'host' => '127.0.0.1',
'port' => '6379',
'prefix' => Config::get('id'),
'auth' => '',
'databases' => '0',
'read_timeout' => -1,
'timeout' => -1,
]);
} }
} }
+33 -4
View File
@@ -21,6 +21,36 @@ class Channel extends Component
private static array $_channels = []; private static array $_channels = [];
private static array $_waitRecover = [];
public function init()
{
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'recover']);
}
/**
* 回收对象
*/
public function recover()
{
foreach (Channel::$_waitRecover as $key => $value) {
if (empty($value)) {
continue;
}
$channel = $this->channelInit($key);
if ($channel->count() >= 100) {
continue;
}
foreach ($value as $item) {
$channel->enqueue($item);
}
}
Channel::$_waitRecover = [];
}
/** /**
* @param mixed $value * @param mixed $value
* @param string $name * @param string $name
@@ -28,11 +58,10 @@ class Channel extends Component
*/ */
public function push(mixed $value, string $name = ''): void public function push(mixed $value, string $name = ''): void
{ {
$channel = $this->channelInit($name); if (!isset(Channel::$_waitRecover[$name])) {
if ($channel->count() >= 100) { Channel::$_waitRecover[$name] = [];
return;
} }
$channel->enqueue($value); Channel::$_waitRecover[$name][] = $value;
} }
+13
View File
@@ -184,6 +184,19 @@ abstract class Crontab extends BaseObject
abstract public function isStop(): bool; abstract public function isStop(): bool;
/**
* @param $name
* @return mixed
*/
public function __get($name): mixed
{
if (!isset($this->params[$name])) {
return null;
}
return $this->params[$name];
}
/** /**
* @throws Exception * @throws Exception
*/ */
+1 -1
View File
@@ -16,7 +16,7 @@ use Snowflake\Snowflake;
class Producer extends Component class Producer extends Component
{ {
const CRONTAB_KEY = '_application:system:crontab'; const CRONTAB_KEY = '_application:{crontab}:system:crontab';
/** /**
+8 -3
View File
@@ -118,11 +118,16 @@ class Zookeeper extends Process
*/ */
private function loadCarobTask(Redis|\Redis $redis): array private function loadCarobTask(Redis|\Redis $redis): array
{ {
$range = $redis->zRangeByScore(Producer::CRONTAB_KEY, '0', (string)time()); $script = <<<SCRIPT
local _two = redis.call('zRangeByScore', KEYS[1], '0', ARGV[1])
$redis->zRem(Producer::CRONTAB_KEY, ...$range); if (table.getn(_two) > 0) then
redis.call('ZREM', KEYS[1], unpack(_two))
end
return $range; return _two
SCRIPT;
return $redis->eval($script, [Producer::CRONTAB_KEY, (string)time()], 1);
} }
} }
+8 -8
View File
@@ -96,7 +96,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
} }
/** /**
* @param $timeout * @param int $timeout
*/ */
public function setTimeout(int $timeout) public function setTimeout(int $timeout)
{ {
@@ -104,7 +104,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
} }
/** /**
* @param $timeout * @param string $timeout
*/ */
public function setKey(string $timeout) public function setKey(string $timeout)
{ {
@@ -127,7 +127,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
public function create(int $unionId, $headers = []): array public function create(int $unionId, array $headers = []): array
{ {
$this->user = $unionId; $this->user = $unionId;
$this->config['time'] = time(); $this->config['time'] = time();
@@ -181,7 +181,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
* @return array * @return array
* @throws * @throws
*/ */
private function assembly(array $param, $update = FALSE): array private function assembly(array $param, bool $update = FALSE): array
{ {
if (isset($param['sign'])) { if (isset($param['sign'])) {
unset($param['sign']); unset($param['sign']);
@@ -204,7 +204,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
public function refresh($headers = []): array public function refresh(array $headers = []): array
{ {
$this->data = $headers; $this->data = $headers;
if (!openssl_public_decrypt(base64_decode($headers['refresh']), $data, $this->public)) { if (!openssl_public_decrypt(base64_decode($headers['refresh']), $data, $this->public)) {
@@ -223,7 +223,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
} }
/** /**
* @param $param * @param array $param
* *
* @return array * @return array
*/ */
@@ -292,7 +292,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
* *
* @return string * @return string
*/ */
private function token(int $user, $param = [], $requestTime = NULL): string private function token(int $user, array $param = [], $requestTime = NULL): string
{ {
$str = ''; $str = '';
@@ -349,7 +349,7 @@ mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
* @param array $data * @param array $data
* @param int $user * @param int $user
* @return bool * @return bool
* @throws AuthException * @throws AuthException|Exception
*/ */
public function check(array $data, int $user): bool public function check(array $data, int $user): bool
{ {
+324
View File
@@ -0,0 +1,324 @@
<?php
namespace Snowflake\Pool;
use Exception;
use JetBrains\PhpStorm\Pure;
use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use Swoole\Timer;
/**
* Class ClientsPool
* @package Snowflake\Pool
*/
class ClientsPool extends Component
{
/** @var Channel[] */
private static array $_connections = [];
public int $max = 60;
public int $creates = -1;
private array $_times = [];
protected static array $hasCreate = [];
/**
* @param string $name
*/
public function increment(string $name)
{
if (!isset(static::$hasCreate[$name])) {
static::$hasCreate[$name] = 0;
}
static::$hasCreate[$name] += 1;
}
/**
* @param string $name
*/
public function decrement(string $name)
{
if (!isset(static::$hasCreate[$name])) {
return;
}
if (static::$hasCreate[$name] <= 0) {
return;
}
static::$hasCreate[$name] -= 1;
}
/**
* @return array
* @throws ConfigException
*/
private function getClearTime(): array
{
$firstClear = Config::get('pool.clear.start', 600);
$lastClear = Config::get('pool.clear.end', 300);
return [$firstClear, $lastClear];
}
/**
* @throws Exception
*/
public function Heartbeat_detection($ticker)
{
if (env('state') == 'exit') {
Timer::clear($this->creates);
$this->creates = -1;
} else {
$this->heartbeat_flush();
}
}
/**
* @throws ConfigException
* @throws Exception
*/
private function heartbeat_flush()
{
$num = [];
$total = 0;
$min = Config::get('databases.pool.min', 1);
foreach (static::$_connections as $key => $channel) {
if (!isset($num[$key])) {
$num[$key] = 0;
}
if (time() - ($this->_times[$key] ?? time()) > 120) {
$this->flush($channel, 0);
} else if ($channel->length() > $min) {
$this->flush($channel, $min);
}
$num[$key] += ($length = $channel->length());
if (str_starts_with($key, 'Mysql') && (Snowflake::isWorker() || Snowflake::isTask()) && $length > 0) {
$this->debug('Worker #' . env('worker') . ' use client -> ' . $key . ':' . $length);
}
$total += $length;
}
write(var_export($num, true), 'connections');
if ($total < 1) {
Timer::clear($this->creates);
if (Snowflake::isWorker() || Snowflake::isTask()) {
$this->debug('Worker #' . env('worker') . ' clear time tick.');
}
$this->creates = -1;
}
}
/**
* @param $channel
* @param $retain_number
* @throws Exception
*/
public function flush($channel, $retain_number)
{
$this->pop($channel, $retain_number);
static::$_connections = [];
}
/**
* @param Channel $channel
* @param $retain_number
* @throws Exception
*/
protected function pop(Channel $channel, $retain_number): void
{
if (Coroutine::getCid() === -1) {
return;
}
while ($channel->length() > $retain_number) {
$connection = $channel->pop();
if ($connection) {
unset($connection);
}
}
}
/**
* @param $name
* @param false $isMaster
* @param int $max
*/
public function initConnections($name, bool $isMaster = false, int $max = 60)
{
$name = $this->name($name, $isMaster);
if (isset(static::$_connections[$name]) && static::$_connections[$name] instanceof Channel) {
return;
}
if (Coroutine::getCid() === -1) {
return;
}
if ($this->creates === -1) {
$this->creates = Timer::tick(60000, [$this, 'Heartbeat_detection']);
}
static::$_connections[$name] = new Channel($max);
$this->max = $max;
}
/**
* @param $name
* @return Channel
* @throws ConfigException
*/
private function getChannel($name): Channel
{
if (!isset(static::$_connections[$name])) {
static::$_connections[$name] = new Channel(Config::get('databases.pool.max', 10));
}
if ($this->creates === -1) {
$this->creates = Timer::tick(60000, [$this, 'Heartbeat_detection']);
}
return static::$_connections[$name];
}
/**
* @param $name
* @return array
* @throws Exception
*/
public function getFromChannel($name): mixed
{
$this->_times[$name] = time();
$channel = $this->getChannel($name);
if (!$channel->isEmpty()) {
$connection = $channel->pop();
if ($this->checkCanUse($name, $connection)) {
return $connection;
}
}
return null;
}
/**
* @param $cds
* @param false $isMaster
* @return string
*/
#[Pure] public function name($cds, bool $isMaster = false): string
{
if ($isMaster === true) {
return $cds . '_master';
} else {
return $cds . '_slave';
}
}
/**
* @param string $name
* @param mixed $client
* @return bool
* 检查连接可靠性
*/
public function checkCanUse(string $name, mixed $client): bool
{
return true;
}
/**
* @param array $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function get(mixed $config, bool $isMaster): mixed
{
throw new Exception('Undefined system processing function.');
}
/**
* @param string $name
* @return bool
*/
public function hasItem(string $name): bool
{
if (isset(static::$_connections[$name])) {
return !static::$_connections[$name]->isEmpty();
}
return false;
}
/**
* @param string $name
* @return mixed
*/
public function size(string $name): mixed
{
if (Coroutine::getCid() === -1) {
return 0;
}
if (!isset(static::$_connections[$name])) {
return 0;
}
return static::$_connections[$name]->length();
}
/**
* @param string $name
* @param mixed $client
* @throws ConfigException
*/
public function push(string $name, mixed $client)
{
if (Coroutine::getCid() === -1) {
return;
}
$channel = $this->getChannel($name);
if (!$channel->isFull()) {
$channel->push($client);
}
unset($client);
}
/**
* @param string $name
* @throws Exception
*/
public function clean(string $name)
{
if (Coroutine::getCid() === -1 || !isset(static::$_connections[$name])) {
return;
}
$channel = static::$_connections[$name];
$this->pop($channel, 0);
}
/**
* @return Channel[]
*/
protected function getChannels(): array
{
return static::$_connections;
}
}
+62 -49
View File
@@ -6,7 +6,8 @@ namespace Snowflake\Pool;
use Exception; use Exception;
use HttpServer\Http\Context; use HttpServer\Http\Context;
use PDO; use PDO;
use Snowflake\Abstracts\Pool; use Snowflake\Abstracts\Component;
use Snowflake\Snowflake;
use Swoole\Coroutine; use Swoole\Coroutine;
use Swoole\Error; use Swoole\Error;
use Swoole\Runtime; use Swoole\Runtime;
@@ -16,51 +17,36 @@ use Throwable;
* Class Connection * Class Connection
* @package Snowflake\Pool * @package Snowflake\Pool
*/ */
class Connection extends Pool class Connection extends Component
{ {
private ?ClientsPool $clientsPool = null;
public int $timeout = 1900;
/**
* @param $timeout
*/
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/** /**
* @param $cds * @param $cds
* @return bool * @return bool
* *
* db is in transaction * db is in transaction
* @throws Exception
*/ */
public function inTransaction($cds): bool public function inTransaction($cds): bool
{ {
return Context::getContext('begin_' . $this->name('mysql', $cds, true)) == 0; return Context::getContext('begin_' . $this->getPool()->name('Mysql:' . $cds, true)) == 0;
} }
/** /**
* @param $coroutineName * @param $coroutineName
* @throws Exception
*/ */
public function beginTransaction($coroutineName) public function beginTransaction($coroutineName)
{ {
$coroutineName = $this->name('mysql', $coroutineName, true); $coroutineName = $this->getPool()->name('Mysql:' . $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) { if (!Context::hasContext('begin_' . $coroutineName)) {
Context::setContext('begin_' . $coroutineName, 0); Context::setContext('begin_' . $coroutineName, 0);
} }
Context::increment('begin_' . $coroutineName); Context::increment('begin_' . $coroutineName);
if (!Context::getContext('begin_' . $coroutineName) !== 0) { if (Context::getContext('begin_' . $coroutineName) != 0) {
return; return;
} }
$connection = Context::getContext($coroutineName); $connection = Context::getContext($coroutineName);
@@ -71,10 +57,11 @@ class Connection extends Pool
/** /**
* @param $coroutineName * @param $coroutineName
* @throws Exception
*/ */
public function commit($coroutineName) public function commit($coroutineName)
{ {
$coroutineName = $this->name('mysql', $coroutineName, true); $coroutineName = $this->getPool()->name('Mysql:' . $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) { if (!Context::hasContext('begin_' . $coroutineName)) {
return; return;
} }
@@ -92,22 +79,13 @@ class Connection extends Pool
} }
/**
* @param $name
* @param false $isMaster
* @return array
*/
private function getIndex($name, $isMaster = false): array
{
return [Coroutine::getCid(), $this->name('mysql', $name, $isMaster)];
}
/** /**
* @param $coroutineName * @param $coroutineName
* @throws Exception
*/ */
public function rollback($coroutineName) public function rollback($coroutineName)
{ {
$coroutineName = $this->name('mysql', $coroutineName, true); $coroutineName = $this->getPool()->name('Mysql:' . $coroutineName, true);
if (!Context::hasContext('begin_' . $coroutineName)) { if (!Context::hasContext('begin_' . $coroutineName)) {
return; return;
} }
@@ -129,13 +107,21 @@ class Connection extends Pool
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
public function get(mixed $config, $isMaster = false): mixed public function get(mixed $config, bool $isMaster = false): mixed
{ {
$coroutineName = $this->name('mysql', $config['cds'], $isMaster); $coroutineName = $this->getPool()->name('Mysql:' . $config['cds'], $isMaster);
if (($pdo = Context::getContext($coroutineName)) instanceof PDO) { if (($pdo = Context::getContext($coroutineName)) instanceof PDO) {
return $pdo; return $pdo;
} }
$connections = $this->getFromChannel($coroutineName, $config); if (Coroutine::getCid() === -1) {
$connections = $this->createClient($coroutineName, $config);
} else {
/** @var PDO $connections */
$connections = $this->getPool()->getFromChannel($coroutineName);
if (empty($connections)) {
$connections = $this->createClient($coroutineName, $config);
}
}
if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) { if ($number = Context::getContext('begin_' . $coroutineName, Coroutine::getCid())) {
$number > 0 && $connections->beginTransaction(); $number > 0 && $connections->beginTransaction();
} }
@@ -143,6 +129,18 @@ class Connection extends Pool
} }
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
/** /**
* @param string $name * @param string $name
* @param mixed $config * @param mixed $config
@@ -154,10 +152,11 @@ class Connection extends Pool
if (Coroutine::getCid() === -1) { if (Coroutine::getCid() === -1) {
Runtime::enableCoroutine(false); Runtime::enableCoroutine(false);
} }
$link = new PDO($config['cds'], $config['username'], $config['password'], [ $cds = 'mysql:dbname=' . $config['database'] . ';host=' . $config['cds'];
$link = new PDO($cds, $config['username'], $config['password'], [
PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_TIMEOUT => $this->timeout, PDO::ATTR_TIMEOUT => 60,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . ($config['charset'] ?? 'utf8mb4') PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . ($config['charset'] ?? 'utf8mb4')
]); ]);
@@ -175,7 +174,7 @@ class Connection extends Pool
*/ */
public function release($coroutineName, $isMaster) public function release($coroutineName, $isMaster)
{ {
$coroutineName = $this->name('mysql', $coroutineName, $isMaster); $coroutineName = $this->getPool()->name('Mysql:' . $coroutineName, $isMaster);
/** @var PDO $client */ /** @var PDO $client */
if (!($client = Context::getContext($coroutineName)) instanceof PDO) { if (!($client = Context::getContext($coroutineName)) instanceof PDO) {
@@ -184,8 +183,8 @@ class Connection extends Pool
if ($client->inTransaction()) { if ($client->inTransaction()) {
$client->commit(); $client->commit();
} }
$this->push($coroutineName, $client); $this->getPool()->push($coroutineName, $client);
$this->lastTime = time(); Context::remove($coroutineName);
} }
@@ -203,9 +202,9 @@ class Connection extends Pool
* batch release * batch release
* @throws Exception * @throws Exception
*/ */
public function connection_clear() public function connection_clear($name, $isMaster)
{ {
$this->flush(0); $this->getPool()->clean($this->getPool()->name($name, $isMaster));
} }
@@ -227,7 +226,7 @@ class Connection extends Pool
$result = $this->addError($exception, 'mysql'); $result = $this->addError($exception, 'mysql');
} finally { } finally {
if (!$result) { if (!$result) {
$this->decrement($name); $this->getPool()->decrement($name);
} }
return $result; return $result;
} }
@@ -239,10 +238,24 @@ class Connection extends Pool
* @param bool $isMaster * @param bool $isMaster
* @throws Exception * @throws Exception
*/ */
public function disconnect($coroutineName, $isMaster = false) public function disconnect($coroutineName, bool $isMaster = false)
{ {
$coroutineName = $this->name($coroutineName, $isMaster); Context::remove($coroutineName);
$this->clean($coroutineName); $coroutineName = $this->getPool()->name('Mysql:' . $coroutineName, $isMaster);
$this->getPool()->clean($coroutineName);
}
/**
* @return ClientsPool
* @throws Exception
*/
public function getPool(): ClientsPool
{
if (!$this->clientsPool) {
$this->clientsPool = Snowflake::app()->getClientsPool();
}
return $this->clientsPool;
} }
} }
+44 -60
View File
@@ -8,8 +8,10 @@ namespace Snowflake\Pool;
use Exception; use Exception;
use HttpServer\Http\Context; use HttpServer\Http\Context;
use Redis as SRedis; use Redis as SRedis;
use Snowflake\Abstracts\Pool; use Snowflake\Abstracts\Component;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\RedisConnectException; use Snowflake\Exception\RedisConnectException;
use Snowflake\Snowflake;
use Swoole\Coroutine; use Swoole\Coroutine;
use Swoole\Runtime; use Swoole\Runtime;
@@ -17,32 +19,10 @@ use Swoole\Runtime;
* Class RedisClient * Class RedisClient
* @package Snowflake\Snowflake\Pool * @package Snowflake\Snowflake\Pool
*/ */
class Redis extends Pool class Redis extends Component
{ {
private ?ClientsPool $clientsPool = null;
public int $_create = 0;
/**
* @param $value
*/
public function setLength($value)
{
$this->max = $value;
}
/**
* @param string $name
* @return bool
*/
public function canCreate(string $name): bool
{
if (!isset(static::$hasCreate[$name])) {
static::$hasCreate[$name] = 0;
}
return static::$hasCreate[$name] >= $this->max;
}
/** /**
@@ -51,15 +31,21 @@ class Redis extends Pool
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
public function get(mixed $config, $isMaster = false): mixed public function get(mixed $config, bool $isMaster = false): mixed
{ {
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases']; $coroutineName = $this->getPool()->name('Redis:' . $config['host'], $isMaster);
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster); if (Context::hasContext($coroutineName)) {
if (!Context::hasContext($coroutineName)) {
return Context::setContext($coroutineName, $this->getFromChannel($coroutineName, $config));
}
return Context::getContext($coroutineName); return Context::getContext($coroutineName);
} }
if (Coroutine::getCid() === -1) {
return Context::setContext($coroutineName, $this->createClient($coroutineName, $config));
}
$clients = $this->getPool()->getFromChannel($coroutineName);
if (empty($clients)) {
return Context::setContext($coroutineName, $this->createClient($coroutineName, $config));
}
return Context::setContext($coroutineName, $clients);
}
/** /**
@@ -88,7 +74,7 @@ class Redis extends Pool
$redis->setOption(SRedis::OPT_READ_TIMEOUT, $config['read_timeout']); $redis->setOption(SRedis::OPT_READ_TIMEOUT, $config['read_timeout']);
$redis->setOption(SRedis::OPT_PREFIX, $config['prefix']); $redis->setOption(SRedis::OPT_PREFIX, $config['prefix']);
$this->increment($name); $this->getPool()->increment($name);
return $redis; return $redis;
} }
@@ -97,18 +83,18 @@ class Redis extends Pool
/** /**
* @param array $config * @param array $config
* @param bool $isMaster * @param bool $isMaster
* @throws ConfigException
* @throws Exception
*/ */
public function release(array $config, $isMaster = false) public function release(array $config, bool $isMaster = false)
{ {
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases']; $coroutineName = $this->getPool()->name('Redis:' . $config['host'], $isMaster);
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (!Context::hasContext($coroutineName)) { if (!Context::hasContext($coroutineName)) {
return; return;
} }
$this->push($coroutineName, Context::getContext($coroutineName)); $this->getPool()->push($coroutineName, Context::getContext($coroutineName));
Context::remove($coroutineName); Context::remove($coroutineName);
$this->lastTime = time();
} }
/** /**
@@ -116,42 +102,40 @@ class Redis extends Pool
* @param bool $isMaster * @param bool $isMaster
* @throws Exception * @throws Exception
*/ */
public function destroy(array $config, $isMaster = false) public function destroy(array $config, bool $isMaster = false)
{ {
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases']; $coroutineName = $this->getPool()->name('Redis:' . $config['host'], $isMaster);
$coroutineName = $this->name('redis', 'redis:' . $name, $isMaster);
if (Context::hasContext($coroutineName)) { if (Context::hasContext($coroutineName)) {
$this->decrement($coroutineName); $this->getPool()->decrement($coroutineName);
} }
$this->getPool()->clean($coroutineName);
Context::remove($coroutineName); Context::remove($coroutineName);
$this->flush(0);
} }
/** /**
* @param string $name * @return ClientsPool
* @param mixed $client
* @return bool
* @throws Exception * @throws Exception
*/ */
public function checkCanUse(string $name, mixed $client): bool public function getPool(): ClientsPool
{ {
try { if (!$this->clientsPool) {
if (!($client instanceof SRedis)) { $this->clientsPool = Snowflake::app()->getClientsPool();
$result = false;
} else {
$result = true;
}
} catch (\Throwable $exception) {
$this->addError($exception, 'redis');
$result = false;
} finally {
if (!$result) {
$this->decrement($name);
}
return $result;
} }
return $this->clientsPool;
} }
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
} }
+2 -1
View File
@@ -28,7 +28,6 @@ abstract class Process extends \Swoole\Process implements SProcess
public function __construct($application, $name, $enable_coroutine = true) public function __construct($application, $name, $enable_coroutine = true)
{ {
parent::__construct([$this, '_load'], false, 1, $enable_coroutine); parent::__construct([$this, '_load'], false, 1, $enable_coroutine);
Snowflake::setProcessId($this->pid);
} }
/** /**
@@ -37,6 +36,8 @@ abstract class Process extends \Swoole\Process implements SProcess
*/ */
public function _load(Process $process) public function _load(Process $process)
{ {
Snowflake::setProcessId($this->pid);
putenv('environmental=' . Snowflake::PROCESS); putenv('environmental=' . Snowflake::PROCESS);
fire(Event::SERVER_WORKER_START); fire(Event::SERVER_WORKER_START);
+34 -2
View File
@@ -17,6 +17,7 @@ use JetBrains\PhpStorm\Pure;
use Snowflake\Abstracts\Config; use Snowflake\Abstracts\Config;
use Snowflake\Application; use Snowflake\Application;
use Snowflake\Core\ArrayAccess; use Snowflake\Core\ArrayAccess;
use Snowflake\Core\Json;
use Snowflake\Error\Logger; use Snowflake\Error\Logger;
use Snowflake\Event; use Snowflake\Event;
use Snowflake\Exception\ConfigException; use Snowflake\Exception\ConfigException;
@@ -375,6 +376,35 @@ if (!function_exists('logger')) {
} }
} }
if (!function_exists('trim_blank')) {
/**
* 空白字符替换
* @param string $content 内容
* @param int $len 截取长度
* @param string $encode 编码
* @param bool $htmlTags
* @return array|string|null
*/
function trim_blank(string $content, $len = 0, $encode = 'utf-8', $htmlTags = true): array|string|null
{
$str = trim($content);
if ($htmlTags) {
$str = strip_tags($str);
}
$str = preg_replace('/[\n|\r|\t]+/', '', $str);
$str = preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/", '', $str);
if ($len > 0) {
return mb_substr($str, 0, $len, $encode);
} else {
return $str;
}
}
}
if (!function_exists('get_file_extension')) { if (!function_exists('get_file_extension')) {
function get_file_extension($filename) function get_file_extension($filename)
@@ -615,12 +645,14 @@ if (!function_exists('send')) {
/** /**
* @param $context * @param $context
* @param $statusCode * @param int $statusCode
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
function send($context, $statusCode = 404): mixed function send($context, int $statusCode = 404): mixed
{ {
if (is_array($context)) $context = Json::encode($context);
return \response()->send($context, $statusCode); return \response()->send($context, $statusCode);
} }