Files
zhamao-framework/src/ZM/Event/Swoole/WorkerStartEvent.php

213 lines
7.5 KiB
PHP
Raw Normal View History

2020-03-02 16:14:20 +08:00
<?php
namespace ZM\Event\Swoole;
use Co;
2020-03-02 16:14:20 +08:00
use Doctrine\Common\Annotations\AnnotationException;
2020-04-15 10:55:10 +08:00
use Exception;
2020-06-05 13:36:30 +08:00
use PDO;
2020-03-02 16:14:20 +08:00
use ReflectionException;
use Swoole\Coroutine;
2020-05-23 17:23:29 +08:00
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
use Swoole\Process;
2020-03-02 16:14:20 +08:00
use Swoole\Timer;
use ZM\Annotation\AnnotationBase;
use ZM\Annotation\AnnotationParser;
2020-03-12 19:06:27 +08:00
use ZM\Annotation\Swoole\OnStart;
2020-03-02 16:14:20 +08:00
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Connection\ConnectionManager;
2020-04-15 10:55:10 +08:00
use ZM\Context\ContextInterface;
2020-03-02 16:14:20 +08:00
use ZM\DB\DB;
use Framework\Console;
use Framework\GlobalConfig;
use Framework\ZMBuf;
use Swoole\Server;
2020-05-08 16:37:38 +08:00
use ZM\Event\EventHandler;
use ZM\Exception\DbException;
2020-05-02 23:27:26 +08:00
use Framework\DataProvider;
use ZM\Utils\ZMUtil;
2020-03-02 16:14:20 +08:00
class WorkerStartEvent implements SwooleEvent
{
private $worker_id;
/**
* @var Server
*/
private $server;
public function __construct(Server $server, $worker_id) {
$this->server = $server;
$this->worker_id = $worker_id;
}
/**
* @return WorkerStartEvent
* @throws AnnotationException
* @throws ReflectionException
* @throws DbException
2020-03-02 16:14:20 +08:00
*/
public function onActivate(): WorkerStartEvent {
Console::info("Worker启动中");
2020-05-23 17:23:29 +08:00
ZMBuf::$server = $this->server;
Console::listenConsole(); //这个方法只能在这里调用且如果worker_num不为1的话此功能不可用
2020-05-02 23:27:26 +08:00
Process::signal(SIGINT, function () {
Console::warning("Server interrupted by keyboard.");
ZMUtil::stop(true);
});
2020-03-02 16:14:20 +08:00
ZMBuf::resetCache(); //清空变量缓存
ZMBuf::set("wait_start", []); //添加队列在workerStart运行完成前先让其他协程等待执行
$this->resetConnections();//释放所有与framework的连接
//设置炸毛buf中储存的对象
ZMBuf::$globals = new GlobalConfig();
ZMBuf::$config = [];
2020-05-02 23:27:26 +08:00
$file = scandir(DataProvider::getWorkingDir() . '/config/');
unset($file[0], $file[1]);
foreach ($file as $k => $v) {
if ($v == "global.php") continue;
$name = explode(".", $v);
if (($prefix = end($name)) == "json") {
2020-05-02 23:27:26 +08:00
ZMBuf::$config[$name[0]] = json_decode(Co::readFile(DataProvider::getWorkingDir() . '/config/' . $v), true);
2020-04-26 15:01:18 +08:00
Console::info("已读取配置文件:" . $v);
} elseif ($prefix == "php") {
2020-05-02 23:27:26 +08:00
ZMBuf::$config[$name[0]] = include_once DataProvider::getWorkingDir() . '/config/' . $v;
if (is_array(ZMBuf::$config[$name[0]]))
2020-04-26 15:01:18 +08:00
Console::info("已读取配置文件:" . $v);
}
}
2020-03-02 16:14:20 +08:00
if (ZMBuf::globals("sql_config")["sql_host"] != "") {
Console::info("新建SQL连接池中");
2020-05-23 17:23:29 +08:00
ob_start();
phpinfo();
$str = ob_get_clean();
$str = explode("\n", $str);
foreach($str as $k => $v) {
$v = trim($v);
if($v == "") continue;
if(mb_strpos($v, "API Extensions") === false) continue;
if(mb_strpos($v, "pdo_mysql") === false) {
throw new DbException("未安装 mysqlnd php-mysql扩展。");
}
}
$sql = ZMBuf::globals("sql_config");
ZMBuf::$sql_pool = new PDOPool((new PDOConfig())
->withHost($sql["sql_host"])
->withPort($sql["sql_port"])
// ->withUnixSocket('/tmp/mysql.sock')
->withDbName($sql["sql_database"])
->withCharset('utf8mb4')
->withUsername($sql["sql_username"])
->withPassword($sql["sql_password"])
2020-06-10 14:39:30 +08:00
->withOptions($sql["sql_options"] ?? [PDO::ATTR_STRINGIFY_FETCHES => false])
2020-05-23 17:23:29 +08:00
);
2020-03-02 16:14:20 +08:00
DB::initTableList();
}
2020-05-23 17:23:29 +08:00
2020-03-02 16:14:20 +08:00
ZMBuf::$atomics['reload_time']->add(1);
Console::info("监听console输入");
2020-05-23 17:23:29 +08:00
2020-03-02 16:14:20 +08:00
$this->setAutosaveTimer(ZMBuf::globals("auto_save_interval"));
2020-05-06 17:19:59 +08:00
$this->loadAllClass(); //加载composer资源、phar外置包、注解解析注册等
2020-03-02 16:14:20 +08:00
return $this;
}
2020-05-08 16:37:38 +08:00
/**
* @return WorkerStartEvent
* @throws AnnotationException
*/
2020-03-02 16:14:20 +08:00
public function onAfter(): WorkerStartEvent {
foreach (ZMBuf::get("wait_start") as $v) {
Coroutine::resume($v);
}
ZMBuf::unsetCache("wait_start");
2020-05-08 16:37:38 +08:00
set_coroutine_params(["server" => $this->server, "worker_id" => $this->worker_id]);
2020-05-23 17:23:29 +08:00
2020-05-02 23:27:26 +08:00
foreach (ZMBuf::$events[OnStart::class] ?? [] as $v) {
2020-03-12 19:06:27 +08:00
$class_name = $v->class;
2020-05-23 17:23:29 +08:00
Console::debug("正在调用启动时函数: " . $class_name . " -> " . $v->method);
2020-05-08 16:37:38 +08:00
EventHandler::callWithMiddleware($class_name, $v->method, ["server" => $this->server, "worker_id" => $this->worker_id], []);
2020-03-12 19:06:27 +08:00
}
2020-03-02 16:14:20 +08:00
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
/** @var AnnotationBase $v */
if (strtolower($v->type) == "workerstart") {
$class_name = $v->class;
2020-05-23 17:23:29 +08:00
Console::debug("正在调用启动时函数after: " . $class_name . " -> " . $v->method);
2020-05-08 16:37:38 +08:00
EventHandler::callWithMiddleware($class_name, $v->method, ["server" => $this->server, "worker_id" => $this->worker_id], []);
2020-05-06 17:26:50 +08:00
if (context()->getCache("block_continue") === true) break;
2020-03-02 16:14:20 +08:00
}
}
2020-05-23 17:23:29 +08:00
Console::debug("调用完毕!");
2020-03-02 16:14:20 +08:00
return $this;
}
private function resetConnections() {
foreach ($this->server->connections as $v) {
$this->server->close($v);
}
2020-05-23 17:23:29 +08:00
if (ZMBuf::$sql_pool !== null) {
ZMBuf::$sql_pool->close();
2020-03-02 16:14:20 +08:00
ZMBuf::$sql_pool = null;
}
}
/**
* @throws AnnotationException
* @throws ReflectionException
2020-04-15 10:55:10 +08:00
* @throws Exception
2020-03-02 16:14:20 +08:00
*/
private function loadAllClass() {
//加载phar包
Console::info("加载外部phar包中");
2020-05-02 23:27:26 +08:00
$dir = DataProvider::getWorkingDir() . "/resources/package/";
if (version_compare(SWOOLE_VERSION, "4.4.0", ">=")) Timer::clearAll();
2020-03-02 16:14:20 +08:00
if (is_dir($dir)) {
$list = scandir($dir);
unset($list[0], $list[1]);
foreach ($list as $v) {
if (is_dir($dir . $v)) continue;
2020-05-10 23:45:45 +08:00
if (pathinfo($dir . $v, 4) == "phar") {
Console::verbose("加载Phar: " . $dir . $v . "");
require_once($dir . $v);
}
2020-03-02 16:14:20 +08:00
}
}
//加载composer类
2020-06-13 14:09:25 +08:00
//remove stupid duplicate code
2020-03-02 16:14:20 +08:00
//加载各个模块的注解类,以及反射
Console::info("检索Module中");
AnnotationParser::registerMods();
//加载Custom目录下的自定义的内部类
ConnectionManager::registerCustomClass();
//加载自定义的全局函数
2020-05-23 17:23:29 +08:00
Console::debug("加载自定义的全局函数中");
2020-05-02 23:27:26 +08:00
if (file_exists(DataProvider::getWorkingDir() . "/src/Custom/global_function.php"))
require_once DataProvider::getWorkingDir() . "/src/Custom/global_function.php";
2020-04-15 10:55:10 +08:00
$this->afterCheck();
2020-03-02 16:14:20 +08:00
}
private function setAutosaveTimer($globals) {
DataProvider::$buffer_list = [];
2020-05-23 17:23:29 +08:00
zm_timer_tick($globals * 1000, function () {
2020-03-02 16:14:20 +08:00
DataProvider::saveBuffer();
});
}
2020-04-15 10:55:10 +08:00
/**
* @throws Exception
*/
private function afterCheck() {
$context_class = ZMBuf::globals("context_class");
2020-05-02 23:27:26 +08:00
if (!is_a($context_class, ContextInterface::class, true)) {
2020-04-15 10:55:10 +08:00
throw new Exception("Context class must implemented from ContextInterface!");
}
}
}