From 12d547c1a2969f2e35e93cfe0679054b790b8dbe Mon Sep 17 00:00:00 2001 From: "as2252258@163.com" Date: Sun, 11 Jul 2021 03:57:25 +0800 Subject: [PATCH] modify --- Annotation/Route/RpcProducer.php | 56 +- HttpServer/Events/OnWorkerExit.php | 8 +- HttpServer/Events/OnWorkerStop.php | 3 - HttpServer/Route/Router.php | 1259 ++++++++++++----------- HttpServer/Server.php | 53 +- HttpServer/Service/Abstracts/Server.php | 160 +-- HttpServer/Service/Packet.php | 2 - Rpc/Actuator.php | 44 + Rpc/Service.php | 179 +++- Rpc/config.php | 42 + System/Channel.php | 15 +- System/Di/Service.php | 14 +- System/Event.php | 19 + 13 files changed, 1038 insertions(+), 816 deletions(-) create mode 100644 Rpc/Actuator.php create mode 100644 Rpc/config.php diff --git a/Annotation/Route/RpcProducer.php b/Annotation/Route/RpcProducer.php index cad5fbaa..2fff888e 100644 --- a/Annotation/Route/RpcProducer.php +++ b/Annotation/Route/RpcProducer.php @@ -9,6 +9,7 @@ use Exception; use HttpServer\Http\Request; use HttpServer\Route\Router; use JetBrains\PhpStorm\Pure; +use Rpc\Actuator; use Snowflake\Snowflake; @@ -19,39 +20,38 @@ use Snowflake\Snowflake; #[\Attribute(\Attribute::TARGET_METHOD)] class RpcProducer extends Attribute { - private string $uri = ''; - - const PROTOCOL_JSON = 'json'; - const PROTOCOL_SERIALIZE = 'serialize'; + const PROTOCOL_JSON = 'json'; + const PROTOCOL_SERIALIZE = 'serialize'; - /** - * Route constructor. - * @param string $cmd - * @param string $protocol - * @param int $port - */ - #[Pure] public function __construct(public string $cmd, public string $protocol = self::PROTOCOL_SERIALIZE, public int $port = 443) - { - $this->uri = 'rpc/p' . $this->port . '/' . ltrim($this->cmd, '/'); - } + /** + * Route constructor. + * @param string $cmd + * @param string $protocol + * @param int $port + */ + #[Pure] public function __construct(public string $cmd, public string $protocol = self::PROTOCOL_SERIALIZE, public int $port = 443) + { + } - /** - * @param array $handler - * @return Router - * @throws Exception - */ + + /** + * @param array $handler + * @return Router + * @throws Exception + */ public function execute(mixed $class, mixed $method = null): Router - { - // TODO: Implement setHandler() method. - $router = Snowflake::app()->getRouter(); - - $router->addRoute($this->uri, [$class, $method], Request::HTTP_CMD) - ->setDataType($this->protocol); - - return $router; - } + { + // TODO: Implement setHandler() method. + $router = Snowflake::app()->getRouter(); + $cmd = $this->cmd; + $callback = function (Actuator $actuator) use ($cmd, $class, $method) { + $actuator->addListener($cmd, $class . '@' . $method); + }; + $router->addRpcService($this->port, $callback); + return $router; + } } diff --git a/HttpServer/Events/OnWorkerExit.php b/HttpServer/Events/OnWorkerExit.php index 8e233bd7..e901223e 100644 --- a/HttpServer/Events/OnWorkerExit.php +++ b/HttpServer/Events/OnWorkerExit.php @@ -25,12 +25,10 @@ class OnWorkerExit extends Callback public function onHandler($server, $worker_id) { putenv('state=exit'); - $channel = Snowflake::app()->getChannel(); - $channel->cleanAll(); - Event::trigger(Event::SERVER_WORKER_EXIT); + Event::trigger(Event::SERVER_WORKER_EXIT, [$server, $worker_id]); - logger()->insert(); - } + Snowflake::getApp('logger')->insert(); + } } diff --git a/HttpServer/Events/OnWorkerStop.php b/HttpServer/Events/OnWorkerStop.php index 921699dc..589eec86 100644 --- a/HttpServer/Events/OnWorkerStop.php +++ b/HttpServer/Events/OnWorkerStop.php @@ -26,9 +26,6 @@ class OnWorkerStop extends Callback { Event::trigger(Event::SERVER_WORKER_STOP); - $this->clearMysqlClient(); - $this->clearRedisClient(); - fire(Event::SYSTEM_RESOURCE_CLEAN); Timer::clearAll(); diff --git a/HttpServer/Route/Router.php b/HttpServer/Route/Router.php index 83553fbc..4cbeda57 100644 --- a/HttpServer/Route/Router.php +++ b/HttpServer/Route/Router.php @@ -13,6 +13,7 @@ use HttpServer\IInterface\Middleware; use HttpServer\IInterface\RouterInterface; use JetBrains\PhpStorm\Pure; use ReflectionException; +use Rpc\Actuator; use Snowflake\Abstracts\Config; use Snowflake\Exception\ConfigException; use Snowflake\Exception\NotFindClassException; @@ -27,628 +28,640 @@ defined('ROUTER_HASH') or define('ROUTER_HASH', 2); */ class Router extends HttpService implements RouterInterface { - /** @var Node[] $nodes */ - public static array $nodes = []; - public array $groupTacks = []; - public ?string $dir = 'App\\Http\\Controllers'; - - const NOT_FOUND = 'Page not found or method not allowed.'; - - /** @var string[] */ - public array $methods = ['get', 'post', 'options', 'put', 'delete', 'receive', 'head']; - - - public ?Closure $middleware = null; - - public int $useTree = ROUTER_TREE; - - - /** - * @param Closure $middleware - */ - public function setMiddleware(\Closure $middleware): void - { - $this->middleware = $middleware; - } - - - /** - * @throws ConfigException - * 初始化函数路径 - */ - public function init() - { - $this->dir = Config::get('http.namespace', $this->dir); - } - - - /** - * @param bool $useTree - */ - public function setUseTree(bool $useTree): void - { - $this->useTree = $useTree ? ROUTER_TREE : ROUTER_HASH; - } - - - /** - * @param $port - * @param Closure|array|string $closure - * @param null $method - * @return Node|bool|null - * @throws - */ - public function addPortListen($port, Closure|array|string $closure, $method = null): Node|null|bool - { - if (!is_string($closure)) { - return $this->addRoute('add-port-listen/port_' . $port, $closure, 'listen'); - } - if (empty($method)) { - return $this->addError($closure . '::' . $method); - } - $_closure = Snowflake::createObject($closure); - if (!method_exists($_closure, $method)) { - return $this->addError($closure . '::' . $method); - } - return $this->addRoute('add-port-listen/port_' . $port, [$_closure, $method], 'listen'); - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return ?Node - * @throws Exception - */ - public function addRoute($path, $handler, $method = 'any'): ?Node - { - $method = strtolower($method); - if (!isset(static::$nodes[$method])) { - static::$nodes[$method] = []; - } - - if ($handler instanceof Closure) { - $handler = Closure::bind($handler, new Controller()); - } - - if ($this->useTree === ROUTER_TREE) { - return $this->tree($path, $handler, $method); - } - - return $this->hash($path, $handler, $method); - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return ?Node - */ - private function hash($path, $handler, $method = 'any'): ?Node - { - $path = $this->resolve($path); - - static::$nodes[$method][$path] = $this->NodeInstance($path, 0, $method); - - return static::$nodes[$method][$path]->bindHandler($handler); - } - - - /** - * @param $path - * @return string - */ - #[Pure] private function resolve($path): string - { - $paths = array_column($this->groupTacks, 'prefix'); - if (empty($paths)) { - return '/' . ltrim($path, '/'); - } - $paths = '/' . implode('/', $paths); - if ($path != '/') { - return $paths . '/' . ltrim($path, '/'); - } - return $paths . '/'; - } - - - /** - * @param $path - * @param $handler - * @param string $method - * @return Node - * @throws Exception - */ - private function tree($path, $handler, $method = 'any'): Node - { - list($first, $explode) = $this->split($path); - - $parent = static::$nodes[$method][$first] ?? null; - if (empty($parent)) { - static::$nodes[$method][$first] = $parent = $this->NodeInstance('/', 0, $method); - } - - if ($first !== '/') { - $parent = $this->bindNode($parent, $explode, $method); - } - $parent->path = $path; - return $parent->bindHandler($handler); - } - - - /** - * @param Node $parent - * @param array $explode - * @param $method - * @return Node - * @throws Exception - */ - private function bindNode(Node $parent, array $explode, $method): Node - { - $a = 0; - if (empty($explode)) { - return $parent->addChild($this->NodeInstance('/', $a, $method), '/'); - } - foreach ($explode as $value) { - if (empty($value)) { - continue; - } - ++$a; - - $search = $parent->findNode($value); - if ($search === null) { - $parent = $parent->addChild($this->NodeInstance($value, $a, $method), $value); - } else { - $parent = $search; - } - } - return $parent; - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function socket($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'socket'); - } - - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function post($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'post'); - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function get($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'get'); - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function options($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'options'); - } - - - /** - * @param $route - * @param $handler - * @return Any - * @throws - */ - public function any($route, $handler): Any - { - $nodes = []; - foreach (['get', 'post', 'options', 'put', 'delete', 'head'] as $method) { - $nodes[] = $this->addRoute($route, $handler, $method); - } - return new Any($nodes); - } - - /** - * @param $route - * @param $handler - * @return Node|null - * @throws - */ - public function delete($route, $handler): ?Node - { - 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 $handler - * @return Node|null - * @throws - */ - public function put($route, $handler): ?Node - { - return $this->addRoute($route, $handler, 'put'); - } - - /** - * @param $value - * @param $index - * @param $method - * @return Node - * @throws - */ - public function NodeInstance($value, $index = 0, $method = 'get'): Node - { - $node = new Node(); - $node->childes = []; - $node->path = $value; - $node->index = $index; - $node->method = $method; - $node->namespace = $this->loadNamespace($method); - - $name = array_column($this->groupTacks, 'middleware'); - if ($this->middleware instanceof \Closure) { - $node->addMiddleware([$this->middleware]); - } - - if (is_array($name)) { - $node->addMiddleware($this->resolve_middleware($name)); - } - - return $node; - } - - - /** - * @param string|array $middleware - * @return array - * @throws NotFindClassException - * @throws ReflectionException - */ - private function resolve_middleware(string|array $middleware): array - { - if (is_string($middleware)) { - $middleware = [$middleware]; - } - - $array = []; - foreach ($middleware as $value) { - if (is_array($value)) { - foreach ($value as $item) { - $array[] = $this->getMiddlewareInstance($item); - } - } else { - $array[] = $this->getMiddlewareInstance($value); - } - } - return $array; - } - - - /** - * @param $value - * @return Closure|array|null - * @throws NotFindClassException - * @throws ReflectionException - */ - private function getMiddlewareInstance($value): null|Closure|array - { - if (is_string($value)) { - $value = Snowflake::createObject($value); - if (!($value instanceof Middleware)) { - return null; - } - return [$value, 'onHandler']; - } else { - return $value; - } - } - - - /** - * @param $method - * @return array - */ - private function loadNamespace($method): array - { - $name = array_column($this->groupTacks, 'namespace'); - if ($method == 'package' || $method == 'receive') { - $dir = 'App\\Listener'; - } else { - $dir = $this->dir; - } - array_unshift($name, $dir); - return array_filter($name); - } - - /** - * @param array $config - * @param callable $callback - * 路由分组 - * @param null $stdClass - */ - public function group(array $config, callable $callback, $stdClass = null) - { - $this->groupTacks[] = $config; - if ($stdClass) { - $callback($stdClass); - } else { - $callback($this); - } - array_pop($this->groupTacks); - } - - /** - * @return string - */ - public function addPrefix(): string - { - $prefix = array_column($this->groupTacks, 'prefix'); - - $prefix = array_filter($prefix); - - if (empty($prefix)) { - return ''; - } - - return '/' . implode('/', $prefix); - } - - /** - * @param array|null $explode - * @param $method - * @return Node|null - * 查找指定路由 - */ - public function tree_search(?array $explode, $method): ?Node - { - if (empty($explode)) { - return static::$nodes[$method]['/'] ?? null; - } - $first = array_shift($explode); - if (!($parent = static::$nodes[$method][$first] ?? null)) { - return null; - } - if (empty($explode)) { - return $parent->findNode('/'); - } - while ($value = array_shift($explode)) { - $node = $parent->findNode($value); - if (!$node) { - break; - } - $parent = $node; - } - return $parent; - } - - /** - * @param $path - * @return array - * '*' - */ - public function split($path): array - { - $prefix = $this->addPrefix(); - $path = ltrim($path, '/'); - if (!empty($prefix)) { - $path = $prefix . '/' . $path; - } - - $explode = array_filter(explode('/', $path)); - if (empty($explode)) { - return ['/', []]; - } - - $first = array_shift($explode); - if (empty($explode)) { - $explode = []; - } - return [$first, $explode]; - } - - /** - * @return array - */ - public function each(): array - { - $paths = []; - foreach (static::$nodes as $node) { - /** @var Node[] $node */ - foreach ($node as $path => $_node) { - $paths[] = strtoupper($_node->method) . ' : ' . $path; - } - } - return $paths; - } - - - /** - * @return mixed - * @throws - */ - public function dispatch(): mixed - { - $node = $this->find_path(\request()); - if (!($node instanceof Node)) { - throw new RequestException(\request()->getUri() . ' -> ' . self::NOT_FOUND, 404); - } - send(($response = $node->dispatch()), 200); - if (!$node->hasAfter()) { - return null; - } - return $node->afterDispatch($response); - } - - - /** - * @param $exception - * @return mixed - * @throws Exception - */ - private function exception($exception): mixed - { - return Snowflake::app()->getLogger()->exception($exception); - } - - - /** - * @param Request $request - * @return Node|null 树干搜索 - * 树干搜索 - */ - public function find_path(Request $request): ?Node - { - return $this->Branch_search($request); - $method = $request->getMethod(); - $uri = $request->headers->get('request_uri', '/'); - - if (!isset(static::$nodes[$method])) { - return null; - } - $methods = static::$nodes[$method]; - if (isset($methods[$uri])) { - return $methods[$uri]; - } - if (!$request->isOption || !isset($methods['/'])) { - return null; - } - return $methods['/']; - } - - - /** - * @param $uri - * @param $method - * @return Node|null - */ - public function search($uri, $method): Node|null - { - if (!isset(static::$nodes[$method])) { - return null; - } - $methods = static::$nodes[$method]; - if (isset($methods[$uri])) { - return $methods[$uri]; - } - return $methods['/'] ?? null; - } - - - /** - * @param $request - * @return Node|null - */ - private function search_options($request): ?Node - { - $method = $request->getMethod(); - if (!isset(static::$nodes[$method])) { - return null; - } - if (!isset(static::$nodes[$method]['*'])) { - return null; - } - return static::$nodes[$method]['*']; - } - - - /** - * @param Request $request - * @return Node|null - * 树杈搜索 - */ - private function Branch_search(Request $request): ?Node - { - $node = $this->tree_search($request->getExplode(), $request->getMethod()); - if ($node instanceof Node) { - return $node; - } - if (!$request->isOption) { - return null; - } - $node = $this->tree_search(['*'], $request->getMethod()); - if (!($node instanceof Node)) { - return null; - } - return $node; - } - - - /** - * @throws - */ - public function _loader() - { - $this->loadRouteDir(APP_PATH . 'routes'); - } - - /** - * @param $path - * @throws Exception - * 加载目录下的路由文件 - */ - private function loadRouteDir($path) - { - $files = glob($path . '/*'); - for ($i = 0; $i < count($files); $i++) { - if (is_dir($files[$i])) { - $this->loadRouteDir($files[$i]); - } else { - $this->loadRouterFile($files[$i]); - } - } - } - - - /** - * @param $files - * @throws Exception - */ - private function loadRouterFile($files) - { - try { - $router = $this; - include_once "{$files}"; - } catch (\Throwable $exception) { - $this->addError($exception, 'throwable'); - } finally { - if (isset($exception)) { - unset($exception); - } - } - } + /** @var Node[] $nodes */ + public static array $nodes = []; + public array $groupTacks = []; + public ?string $dir = 'App\\Http\\Controllers'; + + const NOT_FOUND = 'Page not found or method not allowed.'; + + /** @var string[] */ + public array $methods = ['get', 'post', 'options', 'put', 'delete', 'receive', 'head']; + + + public ?Closure $middleware = null; + + public int $useTree = ROUTER_TREE; + + + /** + * @param Closure $middleware + */ + public function setMiddleware(\Closure $middleware): void + { + $this->middleware = $middleware; + } + + + /** + * @throws ConfigException + * 初始化函数路径 + */ + public function init() + { + $this->dir = Config::get('http.namespace', $this->dir); + } + + + /** + * @param bool $useTree + */ + public function setUseTree(bool $useTree): void + { + $this->useTree = $useTree ? ROUTER_TREE : ROUTER_HASH; + } + + + /** + * @param $port + * @param Closure|array|string $closure + * @param null $method + * @return Node|bool|null + * @throws + */ + public function addPortListen($port, Closure|array|string $closure, $method = null): Node|null|bool + { + if (!is_string($closure)) { + return $this->addRoute('add-port-listen/port_' . $port, $closure, 'listen'); + } + if (empty($method)) { + return $this->addError($closure . '::' . $method); + } + $_closure = Snowflake::createObject($closure); + if (!method_exists($_closure, $method)) { + return $this->addError($closure . '::' . $method); + } + return $this->addRoute('add-port-listen/port_' . $port, [$_closure, $method], 'listen'); + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return ?Node + * @throws Exception + */ + public function addRoute($path, $handler, $method = 'any'): ?Node + { + $method = strtolower($method); + if (!isset(static::$nodes[$method])) { + static::$nodes[$method] = []; + } + + if ($handler instanceof Closure) { + $handler = Closure::bind($handler, new Controller()); + } + + if ($this->useTree === ROUTER_TREE) { + return $this->tree($path, $handler, $method); + } + + return $this->hash($path, $handler, $method); + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return ?Node + */ + private function hash($path, $handler, $method = 'any'): ?Node + { + $path = $this->resolve($path); + + static::$nodes[$method][$path] = $this->NodeInstance($path, 0, $method); + + return static::$nodes[$method][$path]->bindHandler($handler); + } + + + /** + * @param $path + * @return string + */ + #[Pure] private function resolve($path): string + { + $paths = array_column($this->groupTacks, 'prefix'); + if (empty($paths)) { + return '/' . ltrim($path, '/'); + } + $paths = '/' . implode('/', $paths); + if ($path != '/') { + return $paths . '/' . ltrim($path, '/'); + } + return $paths . '/'; + } + + + /** + * @param $path + * @param $handler + * @param string $method + * @return Node + * @throws Exception + */ + private function tree($path, $handler, $method = 'any'): Node + { + list($first, $explode) = $this->split($path); + + $parent = static::$nodes[$method][$first] ?? null; + if (empty($parent)) { + static::$nodes[$method][$first] = $parent = $this->NodeInstance('/', 0, $method); + } + + if ($first !== '/') { + $parent = $this->bindNode($parent, $explode, $method); + } + $parent->path = $path; + return $parent->bindHandler($handler); + } + + + /** + * @param Node $parent + * @param array $explode + * @param $method + * @return Node + * @throws Exception + */ + private function bindNode(Node $parent, array $explode, $method): Node + { + $a = 0; + if (empty($explode)) { + return $parent->addChild($this->NodeInstance('/', $a, $method), '/'); + } + foreach ($explode as $value) { + if (empty($value)) { + continue; + } + ++$a; + + $search = $parent->findNode($value); + if ($search === null) { + $parent = $parent->addChild($this->NodeInstance($value, $a, $method), $value); + } else { + $parent = $search; + } + } + return $parent; + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function socket($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'socket'); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function post($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'post'); + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function get($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'get'); + } + + + /** + * @param $port + * @param callable $callback + * @return false|mixed + */ + public function addRpcService($port, callable $callback) + { + return call_user_func($callback, new Actuator($port)); + } + + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function options($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'options'); + } + + + /** + * @param $route + * @param $handler + * @return Any + * @throws + */ + public function any($route, $handler): Any + { + $nodes = []; + foreach (['get', 'post', 'options', 'put', 'delete', 'head'] as $method) { + $nodes[] = $this->addRoute($route, $handler, $method); + } + return new Any($nodes); + } + + /** + * @param $route + * @param $handler + * @return Node|null + * @throws + */ + public function delete($route, $handler): ?Node + { + 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 $handler + * @return Node|null + * @throws + */ + public function put($route, $handler): ?Node + { + return $this->addRoute($route, $handler, 'put'); + } + + /** + * @param $value + * @param $index + * @param $method + * @return Node + * @throws + */ + public function NodeInstance($value, $index = 0, $method = 'get'): Node + { + $node = new Node(); + $node->childes = []; + $node->path = $value; + $node->index = $index; + $node->method = $method; + $node->namespace = $this->loadNamespace($method); + + $name = array_column($this->groupTacks, 'middleware'); + if ($this->middleware instanceof \Closure) { + $node->addMiddleware([$this->middleware]); + } + + if (is_array($name)) { + $node->addMiddleware($this->resolve_middleware($name)); + } + + return $node; + } + + + /** + * @param string|array $middleware + * @return array + * @throws NotFindClassException + * @throws ReflectionException + */ + private function resolve_middleware(string|array $middleware): array + { + if (is_string($middleware)) { + $middleware = [$middleware]; + } + + $array = []; + foreach ($middleware as $value) { + if (is_array($value)) { + foreach ($value as $item) { + $array[] = $this->getMiddlewareInstance($item); + } + } else { + $array[] = $this->getMiddlewareInstance($value); + } + } + return $array; + } + + + /** + * @param $value + * @return Closure|array|null + * @throws NotFindClassException + * @throws ReflectionException + */ + private function getMiddlewareInstance($value): null|Closure|array + { + if (is_string($value)) { + $value = Snowflake::createObject($value); + if (!($value instanceof Middleware)) { + return null; + } + return [$value, 'onHandler']; + } else { + return $value; + } + } + + + /** + * @param $method + * @return array + */ + private function loadNamespace($method): array + { + $name = array_column($this->groupTacks, 'namespace'); + if ($method == 'package' || $method == 'receive') { + $dir = 'App\\Listener'; + } else { + $dir = $this->dir; + } + array_unshift($name, $dir); + return array_filter($name); + } + + /** + * @param array $config + * @param callable $callback + * 路由分组 + * @param null $stdClass + */ + public function group(array $config, callable $callback, $stdClass = null) + { + $this->groupTacks[] = $config; + if ($stdClass) { + $callback($stdClass); + } else { + $callback($this); + } + array_pop($this->groupTacks); + } + + /** + * @return string + */ + public function addPrefix(): string + { + $prefix = array_column($this->groupTacks, 'prefix'); + + $prefix = array_filter($prefix); + + if (empty($prefix)) { + return ''; + } + + return '/' . implode('/', $prefix); + } + + /** + * @param array|null $explode + * @param $method + * @return Node|null + * 查找指定路由 + */ + public function tree_search(?array $explode, $method): ?Node + { + if (empty($explode)) { + return static::$nodes[$method]['/'] ?? null; + } + $first = array_shift($explode); + if (!($parent = static::$nodes[$method][$first] ?? null)) { + return null; + } + if (empty($explode)) { + return $parent->findNode('/'); + } + while ($value = array_shift($explode)) { + $node = $parent->findNode($value); + if (!$node) { + break; + } + $parent = $node; + } + return $parent; + } + + /** + * @param $path + * @return array + * '*' + */ + public function split($path): array + { + $prefix = $this->addPrefix(); + $path = ltrim($path, '/'); + if (!empty($prefix)) { + $path = $prefix . '/' . $path; + } + + $explode = array_filter(explode('/', $path)); + if (empty($explode)) { + return ['/', []]; + } + + $first = array_shift($explode); + if (empty($explode)) { + $explode = []; + } + return [$first, $explode]; + } + + /** + * @return array + */ + public function each(): array + { + $paths = []; + foreach (static::$nodes as $node) { + /** @var Node[] $node */ + foreach ($node as $path => $_node) { + $paths[] = strtoupper($_node->method) . ' : ' . $path; + } + } + return $paths; + } + + + /** + * @return mixed + * @throws + */ + public function dispatch(): mixed + { + $node = $this->find_path(\request()); + if (!($node instanceof Node)) { + throw new RequestException(\request()->getUri() . ' -> ' . self::NOT_FOUND, 404); + } + send(($response = $node->dispatch()), 200); + if (!$node->hasAfter()) { + return null; + } + return $node->afterDispatch($response); + } + + + /** + * @param $exception + * @return mixed + * @throws Exception + */ + private function exception($exception): mixed + { + return Snowflake::app()->getLogger()->exception($exception); + } + + + /** + * @param Request $request + * @return Node|null 树干搜索 + * 树干搜索 + */ + public function find_path(Request $request): ?Node + { + return $this->Branch_search($request); + $method = $request->getMethod(); + $uri = $request->headers->get('request_uri', '/'); + + if (!isset(static::$nodes[$method])) { + return null; + } + $methods = static::$nodes[$method]; + if (isset($methods[$uri])) { + return $methods[$uri]; + } + if (!$request->isOption || !isset($methods['/'])) { + return null; + } + return $methods['/']; + } + + + /** + * @param $uri + * @param $method + * @return Node|null + */ + public function search($uri, $method): Node|null + { + if (!isset(static::$nodes[$method])) { + return null; + } + $methods = static::$nodes[$method]; + if (isset($methods[$uri])) { + return $methods[$uri]; + } + return $methods['/'] ?? null; + } + + + /** + * @param $request + * @return Node|null + */ + private function search_options($request): ?Node + { + $method = $request->getMethod(); + if (!isset(static::$nodes[$method])) { + return null; + } + if (!isset(static::$nodes[$method]['*'])) { + return null; + } + return static::$nodes[$method]['*']; + } + + + /** + * @param Request $request + * @return Node|null + * 树杈搜索 + */ + private function Branch_search(Request $request): ?Node + { + $node = $this->tree_search($request->getExplode(), $request->getMethod()); + if ($node instanceof Node) { + return $node; + } + if (!$request->isOption) { + return null; + } + $node = $this->tree_search(['*'], $request->getMethod()); + if (!($node instanceof Node)) { + return null; + } + return $node; + } + + + /** + * @throws + */ + public function _loader() + { + $this->loadRouteDir(APP_PATH . 'routes'); + } + + /** + * @param $path + * @throws Exception + * 加载目录下的路由文件 + */ + private function loadRouteDir($path) + { + $files = glob($path . '/*'); + for ($i = 0; $i < count($files); $i++) { + if (is_dir($files[$i])) { + $this->loadRouteDir($files[$i]); + } else { + $this->loadRouterFile($files[$i]); + } + } + } + + + /** + * @param $files + * @throws Exception + */ + private function loadRouterFile($files) + { + try { + $router = $this; + include_once "{$files}"; + } catch (\Throwable $exception) { + $this->addError($exception, 'throwable'); + } finally { + if (isset($exception)) { + unset($exception); + } + } + } } diff --git a/HttpServer/Server.php b/HttpServer/Server.php index 53761863..025cc2e9 100644 --- a/HttpServer/Server.php +++ b/HttpServer/Server.php @@ -276,7 +276,7 @@ class Server extends HttpService /** * @param $config - * @return \Swoole\Server|Packet|Receive|Http|Websocket|null + * @return mixed * @throws ConfigException * @throws Exception */ @@ -288,7 +288,7 @@ class Server extends HttpService } $server = $this->dispatchCreate($config, $settings); if (isset($config['events'])) { - $this->createEventListen($config); + $this->createEventListen($server, $config); } return $server; } @@ -298,33 +298,26 @@ class Server extends HttpService * @param $config * @throws Exception */ - protected function createEventListen($config) + protected function createEventListen($server, $config) { if (!is_array($config['events'])) { return; } foreach ($config['events'] as $name => $_event) { - if ($name !== Event::SERVER_CLIENT_CLOSE) { - Event::on('listen ' . $config['port'] . ' ' . $name, $_event); - } else { - Event::on($name, $_event); - } + $server->on($name, $_event); } } /** * @param $config * @param $settings - * @return \Swoole\Server|Packet|Receive|Http|Websocket|null + * @return mixed * @throws Exception */ - private function dispatchCreate($config, $settings): \Swoole\Server|Packet|Receive|Http|Websocket|null + private function dispatchCreate($config, $settings): mixed { - if (Snowflake::port_already($config['port'])) { - return $this->error_stop($config['host'], $config['port']); - } if (!($this->swoole instanceof \Swoole\Server)) { - return $this->parseServer($config, $settings); + $this->parseServer($config, $settings); } return $this->addListener($config); } @@ -405,7 +398,17 @@ class Server extends HttpService */ private function onListenerBind($server, $config): Packet|Websocket|Receive|Http|null { - $this->bindServerEvent($server, $config['type']); + if (self::PACKAGE == $config['type']) { + $this->onBindCallback($server, 'packet', $config['events'][Event::SERVER_ON_PACKET] ?? [make(OnPacket::class), 'onHandler']); + } else if ($config['type'] == self::TCP) { + $this->onBindCallback($server, 'connect', $config['events'][Event::SERVER_ON_CONNECT] ?? [make(OnConnect::class), 'onHandler']); + $this->onBindCallback($server, 'close', $config['events'][Event::SERVER_ON_CLOSE] ?? [make(OnClose::class), 'onHandler']); + $this->onBindCallback($server, 'receive', $config['events'][Event::SERVER_ON_RECEIVE] ?? [make(OnReceive::class), 'onHandler']); + } else if ($config['type'] === self::HTTP) { + $this->onBindCallback($server, 'request', $config['events'][Event::SERVER_ON_REQUEST] ?? [make(OnRequest::class), 'onHandler']); + } else { + throw new Exception('Unknown server type(' . $config['type'] . ').'); + } $this->debug(sprintf('Check listen %s::%d -> ok', $config['host'], $config['port'])); @@ -413,26 +416,6 @@ class Server extends HttpService } - /** - * @param string $type - * @throws Exception - */ - private function bindServerEvent($server, $type = self::TCP) - { - if (self::PACKAGE == $type) { - $this->onBindCallback($server, 'packet', [make(OnPacket::class), 'onHandler']); - } else if ($type == self::TCP) { - $this->onBindCallback($server, 'connect', [make(OnConnect::class), 'onHandler']); - $this->onBindCallback($server, 'close', [make(OnClose::class), 'onHandler']); - $this->onBindCallback($server, 'receive', [make(OnReceive::class), 'onHandler']); - } else if ($type === self::HTTP) { - $this->onBindCallback($server, 'request', [make(OnRequest::class), 'onHandler']); - } else { - throw new Exception('Unknown server type(' . $type . ').'); - } - } - - /** * @param $name * @param $callback diff --git a/HttpServer/Service/Abstracts/Server.php b/HttpServer/Service/Abstracts/Server.php index 4049a802..034e375b 100644 --- a/HttpServer/Service/Abstracts/Server.php +++ b/HttpServer/Service/Abstracts/Server.php @@ -10,85 +10,113 @@ use Snowflake\Application; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; + +/** + * Trait Server + * @package HttpServer\Service\Abstracts + */ trait Server { - public ?Application $application = null; + public ?Application $application = null; - /** - * Server constructor. - * @param $host - * @param null $port - * @param null $mode - * @param null $sock_type - */ - public function __construct($host, $port = null, $mode = null, $sock_type = null) - { - parent::__construct($host, $port, $mode, $sock_type); - } + /** + * Server constructor. + * @param $host + * @param null $port + * @param null $mode + * @param null $sock_type + */ + public function __construct($host, $port = null, $mode = null, $sock_type = null) + { + parent::__construct($host, $port, $mode, $sock_type); + } - /** - * @param array $settings - */ - public function set(array $settings) - { - parent::set($settings); // TODO: Change the autogenerated stub - $this->onInit(); - } + /** + * @param array $settings + */ + public function set(array $settings) + { + parent::set($settings); // TODO: Change the autogenerated stub + $this->onInit(); + } - /** - * @return void - * @throws NotFindClassException - * @throws ReflectionException - */ - public function onHandlerListener(): void - { - $this->on('WorkerStop', $this->createHandler('workerStop')); - $this->on('WorkerExit', $this->createHandler('workerExit')); - $this->on('WorkerStart', $this->createHandler('workerStart')); - $this->on('WorkerError', $this->createHandler('workerError')); - $this->on('ManagerStart', $this->createHandler('managerStart')); - $this->on('ManagerStop', $this->createHandler('managerStop')); - $this->on('PipeMessage', $this->createHandler('pipeMessage')); - $this->on('Shutdown', $this->createHandler('shutdown')); - $this->on('Start', $this->createHandler('start')); - $this->addTask(); - } + /** + * @return void + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onHandlerListener(): void + { + $this->on('Shutdown', $this->createHandler('shutdown')); + $this->on('Start', $this->createHandler('start')); + if ($this->setting['task_worker_num'] ?? 0 > 0) { + $this->on('Finish', $this->createHandler('finish')); + $this->on('Task', $this->createHandler('task')); + } + $this->onManager(); + } - /** - * @throws NotFindClassException - * @throws ReflectionException - */ - protected function addTask() - { - $settings = $this->setting; - if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) { - $this->on('Finish', $this->createHandler('finish')); - $this->on('Task', $this->createHandler('task')); - } - } + /** + * @throws \ReflectionException + * @throws \Snowflake\Exception\NotFindClassException + */ + private function onManager() + { + $this->on('ManagerStart', $this->createHandler('managerStart')); + $this->on('ManagerStop', $this->createHandler('managerStop')); + + $this->onWorker(); + $this->onOther(); + } - /** - * @param $eventName - * @return array - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - protected function createHandler($eventName): array - { - $classPrefix = 'HttpServer\Events\On' . ucfirst($eventName); - if (!class_exists($classPrefix)) { - throw new Exception('class not found.'); - } - $class = Snowflake::createObject($classPrefix, [Snowflake::app()]); - return [$class, 'onHandler']; - } + /** + * @throws \ReflectionException + * @throws \Snowflake\Exception\NotFindClassException + */ + private function onWorker() + { + $this->on('WorkerStop', $this->createHandler('workerStop')); + $this->on('WorkerExit', $this->createHandler('workerExit')); + $this->on('WorkerStart', $this->createHandler('workerStart')); + $this->on('WorkerError', $this->createHandler('workerError')); + } + + + /** + * @throws \ReflectionException + * @throws \Snowflake\Exception\NotFindClassException + */ + private function onOther() + { + $this->on('PipeMessage', $this->createHandler('pipeMessage')); + $this->on('BeforeReload', $this->createHandler('BeforeReload')); + $this->on('AfterReload', $this->createHandler('AfterReload')); + } + + + /** + * @param $eventName + * @return array + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + protected function createHandler($eventName): array + { + $classPrefix = 'HttpServer\Events\On' . ucfirst($eventName); + if (!class_exists($classPrefix)) { + throw new Exception('class not found.'); + } + + $class = Snowflake::createObject($classPrefix, [Snowflake::app()]); + return [$class, 'onHandler']; + } } diff --git a/HttpServer/Service/Packet.php b/HttpServer/Service/Packet.php index 10f5055b..32f0e74f 100644 --- a/HttpServer/Service/Packet.php +++ b/HttpServer/Service/Packet.php @@ -33,9 +33,7 @@ class Packet extends Tcp */ public function onBaseListener() { - $this->on('connect', $this->createHandler('connect')); $this->on('packet', $this->createHandler('packet')); - $this->on('close', $this->createHandler('close')); } diff --git a/Rpc/Actuator.php b/Rpc/Actuator.php new file mode 100644 index 00000000..f16af86a --- /dev/null +++ b/Rpc/Actuator.php @@ -0,0 +1,44 @@ +router = Snowflake::getApp('router'); + } + + + /** + * @param string $path + * @param string|callable $callback + * @throws \Exception + */ + public function addListener(string $path, string|callable $callback): void + { + $this->router->addRoute('rpc/p' . $this->port . '/' . ltrim($path, '/'), $callback); + } + + +} diff --git a/Rpc/Service.php b/Rpc/Service.php index bacb711d..2a0de22e 100644 --- a/Rpc/Service.php +++ b/Rpc/Service.php @@ -4,25 +4,21 @@ namespace Rpc; use Exception; -use HttpServer\Events\OnClose; -use HttpServer\Events\OnConnect; -use HttpServer\Events\OnPacket; -use HttpServer\Events\OnReceive; use HttpServer\Http\Context; use HttpServer\Http\Request; -use HttpServer\Server; +use HttpServer\Route\Router; use HttpServer\Service\Http; use HttpServer\Service\Packet; use HttpServer\Service\Receive; use HttpServer\Service\Websocket; -use JetBrains\PhpStorm\Pure; -use ReflectionException; use Snowflake\Abstracts\Component; use Snowflake\Abstracts\Config; use Snowflake\Core\Json; +use Snowflake\Event; use Snowflake\Exception\ConfigException; -use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; +use Swoole\Server; +use function Swoole\Coroutine\defer; /** @@ -41,6 +37,22 @@ class Service extends Component 'open_websocket_protocol' => false, ]; + + const RPC_CONNECT = 'RPC::CONNECT'; + const RPC_CLOSE = 'RPC::CLOSE'; + + private Router $router; + + + /** + * @throws \Exception + */ + public function init() + { + $this->router = Snowflake::getApp('router'); + } + + /** * @param Packet|Websocket|Receive|Http|null $server * @throws ConfigException @@ -49,33 +61,19 @@ class Service extends Component public function instance(Packet|Websocket|Receive|null|Http $server): void { $service = Config::get('rpc'); - if (empty($service) || !is_array($service)) { + if (!is_array($service) || empty($service)) { return; } - $mode = $service['mode'] ?? SWOOLE_SOCK_TCP6; - if (Snowflake::port_already($service['port'])) { - throw new Exception($this->already($service)); + $listen_type = $service['mode'] ?? SWOOLE_SOCK_TCP6; + $rpcServer = $server->addlistener($service['host'], $service['port'], $listen_type); + if ($rpcServer === false) { + throw new Exception('Listen rpc service fail.'); } $this->debug(Snowflake::listen($service)); - if (!isset($service['setting'])) { - $service['setting'] = self::defaultConfig; - } - - $rpcServer = $server->addlistener($service['host'], $service['port'], $mode); - $rpcServer->set($service['setting']); - $this->addCallback($rpcServer, $mode); - } - - - /** - * @param $service - * @return string - */ - #[Pure] private function already($service): string - { - return sprintf('Port %s::%d is already.', $service['host'], $service['port']); + $rpcServer->set($service['setting'] ?? self::defaultConfig); + $this->addCallback($rpcServer, $service, $listen_type); } @@ -83,18 +81,131 @@ class Service extends Component * @param $mode * @throws Exception */ - private function addCallback($rpcServer, $mode) + private function addCallback($rpcServer, $config, $mode) { $tcp = [SWOOLE_SOCK_TCP, SWOOLE_TCP, SWOOLE_TCP6, SWOOLE_SOCK_TCP6]; $server = Snowflake::app()->getServer(); if (in_array($mode, $tcp)) { - $server->onBindCallback($rpcServer, 'connect', [make(OnConnect::class), 'onHandler']); - $server->onBindCallback($rpcServer, 'close', [make(OnClose::class), 'onHandler']); - $server->onBindCallback($rpcServer, 'receive', [make(OnReceive::class), 'onHandler']); + $connectCallback = $config['events'][Event::SERVER_ON_CONNECT] ?? [$this, 'onConnect']; + $server->onBindCallback($rpcServer, 'connect', $connectCallback); + + $connectCallback = $config['events'][Event::SERVER_ON_CLOSE] ?? [$this, 'onClose']; + $server->onBindCallback($rpcServer, 'close', $connectCallback); + + $connectCallback = $config['events'][Event::SERVER_ON_CONNECT] ?? [$this, 'onReceive']; + $server->onBindCallback($rpcServer, 'receive', $connectCallback); } else { - $server->onBindCallback($rpcServer, 'packet', [make(OnReceive::class), 'onHandler']); + $connectCallback = $config['events'][Event::SERVER_ON_PACKET] ?? [$this, 'onPacket']; + $server->onBindCallback($rpcServer, 'packet', $connectCallback); } } + /** + * @param \Swoole\Server $server + * @param int $fd + * @param int $reactorId + */ + private function onConnect(Server $server, int $fd, int $reactorId) + { + defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); + + $config = $server->setting['enable_delay_receive'] ?? null; + if ($config === true) { + $server->confirm($fd); + } + Event::trigger(Service::RPC_CONNECT, [$server, $fd, $reactorId]); + } + + + /** + * @param \Swoole\Server $server + * @param int $fd + * on tcp client close + */ + private function onClose(Server $server, int $fd) + { + defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); + + Event::trigger(Service::RPC_CLOSE, [$server, $fd]); + } + + + /** + * @param \Swoole\Server $server + * @param int $fd + * @param int $reID + * @param string $data + * @throws \Exception + */ + private function onReceive(Server $server, int $fd, int $reID, string $data) + { + defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); + try { + $client = $server->getClientInfo($fd, $reID); + + $request = $this->requestSpl((int)$client['server_port'], $data); + + $result = $this->router->find_path($request)?->dispatch(); + + $server->send($fd, $result); + } catch (\Throwable $exception) { + $this->addError($exception, 'rpc-service'); + $server->send($fd, $exception->getMessage()); + } + } + + + /** + * @param \Swoole\Server $server + * @param int $fd + * @param int $reID + * @param string $data + * @throws \Exception + */ + private function onPacket(Server $server, string $data, array $client) + { + defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES)); + try { + $request = $this->requestSpl((int)$client['server_port'], $data); + + $result = $this->router->find_path($request)?->dispatch(); + + $server->sendto($client['address'], $client['port'], $result); + } catch (\Throwable $exception) { + $this->addError($exception, 'rpc-service'); + $server->sendto($client['address'], $client['port'], $exception->getMessage()); + } + } + + + /** + * @param \Swoole\Server $server + * @param int $fd + * @param int $reID + * @param string $data + * @return mixed + * @throws \Exception + */ + private function requestSpl(int $server_port, string $data) + { + $sRequest = new Request(); + + [$cmd, $repeat, $body] = explode("\n", $data); + if (is_null($body) || is_null($cmd) || !empty($repeat)) { + throw new Exception('Protocol format error.'); + } + + if (is_string($body) && is_null($data = Json::decode($body))) { + throw new Exception('Protocol format error.'); + } + + $sRequest->params->setPosts($data); + $sRequest->headers->setRequestUri('rpc/p' . $server_port . '/' . ltrim($cmd, '/')); + $sRequest->headers->setRequestMethod(Request::HTTP_CMD); + + return Context::setContext('request', $sRequest); + } + + } diff --git a/Rpc/config.php b/Rpc/config.php new file mode 100644 index 00000000..1c4a4b37 --- /dev/null +++ b/Rpc/config.php @@ -0,0 +1,42 @@ +addRpcService(9527, function (\Rpc\Actuator $actuator) { + $actuator->addListener('', ''); + $actuator->addListener('', ''); +}); + +return [ + 'rpc' => [ + 'type' => Server::TCP, + 'host' => '0.0.0.0', + 'mode' => SWOOLE_SOCK_TCP, + 'port' => 5377, + 'setting' => [ + 'open_tcp_keepalive' => true, + 'tcp_keepidle' => 30, + 'tcp_keepinterval' => 10, + 'tcp_keepcount' => 10, + 'open_http_protocol' => false, + 'open_websocket_protocol' => false, + ], + 'events' => [ + Server::SERVER_ON_CONNECT => [], + Server::SERVER_ON_CLOSE => [], + ], + 'registry' => [ + 'protocol' => 'consul', + 'address' => [ + 'host' => '47.14.25.45', + 'port' => 5527, + 'path' => '' + ], + ], + ] + +]; diff --git a/System/Channel.php b/System/Channel.php index 7a8d57c9..1c601b93 100644 --- a/System/Channel.php +++ b/System/Channel.php @@ -18,15 +18,16 @@ class Channel extends Component { - private static array $_channels = []; + private static ?array $_channels = []; - private static array $_waitRecover = []; + private static ?array $_waitRecover = []; public function init() { Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'recover']); + Event::on(Event::SERVER_WORKER_EXIT, [$this, 'cleanAll']); } @@ -84,15 +85,7 @@ class Channel extends Component */ public function cleanAll() { - /** @var SplQueue $channel */ - foreach (static::$_channels as $channel) { - if (!($channel instanceof SplQueue)) { - continue; - } - while ($channel->count() > 0) { - $channel->dequeue(); - } - } + static::$_channels = null; static::$_channels = []; } diff --git a/System/Di/Service.php b/System/Di/Service.php index fab64ba4..298320cc 100644 --- a/System/Di/Service.php +++ b/System/Di/Service.php @@ -81,26 +81,22 @@ class Service extends Component * @return mixed * @throws Exception */ - public function set($id, $definition): mixed + public function set($id, $definition): void { if ($definition === NULL) { - return $this->remove($id); + $this->remove($id); + return; } $this->_ids[] = $id; unset($this->_components[$id]); if (is_object($definition) || is_callable($definition, TRUE)) { - return $this->_definition[$id] = $definition; + $this->_definition[$id] = $definition; } else if (!is_array($definition)) { throw new ComponentException("Unexpected configuration type for the \"$id\" component: " . gettype($definition)); } - if (!isset($definition['class'])) { - throw new ComponentException("The configuration for the \"$id\" component must contain a \"class\" element."); - } else { - $this->_definition[$id] = $definition; - } - return $this->get($id); + $this->_definition[$id] = $definition; } /** diff --git a/System/Event.php b/System/Event.php index 869b80e5..f74106be 100644 --- a/System/Event.php +++ b/System/Event.php @@ -60,6 +60,25 @@ class Event extends BaseObject const SERVER_MESSAGE = 'on message'; const SERVER_CLIENT_CLOSE = 'SERVER:CLIENT:CLOSE'; + const SERVER_ON_START = 'Start'; + const SERVER_ON_SHUTDOWN = 'Shutdown'; + const SERVER_ON_WORKER_START = 'WorkerStart'; + const SERVER_ON_WORKER_STOP = 'WorkerStop'; + const SERVER_ON_WORKER_EXIT = 'WorkerExit'; + const SERVER_ON_CONNECT = 'Connect'; + const SERVER_ON_RECEIVE = 'Receive'; + const SERVER_ON_PACKET = 'Packet'; + const SERVER_ON_REQUEST = 'request'; + const SERVER_ON_CLOSE = 'Close'; + const SERVER_ON_TASK = 'Task'; + const SERVER_ON_FINISH = 'Finish'; + const SERVER_ON_PIPE_MESSAGE = 'PipeMessage'; + const SERVER_ON_WORKER_ERROR = 'WorkerError'; + const SERVER_ON_MANAGER_START = 'ManagerStart'; + const SERVER_ON_MANAGER_STOP = 'ManagerStop'; + const SERVER_ON_BEFORE_RELOAD = 'BeforeReload'; + const SERVER_ON_AFTER_RELOAD = 'AfterReload'; + /** * @param $name