mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-23 16:45:35 +08:00
update to 1.3.1 version
fix DataProvider::setJsonData bug
add Root document of default request
⚠️ change MySQL driver to PDO, mysqlnd required
improve exception catcher
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"description": "high-performance intelligent assistant",
|
"description": "high-performance intelligent assistant",
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"license": "proprietary",
|
"license": "proprietary",
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "whale",
|
"name": "whale",
|
||||||
@@ -22,12 +22,16 @@
|
|||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-posix": "*",
|
"ext-posix": "*",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"nikic/php-parser": "^4.4"
|
"nikic/php-parser": "^4.4",
|
||||||
|
"ext-pdo": "*"
|
||||||
},
|
},
|
||||||
"repositories": {
|
"repositories": {
|
||||||
"packagist": {
|
"packagist": {
|
||||||
"type": "composer",
|
"type": "composer",
|
||||||
"url": "https://mirrors.aliyun.com/composer/"
|
"url": "https://mirrors.aliyun.com/composer/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,10 @@ class DataProvider
|
|||||||
|
|
||||||
private static function setJsonData($filename, array $args) {
|
private static function setJsonData($filename, array $args) {
|
||||||
$pathinfo = pathinfo($filename);
|
$pathinfo = pathinfo($filename);
|
||||||
if (!is_dir($pathinfo["dirname"])) mkdir(self::getDataConfig() . $pathinfo["dirname"]);
|
if (!is_dir(self::getDataConfig() . $pathinfo["dirname"])) {
|
||||||
|
Console::debug("Making Directory: " . self::getDataConfig() . $pathinfo["dirname"]);
|
||||||
|
mkdir(self::getDataConfig() . $pathinfo["dirname"]);
|
||||||
|
}
|
||||||
$r = file_put_contents(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
|
$r = file_put_contents(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
|
||||||
if ($r === false) {
|
if ($r === false) {
|
||||||
Console::warning("无法保存文件: " . $filename);
|
Console::warning("无法保存文件: " . $filename);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
namespace Framework;
|
namespace Framework;
|
||||||
|
|
||||||
use Co;
|
use Co;
|
||||||
|
use Doctrine\Common\Annotations\AnnotationException;
|
||||||
use Swoole\Http\Request;
|
use Swoole\Http\Request;
|
||||||
use Swoole\Runtime;
|
use Swoole\Runtime;
|
||||||
use Swoole\WebSocket\Frame;
|
use Swoole\WebSocket\Frame;
|
||||||
@@ -46,9 +47,7 @@ class FrameworkLoader
|
|||||||
echo "Phar mode: " . WORKING_DIR . PHP_EOL;
|
echo "Phar mode: " . WORKING_DIR . PHP_EOL;
|
||||||
}
|
}
|
||||||
$this->registerAutoloader('classLoader');
|
$this->registerAutoloader('classLoader');
|
||||||
Runtime::enableCoroutine();
|
Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL);
|
||||||
|
|
||||||
|
|
||||||
self::$settings = new GlobalConfig();
|
self::$settings = new GlobalConfig();
|
||||||
ZMBuf::$globals = self::$settings;
|
ZMBuf::$globals = self::$settings;
|
||||||
if (!self::$settings->success) die("Failed to load global config. Please check config/global.php file");
|
if (!self::$settings->success) die("Failed to load global config. Please check config/global.php file");
|
||||||
@@ -95,7 +94,7 @@ class FrameworkLoader
|
|||||||
", port: " . self::$settings->get("port") .
|
", port: " . self::$settings->get("port") .
|
||||||
", log_level: " . ZMBuf::$atomics["info_level"]->get() .
|
", log_level: " . ZMBuf::$atomics["info_level"]->get() .
|
||||||
", version: " . json_decode(file_get_contents(WORKING_DIR . "/composer.json"), true)["version"] .
|
", version: " . json_decode(file_get_contents(WORKING_DIR . "/composer.json"), true)["version"] .
|
||||||
"\nworking_dir: ".(isPharMode() ? realpath('.') : WORKING_DIR)
|
"\nworking_dir: " . (isPharMode() ? realpath('.') : WORKING_DIR)
|
||||||
);
|
);
|
||||||
global $motd;
|
global $motd;
|
||||||
echo $motd . PHP_EOL;
|
echo $motd . PHP_EOL;
|
||||||
@@ -141,6 +140,11 @@ class FrameworkLoader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Swoole\Server $server
|
||||||
|
* @param $worker_id
|
||||||
|
* @throws AnnotationException
|
||||||
|
*/
|
||||||
public function onWorkerStart(\Swoole\Server $server, $worker_id) {
|
public function onWorkerStart(\Swoole\Server $server, $worker_id) {
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
self::$run_time = microtime(true);
|
self::$run_time = microtime(true);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class Hello extends ModBase
|
|||||||
/**
|
/**
|
||||||
* 默认示例页面
|
* 默认示例页面
|
||||||
* @RequestMapping("/index")
|
* @RequestMapping("/index")
|
||||||
|
* @RequestMapping("/")
|
||||||
*/
|
*/
|
||||||
public function index() {
|
public function index() {
|
||||||
return "Hello Zhamao!";
|
return "Hello Zhamao!";
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
namespace ZM\DB;
|
namespace ZM\DB;
|
||||||
|
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use framework\Console;
|
use framework\Console;
|
||||||
use framework\ZMBuf;
|
use framework\ZMBuf;
|
||||||
|
use PDOStatement;
|
||||||
use Swoole\Coroutine;
|
use Swoole\Coroutine;
|
||||||
use Swoole\Coroutine\MySQL\Statement;
|
|
||||||
use ZM\Exception\DbException;
|
use ZM\Exception\DbException;
|
||||||
|
|
||||||
class DB
|
class DB
|
||||||
@@ -16,8 +17,10 @@ class DB
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws DbException
|
* @throws DbException
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static function initTableList() {
|
public static function initTableList() {
|
||||||
|
if (!extension_loaded("mysqlnd")) throw new Exception("Can not find mysqlnd PHP extension.");
|
||||||
$result = self::rawQuery("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='" . ZMBuf::globals("sql_config")["sql_database"] . "';", []);
|
$result = self::rawQuery("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='" . ZMBuf::globals("sql_config")["sql_database"] . "';", []);
|
||||||
foreach ($result as $v) {
|
foreach ($result as $v) {
|
||||||
self::$table_list[] = $v['TABLE_NAME'];
|
self::$table_list[] = $v['TABLE_NAME'];
|
||||||
@@ -99,11 +102,10 @@ class DB
|
|||||||
}
|
}
|
||||||
$ps = $conn->prepare($line);
|
$ps = $conn->prepare($line);
|
||||||
if ($ps === false) {
|
if ($ps === false) {
|
||||||
$conn->close();
|
|
||||||
ZMBuf::$sql_pool->connect_cnt -= 1;
|
ZMBuf::$sql_pool->connect_cnt -= 1;
|
||||||
throw new DbException("SQL语句查询错误," . $line . ",错误信息:" . $conn->error);
|
throw new DbException("SQL语句查询错误," . $line . ",错误信息:" . $conn->error);
|
||||||
} else {
|
} else {
|
||||||
if (!($ps instanceof Statement)) {
|
if (!($ps instanceof PDOStatement)) {
|
||||||
throw new DbException("语句查询错误!" . $line);
|
throw new DbException("语句查询错误!" . $line);
|
||||||
}
|
}
|
||||||
if ($params == []) $result = $ps->execute();
|
if ($params == []) $result = $ps->execute();
|
||||||
@@ -111,8 +113,8 @@ class DB
|
|||||||
$result = $ps->execute([$params]);
|
$result = $ps->execute([$params]);
|
||||||
} else $result = $ps->execute($params);
|
} else $result = $ps->execute($params);
|
||||||
ZMBuf::$sql_pool->put($conn);
|
ZMBuf::$sql_pool->put($conn);
|
||||||
if ($ps->errno != 0) {
|
if ($result !== true) {
|
||||||
throw new DBException("语句[$line]错误!" . $ps->error);
|
throw new DBException("语句[$line]错误!" . $ps->errorInfo()[2]);
|
||||||
//echo json_encode(debug_backtrace(), 128 | 256);
|
//echo json_encode(debug_backtrace(), 128 | 256);
|
||||||
}
|
}
|
||||||
if (ZMBuf::get("sql_log") === true) {
|
if (ZMBuf::get("sql_log") === true) {
|
||||||
@@ -122,7 +124,7 @@ class DB
|
|||||||
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . "\n";
|
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . "\n";
|
||||||
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
||||||
}
|
}
|
||||||
return $result;
|
return $ps->fetchAll();
|
||||||
}
|
}
|
||||||
} catch (DBException $e) {
|
} catch (DBException $e) {
|
||||||
if (ZMBuf::get("sql_log") === true) {
|
if (ZMBuf::get("sql_log") === true) {
|
||||||
@@ -133,6 +135,7 @@ class DB
|
|||||||
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
||||||
}
|
}
|
||||||
Console::warning($e->getMessage());
|
Console::warning($e->getMessage());
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class SelectBody
|
|||||||
if ($this->table->isCacheEnabled()) {
|
if ($this->table->isCacheEnabled()) {
|
||||||
$rr = md5(implode(",", $this->select_thing) . serialize($this->where_thing));
|
$rr = md5(implode(",", $this->select_thing) . serialize($this->where_thing));
|
||||||
if (array_key_exists($rr, $this->table->cache)) {
|
if (array_key_exists($rr, $this->table->cache)) {
|
||||||
Console::info('SQL query cached: ' . $rr, date("[H:i:s ") . 'DB] ');
|
Console::debug('SQL query cached: ' . $rr);
|
||||||
return $this->table->cache[$rr]->getResult();
|
return $this->table->cache[$rr]->getResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,12 @@ class EventHandler
|
|||||||
/** @var Server $param0 */
|
/** @var Server $param0 */
|
||||||
$conn = ConnectionManager::get($param1->fd);
|
$conn = ConnectionManager::get($param1->fd);
|
||||||
set_coroutine_params(["server" => $param0, "frame" => $param1, "connection" => $conn]);
|
set_coroutine_params(["server" => $param0, "frame" => $param1, "connection" => $conn]);
|
||||||
(new MessageEvent($param0, $param1))->onActivate()->onAfter();
|
try {
|
||||||
|
(new MessageEvent($param0, $param1))->onActivate()->onAfter();
|
||||||
|
} catch (Error $e) {
|
||||||
|
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
|
||||||
|
Console::error("Fatal error when calling $event_name: " . $error_msg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "request":
|
case "request":
|
||||||
try {
|
try {
|
||||||
@@ -78,15 +83,37 @@ class EventHandler
|
|||||||
if (!$param1->isEnd()) $param1->end("Internal server error: " . $e->getMessage());
|
if (!$param1->isEnd()) $param1->end("Internal server error: " . $e->getMessage());
|
||||||
Console::error("Internal server error (500), caused by uncaught exception.");
|
Console::error("Internal server error (500), caused by uncaught exception.");
|
||||||
Console::log($e->getTraceAsString(), "gray");
|
Console::log($e->getTraceAsString(), "gray");
|
||||||
|
} catch (Error $e) {
|
||||||
|
/** @var Response $param1 */
|
||||||
|
$param1->status(500);
|
||||||
|
Console::info($param0->server["remote_addr"] . ":" . $param0->server["remote_port"] .
|
||||||
|
" [" . $param1->getStatusCode() . "] " . $param0->server["request_uri"]
|
||||||
|
);
|
||||||
|
$doc = "Internal server error<br>";
|
||||||
|
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
|
||||||
|
if (ZMBuf::$atomics["info_level"]->get() >= 4) $doc .= $error_msg;
|
||||||
|
if (!$param1->isEnd()) $param1->end($doc);
|
||||||
|
Console::error("Internal server error (500): " . $error_msg);
|
||||||
|
Console::log($e->getTraceAsString(), "gray");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "open":
|
case "open":
|
||||||
set_coroutine_params(["server" => $param0, "request" => $param1]);
|
set_coroutine_params(["server" => $param0, "request" => $param1]);
|
||||||
(new WSOpenEvent($param0, $param1))->onActivate()->onAfter();
|
try {
|
||||||
|
(new WSOpenEvent($param0, $param1))->onActivate()->onAfter();
|
||||||
|
} catch (Error $e) {
|
||||||
|
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
|
||||||
|
Console::error("Fatal error when calling $event_name: " . $error_msg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "close":
|
case "close":
|
||||||
set_coroutine_params(["server" => $param0, "fd" => $param1]);
|
set_coroutine_params(["server" => $param0, "fd" => $param1]);
|
||||||
(new WSCloseEvent($param0, $param1))->onActivate()->onAfter();
|
try {
|
||||||
|
(new WSCloseEvent($param0, $param1))->onActivate()->onAfter();
|
||||||
|
} catch (Error $e) {
|
||||||
|
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
|
||||||
|
Console::error("Fatal error when calling $event_name: " . $error_msg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Console::info(Console::setColor("Event: " . $event_name . " 运行了 " . round(microtime(true) - $starttime, 5) . " 秒", "gold"));
|
//Console::info(Console::setColor("Event: " . $event_name . " 运行了 " . round(microtime(true) - $starttime, 5) . " 秒", "gold"));
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class MessageEvent implements SwooleEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Console::warning("Websocket message event exception: " . $e->getMessage());
|
Console::warning("Websocket message event exception: " . (($cs = $e->getMessage()) == "" ? get_class($e) : $cs));
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
//加载phar包
|
//加载phar包
|
||||||
Console::info("加载外部phar包中");
|
Console::info("加载外部phar包中");
|
||||||
$dir = DataProvider::getWorkingDir() . "/resources/package/";
|
$dir = DataProvider::getWorkingDir() . "/resources/package/";
|
||||||
|
if (version_compare(SWOOLE_VERSION, "4.4.0", ">=")) Timer::clearAll();
|
||||||
if (is_dir($dir)) {
|
if (is_dir($dir)) {
|
||||||
$list = scandir($dir);
|
$list = scandir($dir);
|
||||||
unset($list[0], $list[1]);
|
unset($list[0], $list[1]);
|
||||||
@@ -147,7 +148,7 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
Console::info("加载composer资源中");
|
Console::info("加载composer资源中");
|
||||||
require_once DataProvider::getWorkingDir() . "/vendor/autoload.php";
|
require_once DataProvider::getWorkingDir() . "/vendor/autoload.php";
|
||||||
} else {
|
} else {
|
||||||
if(isPharMode()) require_once WORKING_DIR . "/vendor/autoload.php";
|
if (isPharMode()) require_once WORKING_DIR . "/vendor/autoload.php";
|
||||||
}
|
}
|
||||||
|
|
||||||
//加载各个模块的注解类,以及反射
|
//加载各个模块的注解类,以及反射
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace ZM\Utils;
|
|||||||
|
|
||||||
use framework\Console;
|
use framework\Console;
|
||||||
use framework\ZMBuf;
|
use framework\ZMBuf;
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
use SplQueue;
|
use SplQueue;
|
||||||
use Swoole\Coroutine;
|
use Swoole\Coroutine;
|
||||||
use Swoole\Coroutine\Mysql;
|
use Swoole\Coroutine\Mysql;
|
||||||
@@ -48,11 +50,11 @@ class SQLPool
|
|||||||
/**
|
/**
|
||||||
* 获取队中的连接,如果不存在则创建新的
|
* 获取队中的连接,如果不存在则创建新的
|
||||||
* @param bool $no_new_conn
|
* @param bool $no_new_conn
|
||||||
* @return bool|mixed|Mysql
|
* @return bool|mixed|PDO
|
||||||
*/
|
*/
|
||||||
public function get($no_new_conn = false) {
|
public function get($no_new_conn = false) {
|
||||||
if (count($this->pool) == 0 && $this->connect_cnt <= 70) {
|
if (count($this->pool) == 0 && $this->connect_cnt <= 70) {
|
||||||
if($no_new_conn) return false;
|
if ($no_new_conn) return false;
|
||||||
$this->connect_cnt += 1;
|
$this->connect_cnt += 1;
|
||||||
$r = $this->newConnect();
|
$r = $this->newConnect();
|
||||||
if ($r !== false) {
|
if ($r !== false) {
|
||||||
@@ -62,11 +64,12 @@ class SQLPool
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} elseif (count($this->pool) > 0) {
|
} elseif (count($this->pool) > 0) {
|
||||||
|
/** @var PDO $con */
|
||||||
$con = $this->pool->pop();
|
$con = $this->pool->pop();
|
||||||
if ($con->connected !== false) return $con;
|
return $con;
|
||||||
} elseif ($this->connect_cnt > 70) {
|
} elseif ($this->connect_cnt > 70) {
|
||||||
$this->co_list[]=Coroutine::getuid();
|
$this->co_list[] = Coroutine::getuid();
|
||||||
Console::warning("数据库连接过多,协程等待重复利用中...当前协程数 ".Coroutine::stats()["coroutine_num"]);
|
Console::warning("数据库连接过多,协程等待重复利用中...当前协程数 " . Coroutine::stats()["coroutine_num"]);
|
||||||
Coroutine::suspend();
|
Coroutine::suspend();
|
||||||
return $this->get($no_new_conn);
|
return $this->get($no_new_conn);
|
||||||
}
|
}
|
||||||
@@ -88,14 +91,14 @@ class SQLPool
|
|||||||
private function newConnect() {
|
private function newConnect() {
|
||||||
//无空闲连接,创建新连接
|
//无空闲连接,创建新连接
|
||||||
$mysql = new Mysql();
|
$mysql = new Mysql();
|
||||||
|
$dsn = "mysql:host=" . $this->info["host"] . ";dbname=" . $this->info["database"];
|
||||||
Console::info("创建SQL连接中,当前有" . $this->connect_cnt . "个连接");
|
try {
|
||||||
$res = $mysql->connect($this->info);
|
$mysql = new PDO($dsn, $this->info["user"], $this->info["password"], array(PDO::ATTR_PERSISTENT => true));
|
||||||
if ($res == false) {
|
} catch (PDOException $e) {
|
||||||
echo $mysql->error . PHP_EOL;
|
Console::error("PDO Error: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return $mysql;
|
|
||||||
}
|
}
|
||||||
|
Console::info("创建SQL连接中,当前有" . $this->connect_cnt . "个连接");
|
||||||
|
return $mysql;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user