From f677b0e1320360e1951efba6a88283b72445382c Mon Sep 17 00:00:00 2001 From: jerry Date: Mon, 15 Feb 2021 15:15:26 +0800 Subject: [PATCH] update to 2.2.5 version add saveToJson and loadFromJson function for DataProvider.php fix @OnSave annotation not working adjust swoole timer tick add hasKey() for WorkerCache.php --- composer.json | 2 +- docs/component/cqcode.md | 14 ++++++++++++++ src/ZM/Event/EventManager.php | 9 +++++++++ src/ZM/Event/ServerEventHandler.php | 9 +++++++++ src/ZM/Store/LightCache.php | 16 +++++++++++++++- src/ZM/Store/WorkerCache.php | 10 ++++++++++ src/ZM/Utils/DataProvider.php | 26 ++++++++++++++++++++++++++ src/ZM/global_functions.php | 12 ++++++++---- 8 files changed, 92 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index cba88b5f..8808cd16 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "High performance QQ robot and web server development framework", "minimum-stability": "stable", "license": "Apache-2.0", - "version": "2.2.4", + "version": "2.2.5", "extra": { "exclude_annotate": [ "src/ZM" diff --git a/docs/component/cqcode.md b/docs/component/cqcode.md index 3d731f77..6a898826 100644 --- a/docs/component/cqcode.md +++ b/docs/component/cqcode.md @@ -111,6 +111,20 @@ $str = CQ::removeCQ("[CQ:at,qq=all]这是带表情的全体消息[CQ:face,id=8]" // $str: "这是带表情的全体消息" ``` +### CQ::getCQ() + +解析CQ码。 + +- 参数:`getCQ($msg);`:要解析出 CQ 码的消息。 +- 返回:`数组 | null`,见下表 + +| 键名 | 说明 | +| ------ | ------------------------------------------------------------ | +| type | CQ码类型,比如 `[CQ:at]` 中的 `at` | +| params | 参数列表,比如 `[CQ:image,file=123.jpg,url=http://a.com/a.jpg]`,params 为 `["file" => "123","url" => "http://a.com/a.jpg"]` | +| start | 此 CQ 码在字符串中的起始位置 | +| end | 此 CQ 码在字符串中的结束位置 | + ## CQ 码列表 ### CQ::face() - 发送 QQ 表情 diff --git a/src/ZM/Event/EventManager.php b/src/ZM/Event/EventManager.php index beaac370..221b649a 100644 --- a/src/ZM/Event/EventManager.php +++ b/src/ZM/Event/EventManager.php @@ -9,8 +9,11 @@ use Exception; use Swoole\Timer; use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationParser; +use ZM\Annotation\Swoole\OnSave; use ZM\Annotation\Swoole\OnTick; +use ZM\Config\ZMConfig; use ZM\Console\Console; +use ZM\Store\LightCache; use ZM\Store\ZMAtomic; class EventManager @@ -59,5 +62,11 @@ class EventManager } }); } + $conf = ZMConfig::get("global", "worker_cache") ?? ["worker" => 0]; + if (server()->worker_id == $conf["worker"]) { + zm_timer_tick(ZMConfig::get("global", "light_cache")["auto_save_interval"] * 1000, function () { + LightCache::savePersistence(); + }); + } } } diff --git a/src/ZM/Event/ServerEventHandler.php b/src/ZM/Event/ServerEventHandler.php index fa26e465..0375d56c 100644 --- a/src/ZM/Event/ServerEventHandler.php +++ b/src/ZM/Event/ServerEventHandler.php @@ -41,6 +41,7 @@ use ZM\Exception\InterruptException; use ZM\Framework; use ZM\Http\Response; use ZM\Module\QQBot; +use ZM\Store\LightCache; use ZM\Store\LightCacheInside; use ZM\Store\MySQL\SqlPoolStorage; use ZM\Store\Redis\ZMRedisPool; @@ -121,6 +122,9 @@ class ServerEventHandler * @param $worker_id */ public function onWorkerStop(Server $server, $worker_id) { + if ($worker_id == (ZMConfig::get("worker_cache")["worker"] ?? 0)) { + LightCache::savePersistence(); + } Console::debug(($server->taskworker ? "Task" : "") . "Worker #$worker_id 已停止"); } @@ -533,6 +537,11 @@ class ServerEventHandler $action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r]; $server->sendMessage(json_encode($action, 256), $src_worker_id); break; + case "hasKeyWorkerCache": + $r = WorkerCache::hasKey($data["key"], $data["subkey"]); + $action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r]; + $server->sendMessage(json_encode($action, 256), $src_worker_id); + break; case "asyncAddWorkerCache": WorkerCache::add($data["key"], $data["value"], true); break; diff --git a/src/ZM/Store/LightCache.php b/src/ZM/Store/LightCache.php index d2c499e0..373b6bc7 100644 --- a/src/ZM/Store/LightCache.php +++ b/src/ZM/Store/LightCache.php @@ -6,7 +6,10 @@ namespace ZM\Store; use Exception; use Swoole\Table; +use ZM\Annotation\Swoole\OnSave; +use ZM\Config\ZMConfig; use ZM\Console\Console; +use ZM\Event\EventDispatcher; use ZM\Exception\ZMException; class LightCache @@ -175,7 +178,16 @@ class LightCache return $r; } - public static function savePersistence() { + public static function savePersistence($only_worker = false) { + + // 下面将OnSave激活一下 + if (server()->worker_id == (ZMConfig::get("global", "worker_cache")["worker"] ?? 0)) { + $dispatcher = new EventDispatcher(OnSave::class); + $dispatcher->dispatchEvents(); + } + + if($only_worker) return; + if (self::$kv_table === null) return; $r = []; foreach (self::$kv_table as $k => $v) { @@ -189,6 +201,8 @@ class LightCache $r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256)); if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!"); } + + } private static function checkExpire($key) { diff --git a/src/ZM/Store/WorkerCache.php b/src/ZM/Store/WorkerCache.php index 7e7bd2d6..023ff69a 100644 --- a/src/ZM/Store/WorkerCache.php +++ b/src/ZM/Store/WorkerCache.php @@ -39,6 +39,16 @@ class WorkerCache } } + public static function hasKey($key, $subkey) { + $config = self::$config ?? ZMConfig::get("global", "worker_cache") ?? ["worker" => 0]; + if ($config["worker"] === server()->worker_id) { + return isset(self::$store[$key][$subkey]); + } else { + $action = ["hasKeyWorkerCache", "key" => $key, "subkey" => $subkey, "cid" => zm_cid()]; + return self::processRemote($action, false, $config); + } + } + private static function processRemote($action, $async, $config) { $ss = server()->sendMessage(json_encode($action, JSON_UNESCAPED_UNICODE), $config["worker"]); if (!$ss) return false; diff --git a/src/ZM/Utils/DataProvider.php b/src/ZM/Utils/DataProvider.php index 1d416bf0..ccfc6981 100644 --- a/src/ZM/Utils/DataProvider.php +++ b/src/ZM/Utils/DataProvider.php @@ -5,6 +5,7 @@ namespace ZM\Utils; use ZM\Config\ZMConfig; +use ZM\Console\Console; class DataProvider { @@ -28,4 +29,29 @@ class DataProvider public static function getDataFolder() { return ZM_DATA; } + + public static function saveToJson($filename, $file_array) { + $path = ZMConfig::get("global", "config_dir"); + $r = explode("/", $filename); + if(count($r) == 2) { + $path = $path . $r[0]."/"; + if(!is_dir($path)) mkdir($path); + $name = $r[1]; + } elseif (count($r) != 1) { + Console::warning("存储失败,文件名只能有一级目录"); + return false; + } else { + $name = $r[0]; + } + return file_put_contents($path.$name.".json", json_encode($file_array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + } + + public static function loadFromJson($filename) { + $path = ZMConfig::get("global", "config_dir"); + if(file_exists($path.$filename.".json")) { + return json_decode(file_get_contents($path.$filename.".json"), true); + } else { + return null; + } + } } diff --git a/src/ZM/global_functions.php b/src/ZM/global_functions.php index 83cd8cd4..25954b65 100644 --- a/src/ZM/global_functions.php +++ b/src/ZM/global_functions.php @@ -267,10 +267,14 @@ function zm_timer_after($ms, callable $callable) { } function zm_timer_tick($ms, callable $callable) { - go(function () use ($ms, $callable) { - Console::debug("Adding extra timer tick of " . $ms . " ms"); - Swoole\Timer::tick($ms, $callable); - }); + if (zm_cid() === -1) { + return go(function () use ($ms, $callable) { + Console::debug("Adding extra timer tick of " . $ms . " ms"); + Swoole\Timer::tick($ms, $callable); + }); + } else { + return Swoole\Timer::tick($ms, $callable); + } } function zm_data_hash($v) {