mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-23 00:25:35 +08:00
update to 2.5.0-b1 (build 408)
This commit is contained in:
115
src/ZM/Utils/Manager/ModuleManager.php
Normal file
115
src/ZM/Utils/Manager/ModuleManager.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use ZM\Console\Console;
|
||||
use ZM\Exception\ModulePackException;
|
||||
use ZM\Exception\ZMException;
|
||||
use ZM\Module\ModulePacker;
|
||||
use ZM\Module\ModuleUnpacker;
|
||||
use ZM\Utils\DataProvider;
|
||||
|
||||
/**
|
||||
* 模块管理器,负责打包解包模块
|
||||
* Class ModuleManager
|
||||
* @package ZM\Utils\Manager
|
||||
* @since 2.5
|
||||
*/
|
||||
class ModuleManager
|
||||
{
|
||||
|
||||
/**
|
||||
* 扫描src目录下的所有已经被标注的模块
|
||||
* @return array
|
||||
* @throws ZMException
|
||||
*/
|
||||
public static function getConfiguredModules(): array {
|
||||
$dir = DataProvider::getSourceRootDir() . "/src/";
|
||||
$ls = DataProvider::scanDirFiles($dir, true, true);
|
||||
$modules = [];
|
||||
foreach ($ls as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if ($pathinfo["basename"] == "zm.json") {
|
||||
$json = json_decode(file_get_contents(realpath($dir . "/" . $v)), true);
|
||||
if ($json === null) continue;
|
||||
if (!isset($json["name"])) continue;
|
||||
if ($pathinfo["dirname"] == ".") {
|
||||
throw new ZMException(zm_internal_errcode("E00052") . "在/src/目录下不可以直接标记为模块(zm.json),因为命名空间不能为根空间!");
|
||||
}
|
||||
$json["module-path"] = realpath($dir . "/" . $pathinfo["dirname"]);
|
||||
$json["namespace"] = str_replace("/", "\\", $pathinfo["dirname"]);
|
||||
if (isset($modules[$json["name"]])) {
|
||||
throw new ZMException(zm_internal_errcode("E00053") . "重名模块:" . $json["name"]);
|
||||
}
|
||||
$modules[$json["name"]] = $json;
|
||||
}
|
||||
}
|
||||
return $modules;
|
||||
}
|
||||
|
||||
public static function getPackedModules(): array {
|
||||
$dir = DataProvider::getDataFolder() . "modules";
|
||||
$ls = DataProvider::scanDirFiles($dir, true, false);
|
||||
if ($ls === false) return [];
|
||||
$modules = [];
|
||||
foreach ($ls as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if (($pathinfo["extension"] ?? "") != "phar") continue;
|
||||
$file = "phar://" . $v;
|
||||
if (!is_file($file . "/module_entry.php") || !is_file($file . "/zmplugin.json")) continue;
|
||||
$module_config = json_decode(file_get_contents($file . "/zmplugin.json"), true);
|
||||
if ($module_config === null) continue;
|
||||
if (!is_file($file . "/" . $module_config["module-root-path"] . "/zm.json")) {
|
||||
Console::warning(zm_internal_errcode("E00054") . "模块(插件)文件 " . $pathinfo["basename"] . " 无法找到模块配置文件(zm.json)!");
|
||||
continue;
|
||||
}
|
||||
$module_file = json_decode(file_get_contents($file . "/" . $module_config["module-root-path"] . "/zm.json"), true);
|
||||
if ($module_file === null) {
|
||||
Console::warning(zm_internal_errcode("E000555") . "模块(插件)文件 " . $pathinfo["basename"] . " 无法正常读取模块配置文件(zm.json)!");
|
||||
continue;
|
||||
}
|
||||
$module_config["phar-path"] = $v;
|
||||
$module_config["name"] = $module_file["name"] ?? null;
|
||||
if ($module_config["name"] === null) continue;
|
||||
$module_config["module-config"] = $module_file;
|
||||
$modules[$module_config["name"]] = $module_config;
|
||||
}
|
||||
return $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包模块
|
||||
* @param $module
|
||||
* @return bool
|
||||
* @throws ZMException
|
||||
*/
|
||||
public static function packModule($module): bool {
|
||||
try {
|
||||
$packer = new ModulePacker($module);
|
||||
$packer->setOutputPath(DataProvider::getDataFolder() . "output");
|
||||
$packer->setOverride();
|
||||
$packer->pack();
|
||||
return true;
|
||||
} catch (ModulePackException $e) {
|
||||
Console::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解包模块 TODO
|
||||
* @param $module
|
||||
* @return array|false
|
||||
*/
|
||||
public static function unpackModule($module) {
|
||||
try {
|
||||
$packer = new ModuleUnpacker($module);
|
||||
return $packer->unpack();
|
||||
} catch (ModulePackException $e) {
|
||||
Console::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
src/ZM/Utils/Manager/ProcessManager.php
Normal file
123
src/ZM/Utils/Manager/ProcessManager.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use Swoole\Coroutine;
|
||||
use ZM\Annotation\CQ\CQCommand;
|
||||
use ZM\Annotation\Swoole\OnPipeMessageEvent;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Event\EventDispatcher;
|
||||
use ZM\Event\EventManager;
|
||||
use ZM\Store\LightCache;
|
||||
use ZM\Store\LightCacheInside;
|
||||
use ZM\Store\WorkerCache;
|
||||
|
||||
class ProcessManager
|
||||
{
|
||||
public static function workerAction($src_worker_id, $data) {
|
||||
$server = server();
|
||||
switch ($data["action"] ?? '') {
|
||||
case 'add_short_command':
|
||||
Console::verbose("Adding short command " . $data["data"][0]);
|
||||
$obj = new CQCommand();
|
||||
$obj->method = quick_reply_closure($data["data"][1]);
|
||||
$obj->match = $data["data"][0];
|
||||
$obj->class = "";
|
||||
EventManager::addEvent(CQCommand::class, $obj);
|
||||
break;
|
||||
case "eval":
|
||||
eval($data["data"]);
|
||||
break;
|
||||
case "call_static":
|
||||
call_user_func_array([$data["data"]["class"], $data["data"]["method"]], $data["data"]["params"]);
|
||||
break;
|
||||
case "save_persistence":
|
||||
LightCache::savePersistence();
|
||||
break;
|
||||
case "resume_ws_message":
|
||||
$obj = $data["data"];
|
||||
Coroutine::resume($obj["coroutine"]);
|
||||
break;
|
||||
case "getWorkerCache":
|
||||
$r = WorkerCache::get($data["key"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "setWorkerCache":
|
||||
$r = WorkerCache::set($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "unsetWorkerCache":
|
||||
$r = WorkerCache::unset($data["key"]);
|
||||
$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;
|
||||
case "asyncSubWorkerCache":
|
||||
WorkerCache::sub($data["key"], $data["value"], true);
|
||||
break;
|
||||
case "asyncSetWorkerCache":
|
||||
WorkerCache::set($data["key"], $data["value"], true);
|
||||
break;
|
||||
case "asyncUnsetWorkerCache":
|
||||
WorkerCache::unset($data["key"], true);
|
||||
break;
|
||||
case "addWorkerCache":
|
||||
$r = WorkerCache::add($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "subWorkerCache":
|
||||
$r = WorkerCache::sub($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "returnWorkerCache":
|
||||
WorkerCache::$transfer[$data["cid"]] = $data["value"];
|
||||
zm_resume($data["cid"]);
|
||||
break;
|
||||
default:
|
||||
$dispatcher = new EventDispatcher(OnPipeMessageEvent::class);
|
||||
$dispatcher->setRuleFunction(function (OnPipeMessageEvent $v) use ($data) {
|
||||
return $v->action == $data["action"];
|
||||
});
|
||||
$dispatcher->dispatchEvents($data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static function sendActionToWorker($worker_id, $action, $data) {
|
||||
$obj = ["action" => $action, "data" => $data];
|
||||
if (server()->worker_id === -1 && server()->getManagerPid() != posix_getpid()) {
|
||||
Console::warning(zm_internal_errcode("E00022") . "Cannot send worker action from master or manager process!");
|
||||
return;
|
||||
}
|
||||
if (server()->worker_id == $worker_id) {
|
||||
self::workerAction($worker_id, $obj);
|
||||
} else {
|
||||
server()->sendMessage(json_encode($obj), $worker_id);
|
||||
}
|
||||
}
|
||||
|
||||
public static function resumeAllWorkerCoroutines() {
|
||||
if (server()->worker_id === -1) {
|
||||
Console::warning("Cannot call '" . __FUNCTION__ . "' in non-worker process!");
|
||||
return;
|
||||
}
|
||||
foreach ((LightCacheInside::get("wait_api", "wait_api") ?? []) as $v) {
|
||||
if (isset($v["coroutine"], $v["worker_id"])) {
|
||||
if (server()->worker_id == $v["worker_id"]) Coroutine::resume($v["coroutine"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/ZM/Utils/Manager/RouteManager.php
Normal file
67
src/ZM/Utils/Manager/RouteManager.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use ZM\Annotation\Http\Controller;
|
||||
use ZM\Annotation\Http\RequestMapping;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Http\StaticFileHandler;
|
||||
use ZM\Store\LightCacheInside;
|
||||
|
||||
/**
|
||||
* 路由管理器,2.5版本更改了命名空间
|
||||
* Class RouteManager
|
||||
* @package ZM\Utils\Manager
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class RouteManager
|
||||
{
|
||||
/** @var null|RouteCollection */
|
||||
public static $routes = null;
|
||||
|
||||
public static function importRouteByAnnotation(RequestMapping $vss, $method, $class, $methods_annotations) {
|
||||
if (self::$routes === null) self::$routes = new RouteCollection();
|
||||
|
||||
// 拿到所属方法的类上面有没有控制器的注解
|
||||
$prefix = '';
|
||||
foreach ($methods_annotations as $annotation) {
|
||||
if ($annotation instanceof Controller) {
|
||||
$prefix = $annotation->prefix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$tail = trim($vss->route, "/");
|
||||
$route_name = $prefix . ($tail === "" ? "" : "/") . $tail;
|
||||
Console::debug("添加路由:" . $route_name);
|
||||
$route = new Route($route_name, ['_class' => $class, '_method' => $method]);
|
||||
$route->setMethods($vss->request_method);
|
||||
|
||||
self::$routes->add(md5($route_name), $route);
|
||||
}
|
||||
|
||||
public static function addStaticFileRoute($route, $path) {
|
||||
$tail = trim($route, "/");
|
||||
$route_name = ($tail === "" ? "" : "/") . $tail . "/{filename}";
|
||||
Console::debug("添加静态文件路由:" . $route_name);
|
||||
$route = new Route($route_name, ['_class' => RouteManager::class, '_method' => "onStaticRoute"]);
|
||||
//echo $path.PHP_EOL;
|
||||
LightCacheInside::set("static_route", $route->getPath(), $path);
|
||||
|
||||
self::$routes->add(md5($route_name), $route);
|
||||
}
|
||||
|
||||
public function onStaticRoute($params) {
|
||||
$route_path = self::$routes->get($params["_route"])->getPath();
|
||||
if(($path = LightCacheInside::get("static_route", $route_path)) === null) {
|
||||
ctx()->getResponse()->endWithStatus(404);
|
||||
return false;
|
||||
}
|
||||
unset($params["_route"]);
|
||||
$obj = array_shift($params);
|
||||
return new StaticFileHandler($obj, $path);
|
||||
}
|
||||
}
|
||||
25
src/ZM/Utils/Manager/TaskManager.php
Normal file
25
src/ZM/Utils/Manager/TaskManager.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use ZM\Console\Console;
|
||||
|
||||
class TaskManager
|
||||
{
|
||||
/**
|
||||
* @param $task_name
|
||||
* @param int $timeout
|
||||
* @param mixed ...$params
|
||||
* @return false|mixed
|
||||
*/
|
||||
public static function runTask($task_name, int $timeout = -1, ...$params) {
|
||||
if (!isset(server()->setting["task_worker_num"])) {
|
||||
Console::warning(zm_internal_errcode("E00056") . "未开启 TaskWorker 进程,请先修改 global 配置文件启用!");
|
||||
return false;
|
||||
}
|
||||
$r = server()->taskwait(["task" => $task_name, "params" => $params], $timeout);
|
||||
return $r === false ? false : $r["result"];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user