diff --git a/docs/update/v2.md b/docs/update/v2.md
index 7abf8a9c..cfb23bf4 100644
--- a/docs/update/v2.md
+++ b/docs/update/v2.md
@@ -1,5 +1,14 @@
# 更新日志(v2 版本)
+## v2.2.2
+
+> 更新时间:2021.1.29
+
+- 修复:模块文件错误时避免循环报错
+- 优化:代码结构
+- 修复:在不同进程时调用机器人 API 无法返回且报错的 bug
+- **修复:机器人无法连接的问题(2.1.6 ~ 2.2.1 受影响)**
+
## v2.2.1
> 更新时间:2021.1.29
diff --git a/src/Custom/Command/CustomCommand.php b/src/Custom/Command/CustomCommand.php
deleted file mode 100644
index 9fe702f4..00000000
--- a/src/Custom/Command/CustomCommand.php
+++ /dev/null
@@ -1,31 +0,0 @@
-setDescription("custom description | 自定义命令的描述字段");
- $this->addOption("failure", null, null, "以错误码为1返回结果");
- // ...
- }
-
- protected function execute(InputInterface $input, OutputInterface $output) {
- if ($input->getOption("failure")) {
- $output->writeln("Hello error! I am wrong message.");
- return Command::FAILURE;
- } else {
- $output->writeln("Hello world! I am successful message.");
- return Command::SUCCESS;
- }
- }
-}
diff --git a/src/Custom/global_function.php b/src/Custom/global_function.php
index 3965f5ba..471470ee 100644
--- a/src/Custom/global_function.php
+++ b/src/Custom/global_function.php
@@ -1,4 +1,4 @@
- $reply,
"time" => microtime(true),
- "self_id" => $connection->getOption("connect_id")
+ "self_id" => $connection->getOption("connect_id"),
+ "echo" => $api_id
];
- if ($function === true) $r[$api_id]["coroutine"] = Co::getuid();
LightCacheInside::set("wait_api", "wait_api", $r);
SpinLock::unlock("wait_api");
if (server()->push($connection->getFd(), json_encode($reply))) {
if ($function === true) {
- Co::suspend();
+ return CoMessage::yieldByWS($r[$api_id], ["echo"], 60);
+ } else {
SpinLock::lock("wait_api");
$r = LightCacheInside::get("wait_api", "wait_api");
- $data = $r[$api_id];
unset($r[$api_id]);
LightCacheInside::set("wait_api", "wait_api", $r);
SpinLock::unlock("wait_api");
- return isset($data['result']) ? $data['result'] : null;
}
return true;
} else {
diff --git a/src/ZM/API/ZMRobot.php b/src/ZM/API/ZMRobot.php
index 45230948..027fe0ac 100644
--- a/src/ZM/API/ZMRobot.php
+++ b/src/ZM/API/ZMRobot.php
@@ -228,9 +228,9 @@ class ZMRobot
/**
* 群组单人禁言
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_ban-%E7%BE%A4%E7%BB%84%E5%8D%95%E4%BA%BA%E7%A6%81%E8%A8%80
- * @param int $group_id
- * @param int $user_id
- * @param int $duration
+ * @param $group_id
+ * @param $user_id
+ * @param $duration
* @return array|bool|null
*/
public function setGroupBan($group_id, $user_id, $duration = 1800) {
diff --git a/src/ZM/Annotation/AnnotationParser.php b/src/ZM/Annotation/AnnotationParser.php
index ff0d443b..56e19158 100644
--- a/src/ZM/Annotation/AnnotationParser.php
+++ b/src/ZM/Annotation/AnnotationParser.php
@@ -90,6 +90,7 @@ class AnnotationParser
if ($vs instanceof ErgodicAnnotation) {
foreach (($this->annotation_map[$v]["methods"] ?? []) as $method) {
$copy = clone $vs;
+ /** @noinspection PhpUndefinedFieldInspection */
$copy->method = $method->getName();
$this->annotation_map[$v]["methods_annotations"][$method->getName()][] = $copy;
}
diff --git a/src/ZM/DB/DB.php b/src/ZM/DB/DB.php
index 0dd1c35d..8e42e03d 100644
--- a/src/ZM/DB/DB.php
+++ b/src/ZM/DB/DB.php
@@ -31,7 +31,6 @@ class DB
/**
* @param $table_name
- * @param bool $enable_cache
* @return Table
* @throws DbException
*/
@@ -95,6 +94,7 @@ class DB
$ps = $conn->prepare($line);
if ($ps === false) {
SqlPoolStorage::$sql_pool->put(null);
+ /** @noinspection PhpUndefinedFieldInspection */
throw new DbException("SQL语句查询错误," . $line . ",错误信息:" . $conn->error);
} else {
if (!($ps instanceof PDOStatement) && !($ps instanceof PDOStatementProxy)) {
diff --git a/src/ZM/DB/Table.php b/src/ZM/DB/Table.php
index 939bc8ad..5cf4d0a4 100644
--- a/src/ZM/DB/Table.php
+++ b/src/ZM/DB/Table.php
@@ -47,7 +47,7 @@ class Table
return new DeleteBody($this);
}
- public function statement($line){
+ public function statement(){
$this->cache = [];
//TODO: 无返回的statement语句
}
diff --git a/src/ZM/Event/EventDispatcher.php b/src/ZM/Event/EventDispatcher.php
index 4781cff7..16869701 100644
--- a/src/ZM/Event/EventDispatcher.php
+++ b/src/ZM/Event/EventDispatcher.php
@@ -87,7 +87,6 @@ class EventDispatcher
/**
* @param mixed ...$params
* @throws Exception
- * @throws InterruptException
*/
public function dispatchEvents(...$params) {
try {
diff --git a/src/ZM/Event/ServerEventHandler.php b/src/ZM/Event/ServerEventHandler.php
index 4d3f0d9f..d2cbb7ae 100644
--- a/src/ZM/Event/ServerEventHandler.php
+++ b/src/ZM/Event/ServerEventHandler.php
@@ -74,17 +74,17 @@ class ServerEventHandler
}
Process::signal(SIGINT, function () use ($r) {
echo "\r";
- Console::warning("Server interrupted by keyboard on Master.");
+ Console::warning("Server interrupted(SIGINT) on Master.");
if ((Framework::$server->inotify ?? null) !== null)
/** @noinspection PhpUndefinedFieldInspection */ Event::del(Framework::$server->inotify);
ZMUtil::stop();
});
- if(Framework::$argv["daemon"]) {
+ if (Framework::$argv["daemon"]) {
$daemon_data = json_encode([
"pid" => \server()->master_pid,
"stdout" => ZMConfig::get("global")["swoole"]["log_file"]
- ],128|256);
- file_put_contents(DataProvider::getWorkingDir()."/.daemon_pid", $daemon_data);
+ ], 128 | 256);
+ file_put_contents(DataProvider::getWorkingDir() . "/.daemon_pid", $daemon_data);
}
if (Framework::$argv["watch"]) {
if (extension_loaded('inotify')) {
@@ -238,7 +238,7 @@ class ServerEventHandler
Console::error("PHP Error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine());
Console::error("Maybe it caused by your own code if in your own Module directory.");
Console::log($e->getTraceAsString(), 'gray');
- ZMUtil::stop();
+ posix_kill($server->master_pid, SIGINT);
}
} else {
// 这里是TaskWorker初始化的内容部分
@@ -255,7 +255,7 @@ class ServerEventHandler
Console::error("PHP Error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine());
Console::error("Maybe it caused by your own code if in your own Module directory.");
Console::log($e->getTraceAsString(), 'gray');
- ZMUtil::stop();
+ posix_kill($server->master_pid, SIGINT);
}
}
}
@@ -314,7 +314,7 @@ class ServerEventHandler
*/
public function onRequest(?Request $request, ?\Swoole\Http\Response $response) {
$response = new Response($response);
- foreach(ZMConfig::get("global")["http_header"] as $k => $v) {
+ foreach (ZMConfig::get("global")["http_header"] as $k => $v) {
$response->setHeader($k, $v);
}
unset(Context::$context[Co::getCid()]);
@@ -491,10 +491,10 @@ class ServerEventHandler
/**
* @SwooleHandler("pipeMessage")
- * @param $server
+ * @param Server $server
* @param $src_worker_id
* @param $data
- * @throws InterruptException
+ * @throws Exception
*/
public function onPipeMessage(Server $server, $src_worker_id, $data) {
//var_dump($data, $server->worker_id);
@@ -561,10 +561,11 @@ class ServerEventHandler
* @param Server|null $server
* @param Server\Task $task
* @return mixed
+ * @noinspection PhpUnusedParameterInspection
*/
public function onTask(?Server $server, Server\Task $task) {
$data = $task->data;
- switch($data["action"]) {
+ switch ($data["action"]) {
case "runMethod":
$c = $data["class"];
$ss = new $c();
diff --git a/src/ZM/Module/QQBot.php b/src/ZM/Module/QQBot.php
index 084ad444..e64923e4 100644
--- a/src/ZM/Module/QQBot.php
+++ b/src/ZM/Module/QQBot.php
@@ -3,7 +3,7 @@
namespace ZM\Module;
-use Swoole\Coroutine;
+use Exception;
use ZM\Annotation\CQ\CQAPIResponse;
use ZM\Annotation\CQ\CQBefore;
use ZM\Annotation\CQ\CQCommand;
@@ -14,8 +14,6 @@ use ZM\Annotation\CQ\CQRequest;
use ZM\Event\EventDispatcher;
use ZM\Exception\InterruptException;
use ZM\Exception\WaitTimeoutException;
-use ZM\Store\LightCacheInside;
-use ZM\Store\Lock\SpinLock;
use ZM\Utils\CoMessage;
/**
@@ -26,22 +24,25 @@ class QQBot
{
/**
* @throws InterruptException
+ * @throws Exception
*/
public function handle() {
try {
$data = json_decode(context()->getFrame()->data, true);
+ set_coroutine_params(["data" => $data]);
+ if (isset($data["echo"])) {
+ if (CoMessage::resumeByWS()) {
+ EventDispatcher::interrupt();
+ }
+ }
if (isset($data["post_type"])) {
//echo TermColor::ITALIC.json_encode($data, 128|256).TermColor::RESET.PHP_EOL;
- set_coroutine_params(["data" => $data]);
ctx()->setCache("level", 0);
//Console::debug("Calling CQ Event from fd=" . ctx()->getConnection()->getFd());
if ($data["post_type"] != "meta_event") {
$r = $this->dispatchBeforeEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志
if ($r->store === "block") EventDispatcher::interrupt();
}
- if (CoMessage::resumeByWS()) {
- EventDispatcher::interrupt();
- }
//Console::warning("最上数据包:".json_encode($data));
$this->dispatchEvents($data);
} else {
@@ -55,7 +56,7 @@ class QQBot
/**
* @param $data
* @return EventDispatcher
- * @throws InterruptException
+ * @throws Exception
*/
public function dispatchBeforeEvents($data) {
$before = new EventDispatcher(CQBefore::class);
@@ -177,45 +178,16 @@ class QQBot
}
}
+ /**
+ * @param $req
+ * @throws Exception
+ */
private function dispatchAPIResponse($req) {
- $status = $req["status"];
- $retcode = $req["retcode"];
- $data = $req["data"];
- if (isset($req["echo"]) && is_numeric($req["echo"])) {
- $r = LightCacheInside::get("wait_api", "wait_api");
- if (isset($r[$req["echo"]])) {
- $origin = $r[$req["echo"]];
- $self_id = $origin["self_id"];
- $response = [
- "status" => $status,
- "retcode" => $retcode,
- "data" => $data,
- "self_id" => $self_id,
- "echo" => $req["echo"]
- ];
- set_coroutine_params(["cq_response" => $response]);
- $dispatcher = new EventDispatcher(CQAPIResponse::class);
- $dispatcher->setRuleFunction(function (CQAPIResponse $response) {
- return $response->retcode == ctx()->getCQResponse()["retcode"];
- });
- $dispatcher->dispatchEvents($response);
-
- $origin_ctx = ctx()->copy();
- set_coroutine_params($origin_ctx);
- if (($origin["coroutine"] ?? false) !== false) {
- SpinLock::lock("wait_api");
- $r = LightCacheInside::get("wait_api", "wait_api");
- $r[$req["echo"]]["result"] = $response;
- LightCacheInside::set("wait_api", "wait_api", $r);
- SpinLock::unlock("wait_api");
- Coroutine::resume($origin['coroutine']);
- }
- SpinLock::lock("wait_api");
- $r = LightCacheInside::get("wait_api", "wait_api");
- unset($r[$req["echo"]]);
- LightCacheInside::set("wait_api", "wait_api", $r);
- SpinLock::unlock("wait_api");
- }
- }
+ set_coroutine_params(["cq_response" => $req]);
+ $dispatcher = new EventDispatcher(CQAPIResponse::class);
+ $dispatcher->setRuleFunction(function (CQAPIResponse $response) {
+ return $response->retcode == ctx()->getCQResponse()["retcode"];
+ });
+ $dispatcher->dispatchEvents($req);
}
}
diff --git a/src/ZM/Store/LightCacheInside.php b/src/ZM/Store/LightCacheInside.php
index c161eca0..1745bb46 100644
--- a/src/ZM/Store/LightCacheInside.php
+++ b/src/ZM/Store/LightCacheInside.php
@@ -23,9 +23,10 @@ class LightCacheInside
$result = self::$kv_table["wait_api"]->create() && self::$kv_table["connect"]->create();
if ($result === false) {
self::$last_error = '系统内存不足,申请失败';
- return $result;
+ return false;
+ } else {
+ return true;
}
- return $result;
}
/**
diff --git a/src/ZM/Store/WorkerCache.php b/src/ZM/Store/WorkerCache.php
index 85803ce8..4cb68054 100644
--- a/src/ZM/Store/WorkerCache.php
+++ b/src/ZM/Store/WorkerCache.php
@@ -35,15 +35,19 @@ class WorkerCache
return true;
} else {
$action = ["action" => $async ? "asyncSetWorkerCache" : "setWorkerCache", "key" => $key, "value" => $value, "cid" => zm_cid()];
- $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]);
- if(!$ss) return false;
- if ($async) return true;
- zm_yield();
- $p = self::$transfer[zm_cid()] ?? null;
- unset(self::$transfer[zm_cid()]);
- return $p;
+ return self::processRemote($action, $async, $config);
}
}
+
+ private static function processRemote($action, $async, $config) {
+ $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]);
+ if(!$ss) return false;
+ if ($async) return true;
+ zm_yield();
+ $p = self::$transfer[zm_cid()] ?? null;
+ unset(self::$transfer[zm_cid()]);
+ return $p;
+ }
public static function unset($key, $async = false) {
$config = self::$config ?? ZMConfig::get("global", "worker_cache");
@@ -52,13 +56,7 @@ class WorkerCache
return true;
} else {
$action = ["action" => $async ? "asyncUnsetWorkerCache" : "unsetWorkerCache", "key" => $key, "cid" => zm_cid()];
- $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]);
- if(!$ss) return false;
- if ($async) return true;
- zm_yield();
- $p = self::$transfer[zm_cid()] ?? null;
- unset(self::$transfer[zm_cid()]);
- return $p;
+ return self::processRemote($action, $async, $config);
}
}
@@ -70,13 +68,7 @@ class WorkerCache
return true;
} else {
$action = ["action" => $async ? "asyncAddWorkerCache" : "addWorkerCache", "key" => $key, "value" => $value, "cid" => zm_cid()];
- $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]);
- // if(!$ss) return false;
- if ($async) return true;
- zm_yield();
- $p = self::$transfer[zm_cid()] ?? null;
- unset(self::$transfer[zm_cid()]);
- return $p;
+ return self::processRemote($action, $async, $config);
}
}
@@ -88,13 +80,7 @@ class WorkerCache
return true;
} else {
$action = ["action" => $async ? "asyncSubWorkerCache" : "subWorkerCache", "key" => $key, "value" => $value, "cid" => zm_cid()];
- $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]);
- // if(!$ss) return false;
- if ($async) return true;
- zm_yield();
- $p = self::$transfer[zm_cid()] ?? null;
- unset(self::$transfer[zm_cid()]);
- return $p;
+ return self::processRemote($action, $async, $config);
}
}
}
\ No newline at end of file
diff --git a/src/ZM/Utils/CoMessage.php b/src/ZM/Utils/CoMessage.php
index 637f56f7..3f150086 100644
--- a/src/ZM/Utils/CoMessage.php
+++ b/src/ZM/Utils/CoMessage.php
@@ -16,7 +16,7 @@ class CoMessage
* @param array $hang
* @param array $compare
* @param int $timeout
- * @return bool
+ * @return mixed
* @throws Exception
*/
public static function yieldByWS(array $hang, array $compare, $timeout = 600) {
@@ -57,7 +57,8 @@ class CoMessage
foreach ($all as $k => $v) {
if(!isset($v["compare"])) continue;
foreach ($v["compare"] as $vs) {
- if ($v[$vs] != ($dat[$vs] ?? null)) {
+ if (!isset($v[$vs], $dat[$vs])) continue 2;
+ if ($v[$vs] != $dat[$vs]) {
continue 2;
}
}
@@ -68,7 +69,7 @@ class CoMessage
LightCacheInside::set("wait_api", "wait_api", $all);
SpinLock::unlock("wait_api");
if ($all[$last]["worker_id"] != server()->worker_id) {
- ZMUtil::sendActionToWorker($all[$k]["worker_id"], "resume_ws_message", $all[$last]);
+ ZMUtil::sendActionToWorker($all[$last]["worker_id"], "resume_ws_message", $all[$last]);
} else {
Co::resume($all[$last]["coroutine"]);
}
diff --git a/src/ZM/global_functions.php b/src/ZM/global_functions.php
index ba10c519..cecac665 100644
--- a/src/ZM/global_functions.php
+++ b/src/ZM/global_functions.php
@@ -24,6 +24,7 @@ function phar_classloader($p) {
return;
}
try {
+ /** @noinspection PhpIncludeInspection */
require_once $filepath;
} catch (Exception $e) {
echo "Error when finding class: " . $p . PHP_EOL;
@@ -75,7 +76,7 @@ function unicode_decode($str) {
/**
* 获取模块文件夹下的每个类文件的类名称
* @param $dir
- * @param string $indoor_name
+ * @param $indoor_name
* @return array
*/
function getAllClasses($dir, $indoor_name) {
@@ -95,6 +96,7 @@ function getAllClasses($dir, $indoor_name) {
continue 2;
}
}
+ if ($v == "global_function.php") continue;
$class_name = $indoor_name . "\\" . mb_substr($v, 0, -4);
$classes [] = $class_name;
}