mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-14 04:05:35 +08:00
inject container into framework
This commit is contained in:
@@ -27,6 +27,7 @@ use ZM\Utils\ZMUtil;
|
||||
|
||||
/**
|
||||
* Class Hello
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Hello
|
||||
@@ -68,6 +69,7 @@ class Hello
|
||||
*/
|
||||
public function hello()
|
||||
{
|
||||
zm_dump(resolve('swoole_server')->worker_id);
|
||||
return '你好啊,我是由炸毛框架构建的机器人!';
|
||||
}
|
||||
|
||||
@@ -134,10 +136,12 @@ class Hello
|
||||
* 问法2:从1到20的随机数
|
||||
* @CQCommand("随机数")
|
||||
* @CQCommand(pattern="*从*到*的随机数")
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function randNum()
|
||||
{
|
||||
zm_dump(resolve('swoole_server')->worker_id);
|
||||
// 获取第一个数字类型的参数
|
||||
$num1 = ctx()->getNumArg('请输入第一个数字');
|
||||
// 获取第二个数字类型的参数
|
||||
@@ -171,6 +175,7 @@ class Hello
|
||||
/**
|
||||
* 使用自定义参数的路由参数
|
||||
* @RequestMapping("/whoami/{name}")
|
||||
*
|
||||
* @param array $param 参数
|
||||
* @return string 返回的 HTML Body
|
||||
*/
|
||||
@@ -182,11 +187,18 @@ class Hello
|
||||
/**
|
||||
* 在机器人连接后向终端输出信息
|
||||
* @OnOpenEvent("qq")
|
||||
*
|
||||
* @param ConnectionObject $conn WebSocket 连接对象
|
||||
*/
|
||||
public function onConnect(ConnectionObject $conn)
|
||||
{
|
||||
zm_dump(resolve('path.base'));
|
||||
zm_dump(resolve('path.config'));
|
||||
zm_dump(resolve('app')::$server->worker_id);
|
||||
Console::info('机器人 ' . $conn->getOption('connect_id') . ' 已连接!');
|
||||
container()->bind('cid', function () use ($conn) {
|
||||
return resolve('app')::$server->worker_id . $conn->getOption('connect_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,12 +207,14 @@ class Hello
|
||||
*/
|
||||
public function onDisconnect(ConnectionObject $conn)
|
||||
{
|
||||
zm_dump(resolve('cid'));
|
||||
Console::info('机器人 ' . $conn->getOption('connect_id') . ' 已断开连接!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻止 Chrome 自动请求 /favicon.ico 导致的多条请求并发和干扰
|
||||
* @OnRequestEvent(rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200)
|
||||
*
|
||||
* @throws InterruptException
|
||||
*/
|
||||
public function onRequest()
|
||||
|
||||
@@ -5,15 +5,18 @@ declare(strict_types=1);
|
||||
namespace ZM\Event\SwooleEvent;
|
||||
|
||||
use Swoole\Coroutine;
|
||||
use Swoole\Http\Server;
|
||||
use Swoole\WebSocket\Frame;
|
||||
use Throwable;
|
||||
use ZM\Annotation\Swoole\OnMessageEvent;
|
||||
use ZM\Annotation\Swoole\OnSwooleEvent;
|
||||
use ZM\Annotation\Swoole\SwooleHandler;
|
||||
use ZM\ConnectionManager\ConnectionObject;
|
||||
use ZM\ConnectionManager\ManagerGM;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Console\TermColor;
|
||||
use ZM\Context\Context;
|
||||
use ZM\Context\ContextInterface;
|
||||
use ZM\Event\EventDispatcher;
|
||||
use ZM\Event\SwooleEvent;
|
||||
|
||||
@@ -29,6 +32,15 @@ class OnMessage implements SwooleEvent
|
||||
unset(Context::$context[Coroutine::getCid()]);
|
||||
$conn = ManagerGM::get($frame->fd);
|
||||
set_coroutine_params(['server' => $server, 'frame' => $frame, 'connection' => $conn]);
|
||||
|
||||
container()->instance(Server::class, $server);
|
||||
container()->instance(Frame::class, $frame);
|
||||
container()->instance(ConnectionObject::class, $conn);
|
||||
container()->bind(ContextInterface::class, function () {
|
||||
return ctx();
|
||||
});
|
||||
container()->alias(ContextInterface::class, Context::class);
|
||||
|
||||
$dispatcher1 = new EventDispatcher(OnMessageEvent::class);
|
||||
$dispatcher1->setRuleFunction(function ($v) use ($conn) {
|
||||
return $v->connect_type === $conn->getName() && ($v->getRule() === '' || eval('return ' . $v->getRule() . ';'));
|
||||
@@ -56,6 +68,11 @@ class OnMessage implements SwooleEvent
|
||||
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
||||
Console::error(zm_internal_errcode('E00017') . 'Uncaught ' . get_class($e) . ' when calling "message": ' . $error_msg);
|
||||
Console::trace();
|
||||
} finally {
|
||||
container()->flush();
|
||||
if (Console::getLevel() >= 4) {
|
||||
Console::debug(sprintf('Request container [fd=%d, cid=%d] flushed.', $frame->fd, Coroutine::getCid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use ZM\Annotation\Swoole\OnStart;
|
||||
use ZM\Annotation\Swoole\SwooleHandler;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Container\WorkerContainer;
|
||||
use ZM\Context\Context;
|
||||
use ZM\Context\ContextInterface;
|
||||
use ZM\DB\DB;
|
||||
@@ -52,6 +53,13 @@ class OnWorkerStart implements SwooleEvent
|
||||
SignalListener::signalWorker($server, $worker_id);
|
||||
}
|
||||
unset(Context::$context[Coroutine::getCid()]);
|
||||
|
||||
/* @noinspection PhpExpressionResultUnusedInspection */
|
||||
new WorkerContainer();
|
||||
if (Console::getLevel() >= 4) {
|
||||
Console::debug(sprintf('Worker container [id=%d,cid=%d] booted', $worker_id, Coroutine::getCid()));
|
||||
}
|
||||
|
||||
if ($server->taskworker === false) {
|
||||
Framework::saveProcessState(ZM_PROCESS_WORKER, $server->worker_pid, ['worker_id' => $worker_id]);
|
||||
zm_atomic('_#worker_' . $worker_id)->set($server->worker_pid);
|
||||
@@ -274,7 +282,7 @@ class OnWorkerStart implements SwooleEvent
|
||||
(new PDOConfig())
|
||||
->withHost($real_conf['host'])
|
||||
->withPort($real_conf['port'])
|
||||
// ->withUnixSocket('/tmp/mysql.sock')
|
||||
// ->withUnixSocket('/tmp/mysql.sock')
|
||||
->withDbName($real_conf['dbname'])
|
||||
->withCharset($real_conf['charset'])
|
||||
->withUsername($real_conf['username'])
|
||||
|
||||
@@ -8,6 +8,7 @@ use Swoole\Server;
|
||||
use ZM\Annotation\Swoole\SwooleHandler;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Container\WorkerContainer;
|
||||
use ZM\Event\SwooleEvent;
|
||||
use ZM\Framework;
|
||||
use ZM\Store\LightCache;
|
||||
@@ -20,6 +21,11 @@ class OnWorkerStop implements SwooleEvent
|
||||
{
|
||||
public function onCall(Server $server, $worker_id)
|
||||
{
|
||||
WorkerContainer::getInstance()->flush();
|
||||
if (Console::getLevel() >= 4) {
|
||||
Console::debug(sprintf('Worker container [id=%d] flushed', $worker_id));
|
||||
}
|
||||
|
||||
if ($worker_id == (ZMConfig::get('worker_cache')['worker'] ?? 0)) {
|
||||
LightCache::savePersistence();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ use ZM\Config\ZMConfig;
|
||||
use ZM\ConnectionManager\ManagerGM;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Console\TermColor;
|
||||
use ZM\Container\Container;
|
||||
use ZM\Container\ContainerInterface;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Store\LightCache;
|
||||
use ZM\Store\LightCacheInside;
|
||||
@@ -27,70 +29,75 @@ use ZM\Store\ZMAtomic;
|
||||
use ZM\Utils\DataProvider;
|
||||
use ZM\Utils\Terminal;
|
||||
use ZM\Utils\ZMUtil;
|
||||
use function date_default_timezone_set;
|
||||
use function define;
|
||||
use function exec;
|
||||
use function explode;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function get_class;
|
||||
use function get_included_files;
|
||||
use function in_array;
|
||||
use function intval;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
use function mkdir;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use function posix_getpid;
|
||||
use function str_pad;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function swoole_cpu_num;
|
||||
use function trim;
|
||||
use function uuidgen;
|
||||
use function working_dir;
|
||||
use function zm_atomic;
|
||||
use function zm_internal_errcode;
|
||||
|
||||
class Framework
|
||||
{
|
||||
/**
|
||||
* 框架运行的参数
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $argv;
|
||||
|
||||
/**
|
||||
* 通信服务器实例
|
||||
*
|
||||
* @var Server
|
||||
*/
|
||||
public static $server;
|
||||
|
||||
/**
|
||||
* 框架加载的文件
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $loaded_files = [];
|
||||
|
||||
/**
|
||||
* 是否为单文件模式
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $instant_mode = false;
|
||||
|
||||
/**
|
||||
* @var null|array|bool|mixed
|
||||
* Swoole 配置
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
private $server_set;
|
||||
private $swoole_config;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $setup_events = [];
|
||||
|
||||
public function __construct($args = [], $instant_mode = false)
|
||||
/**
|
||||
* 容器
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* 创建一个新的框架实例
|
||||
*
|
||||
* @param array $args 运行参数
|
||||
* @param bool $instant_mode 是否为单文件模式
|
||||
*/
|
||||
public function __construct(array $args = [], bool $instant_mode = false)
|
||||
{
|
||||
$tty_width = $this->getTtyWidth();
|
||||
self::$instant_mode = $instant_mode;
|
||||
self::$argv = $args;
|
||||
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
|
||||
|
||||
// 初始化全局容器
|
||||
$this->container = new Container();
|
||||
$this->bindPathsInContainer();
|
||||
$this->registerBaseBindings();
|
||||
|
||||
// 初始化配置
|
||||
ZMConfig::setDirectory($this->container->get('path.config'));
|
||||
ZMConfig::setEnv($args['env'] ?? '');
|
||||
if (ZMConfig::get('global') === false) {
|
||||
echo zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nError path: " . DataProvider::getSourceRootDir() . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n";
|
||||
@@ -98,19 +105,15 @@ class Framework
|
||||
}
|
||||
|
||||
// 定义常量
|
||||
include_once 'global_defines.php';
|
||||
require_once 'global_defines.php';
|
||||
|
||||
// 确保目录存在
|
||||
DataProvider::createIfNotExists(app('path.data'));
|
||||
DataProvider::createIfNotExists(app('path.config'));
|
||||
DataProvider::createIfNotExists(ZMConfig::get('global', 'crash_dir'));
|
||||
|
||||
// 初始化连接池?
|
||||
try {
|
||||
$sw = ZMConfig::get('global');
|
||||
if (!is_dir($sw['zm_data'])) {
|
||||
mkdir($sw['zm_data']);
|
||||
}
|
||||
if (!is_dir($sw['config_dir'])) {
|
||||
mkdir($sw['config_dir']);
|
||||
}
|
||||
if (!is_dir($sw['crash_dir'])) {
|
||||
mkdir($sw['crash_dir']);
|
||||
}
|
||||
ManagerGM::init(ZMConfig::get('global', 'swoole')['max_connection'] ?? 2048, 0.5, [
|
||||
[
|
||||
'key' => 'connect_id',
|
||||
@@ -126,98 +129,113 @@ class Framework
|
||||
echo zm_internal_errcode('E00008') . $e->getMessage() . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
// 初始化日志
|
||||
Console::init(
|
||||
ZMConfig::get('global', 'info_level') ?? 2,
|
||||
self::$server,
|
||||
$args['log-theme'] ?? 'default',
|
||||
($o = ZMConfig::get('console_color')) === false ? [] : $o
|
||||
);
|
||||
// 是否同步输出到文件
|
||||
if ((ZMConfig::get('global', 'runtime')['save_console_log_file'] ?? false) !== false) {
|
||||
Console::setOutputFile(ZMConfig::get('global', 'runtime')['save_console_log_file']);
|
||||
}
|
||||
|
||||
// 设置默认时区
|
||||
$timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
|
||||
date_default_timezone_set($timezone);
|
||||
|
||||
$this->server_set = ZMConfig::get('global', 'swoole');
|
||||
$this->server_set['log_level'] = SWOOLE_LOG_DEBUG;
|
||||
// 读取 Swoole 配置
|
||||
$this->swoole_config = ZMConfig::get('global', 'swoole');
|
||||
$this->swoole_config['log_level'] = SWOOLE_LOG_DEBUG;
|
||||
|
||||
// 是否启用远程终端
|
||||
$add_port = ZMConfig::get('global', 'remote_terminal')['status'] ?? false;
|
||||
|
||||
// 加载服务器事件
|
||||
if (!$instant_mode) {
|
||||
$this->loadServerEvents();
|
||||
}
|
||||
|
||||
// 解析命令行参数
|
||||
$this->parseCliArgs(self::$argv, $add_port);
|
||||
|
||||
if (!isset($this->server_set['max_wait_time'])) {
|
||||
$this->server_set['max_wait_time'] = 5;
|
||||
// 设置默认最长等待时间
|
||||
if (!isset($this->swoole_config['max_wait_time'])) {
|
||||
$this->swoole_config['max_wait_time'] = 5;
|
||||
}
|
||||
$worker = $this->server_set['worker_num'] ?? swoole_cpu_num();
|
||||
// 设置最大 worker 进程数
|
||||
$worker = $this->swoole_config['worker_num'] ?? swoole_cpu_num();
|
||||
define('ZM_WORKER_NUM', $worker);
|
||||
|
||||
// 初始化原子计数器
|
||||
ZMAtomic::init();
|
||||
$out['working_dir'] = DataProvider::getWorkingDir();
|
||||
|
||||
// 打印初始信息
|
||||
$out['listen'] = ZMConfig::get('global', 'host') . ':' . ZMConfig::get('global', 'port');
|
||||
if (!isset($this->server_set['worker_num'])) {
|
||||
if ((ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS) == SWOOLE_PROCESS) {
|
||||
$out['worker'] = swoole_cpu_num() . ' (auto)';
|
||||
} else {
|
||||
$out['single_proc_mode'] = 'true';
|
||||
}
|
||||
} else {
|
||||
$out['worker'] = $this->server_set['worker_num'];
|
||||
}
|
||||
$out['environment'] = ($args['env'] ?? null) === null ? 'default' : $args['env'];
|
||||
$out['log_level'] = Console::getLevel();
|
||||
$out['version'] = ZM_VERSION . (LOAD_MODE == 0 ? (' (build ' . ZM_VERSION_ID . ')') : '');
|
||||
$out['master_pid'] = posix_getpid();
|
||||
if (APP_VERSION !== 'unknown') {
|
||||
$out['app_version'] = APP_VERSION;
|
||||
}
|
||||
if (isset($this->server_set['task_worker_num'])) {
|
||||
$out['task_worker'] = $this->server_set['task_worker_num'];
|
||||
}
|
||||
if ((ZMConfig::get('global', 'sql_config')['sql_host'] ?? '') !== '') {
|
||||
$conf = ZMConfig::get('global', 'sql_config');
|
||||
$out['mysql_pool'] = $conf['sql_database'] . '@' . $conf['sql_host'] . ':' . $conf['sql_port'];
|
||||
}
|
||||
if ((ZMConfig::get('global', 'mysql_config')['host'] ?? '') !== '') {
|
||||
$conf = ZMConfig::get('global', 'mysql_config');
|
||||
$out['mysql'] = $conf['dbname'] . '@' . $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
if (ZMConfig::get('global', 'redis_config')['host'] !== '') {
|
||||
$conf = ZMConfig::get('global', 'redis_config');
|
||||
$out['redis_pool'] = $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
if (ZMConfig::get('global', 'static_file_server')['status'] !== false) {
|
||||
$out['static_file_server'] = 'enabled';
|
||||
}
|
||||
if (self::$argv['show-php-ver'] !== false) {
|
||||
$out['php_version'] = PHP_VERSION;
|
||||
$out['swoole_version'] = SWOOLE_VERSION;
|
||||
}
|
||||
|
||||
if ($add_port) {
|
||||
$conf = ZMConfig::get('global', 'remote_terminal');
|
||||
$out['terminal'] = $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
|
||||
// 非静默模式下打印启动信息
|
||||
if (!self::$argv['private-mode']) {
|
||||
$out['working_dir'] = DataProvider::getWorkingDir();
|
||||
$out['listen'] = ZMConfig::get('global', 'host') . ':' . ZMConfig::get('global', 'port');
|
||||
if (!isset($this->swoole_config['worker_num'])) {
|
||||
if ((ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS) === SWOOLE_PROCESS) {
|
||||
$out['worker'] = swoole_cpu_num() . ' (auto)';
|
||||
} else {
|
||||
$out['single_proc_mode'] = 'true';
|
||||
}
|
||||
} else {
|
||||
$out['worker'] = $this->swoole_config['worker_num'];
|
||||
}
|
||||
$out['environment'] = ($args['env'] ?? null) === null ? 'default' : $args['env'];
|
||||
$out['log_level'] = Console::getLevel();
|
||||
$out['version'] = ZM_VERSION . (LOAD_MODE === 0 ? (' (build ' . ZM_VERSION_ID . ')') : '');
|
||||
$out['master_pid'] = posix_getpid();
|
||||
if (APP_VERSION !== 'unknown') {
|
||||
$out['app_version'] = APP_VERSION;
|
||||
}
|
||||
if (isset($this->swoole_config['task_worker_num'])) {
|
||||
$out['task_worker'] = $this->swoole_config['task_worker_num'];
|
||||
}
|
||||
if ((ZMConfig::get('global', 'sql_config')['sql_host'] ?? '') !== '') {
|
||||
$conf = ZMConfig::get('global', 'sql_config');
|
||||
$out['mysql_pool'] = $conf['sql_database'] . '@' . $conf['sql_host'] . ':' . $conf['sql_port'];
|
||||
}
|
||||
if ((ZMConfig::get('global', 'mysql_config')['host'] ?? '') !== '') {
|
||||
$conf = ZMConfig::get('global', 'mysql_config');
|
||||
$out['mysql'] = $conf['dbname'] . '@' . $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
if (ZMConfig::get('global', 'redis_config')['host'] !== '') {
|
||||
$conf = ZMConfig::get('global', 'redis_config');
|
||||
$out['redis_pool'] = $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
if (ZMConfig::get('global', 'static_file_server')['status'] !== false) {
|
||||
$out['static_file_server'] = 'enabled';
|
||||
}
|
||||
if (self::$argv['show-php-ver'] !== false) {
|
||||
$out['php_version'] = PHP_VERSION;
|
||||
$out['swoole_version'] = SWOOLE_VERSION;
|
||||
}
|
||||
|
||||
if ($add_port) {
|
||||
$conf = ZMConfig::get('global', 'remote_terminal');
|
||||
$out['terminal'] = $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
self::printProps($out, $tty_width, $args['log-theme'] === null);
|
||||
}
|
||||
|
||||
// 预览模式则直接提出
|
||||
if ($args['preview'] ?? false) {
|
||||
exit();
|
||||
}
|
||||
|
||||
// 初始化服务器
|
||||
self::$server = new Server(
|
||||
ZMConfig::get('global', 'host'),
|
||||
ZMConfig::get('global', 'port'),
|
||||
ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS
|
||||
);
|
||||
|
||||
// 监听远程终端
|
||||
if ($add_port) {
|
||||
$conf = ZMConfig::get('global', 'remote_terminal') ?? [
|
||||
'status' => true,
|
||||
@@ -231,9 +249,11 @@ class Framework
|
||||
$port->set([
|
||||
'open_http_protocol' => false,
|
||||
]);
|
||||
$port->on('connect', function (?\Swoole\Server $serv, $fd) use ($welcome_msg, $conf) {
|
||||
$port->on('connect', function (\Swoole\Server $serv, $fd) use ($welcome_msg, $conf) {
|
||||
ManagerGM::pushConnect($fd, 'terminal');
|
||||
// 推送欢迎信息
|
||||
$serv->send($fd, file_get_contents(working_dir() . '/config/motd.txt'));
|
||||
// 要求输入令牌
|
||||
if (!empty($conf['token'])) {
|
||||
$serv->send($fd, 'Please input token: ');
|
||||
} else {
|
||||
@@ -294,16 +314,22 @@ class Framework
|
||||
});
|
||||
}
|
||||
|
||||
self::$server->set($this->server_set);
|
||||
// 设置服务器配置
|
||||
self::$server->set($this->swoole_config);
|
||||
Console::setServer(self::$server);
|
||||
|
||||
// 非静默模式下,打印欢迎信息
|
||||
if (!self::$argv['private-mode']) {
|
||||
self::printMotd($tty_width);
|
||||
}
|
||||
|
||||
global $asd;
|
||||
$asd = get_included_files();
|
||||
|
||||
// 注册 Swoole Server 的事件
|
||||
$this->registerServerEvents();
|
||||
|
||||
// 初始化缓存
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
||||
@@ -313,8 +339,12 @@ class Framework
|
||||
];
|
||||
LightCache::init($r);
|
||||
LightCacheInside::init();
|
||||
|
||||
// 初始化自旋锁
|
||||
SpinLock::init($r['size']);
|
||||
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
|
||||
|
||||
// 注册全局错误处理器
|
||||
set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) {
|
||||
switch ($error_no) {
|
||||
case E_WARNING:
|
||||
$level_tips = 'PHP Warning: ';
|
||||
@@ -343,13 +373,14 @@ class Framework
|
||||
default:
|
||||
$level_tips = 'Unkonw Type Error: ';
|
||||
break;
|
||||
} // do some handle
|
||||
}
|
||||
$error = $level_tips . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
|
||||
Console::warning($error); // 如果 return false 则错误会继续递交给 PHP 标准错误处理 /
|
||||
Console::warning($error);
|
||||
// 如果 return false 则错误会继续递交给 PHP 标准错误处理
|
||||
return true;
|
||||
}, E_ALL | E_STRICT);
|
||||
} catch (Exception $e) {
|
||||
Console::error('Framework初始化出现错误,请检查!');
|
||||
Console::error('框架初始化出现异常,请检查!');
|
||||
Console::error(zm_internal_errcode('E00010') . $e->getMessage());
|
||||
Console::debug($e);
|
||||
exit;
|
||||
@@ -358,6 +389,7 @@ class Framework
|
||||
|
||||
/**
|
||||
* 将各进程的pid写入文件,以备后续崩溃及僵尸进程处理使用
|
||||
*
|
||||
* @param int|string $pid
|
||||
* @internal
|
||||
*/
|
||||
@@ -394,6 +426,7 @@ class Framework
|
||||
|
||||
/**
|
||||
* 用于框架内部获取多进程运行状态的函数
|
||||
*
|
||||
* @param mixed $id_or_name
|
||||
* @throws ZMKnownException
|
||||
* @return false|int|mixed
|
||||
@@ -510,8 +543,8 @@ class Framework
|
||||
|
||||
public static function printProps($out, $tty_width, $colorful = true)
|
||||
{
|
||||
$max_border = $tty_width < 65 ? $tty_width : 65;
|
||||
if (LOAD_MODE == 0) {
|
||||
$max_border = min($tty_width, 65);
|
||||
if (LOAD_MODE === 0) {
|
||||
echo Console::setColor("* Framework started with source mode.\n", $colorful ? 'yellow' : '');
|
||||
}
|
||||
echo str_pad('', $max_border, '=') . PHP_EOL;
|
||||
@@ -526,7 +559,7 @@ class Framework
|
||||
}
|
||||
// Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
||||
if ($max_border >= 57) { // 很宽的时候,一行能放两个短行
|
||||
if ($line_width[$current_line] == ($max_border - 2)) { // 空行
|
||||
if ($line_width[$current_line] === ($max_border - 2)) { // 空行
|
||||
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
||||
} else { // 不是空行,已经有东西了
|
||||
$tmp_line = $k . ': ' . $v;
|
||||
@@ -582,6 +615,30 @@ class Framework
|
||||
return file_put_contents(DataProvider::getDataFolder() . '.state.json', json_encode($data, 64 | 128 | 256));
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册所有应用路径到容器
|
||||
*/
|
||||
protected function bindPathsInContainer(): void
|
||||
{
|
||||
$this->container->instance('path.working', DataProvider::getWorkingDir());
|
||||
$this->container->instance('path.source', DataProvider::getSourceRootDir());
|
||||
$this->container->alias('path.source', 'path.base');
|
||||
$this->container->instance('path.config', DataProvider::getSourceRootDir() . '/config');
|
||||
$this->container->singleton('path.data', function () {
|
||||
return DataProvider::getDataFolder();
|
||||
});
|
||||
$this->container->instance('path.framework', DataProvider::getFrameworkRootDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册基础绑定到容器
|
||||
*/
|
||||
protected function registerBaseBindings(): void
|
||||
{
|
||||
$this->container->instance('framework', $this);
|
||||
$this->container->alias('framework', 'app');
|
||||
}
|
||||
|
||||
private static function printMotd($tty_width)
|
||||
{
|
||||
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
|
||||
@@ -623,6 +680,7 @@ class Framework
|
||||
|
||||
/**
|
||||
* 从全局配置文件里读取注入系统事件的类
|
||||
*
|
||||
* @throws ReflectionException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
@@ -659,6 +717,7 @@ class Framework
|
||||
|
||||
/**
|
||||
* 解析命令行的 $argv 参数们
|
||||
*
|
||||
* @param array $args 命令行参数
|
||||
* @param bool|string $add_port 是否添加端口号
|
||||
*/
|
||||
@@ -672,15 +731,15 @@ class Framework
|
||||
switch ($x) {
|
||||
case 'worker-num':
|
||||
if (intval($y) >= 1 && intval($y) <= 1024) {
|
||||
$this->server_set['worker_num'] = intval($y);
|
||||
$this->swoole_config['worker_num'] = intval($y);
|
||||
} else {
|
||||
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (' . ($this->server_set['worker_num'] ?? swoole_cpu_num()) . ')');
|
||||
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (' . ($this->swoole_config['worker_num'] ?? swoole_cpu_num()) . ')');
|
||||
}
|
||||
break;
|
||||
case 'task-worker-num':
|
||||
if (intval($y) >= 1 && intval($y) <= 1024) {
|
||||
$this->server_set['task_worker_num'] = intval($y);
|
||||
$this->server_set['task_enable_coroutine'] = true;
|
||||
$this->swoole_config['task_worker_num'] = intval($y);
|
||||
$this->swoole_config['task_enable_coroutine'] = true;
|
||||
} else {
|
||||
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (0)');
|
||||
}
|
||||
@@ -696,9 +755,9 @@ class Framework
|
||||
echo "* You are in debug mode, do not use in production!\n";
|
||||
break;
|
||||
case 'daemon':
|
||||
$this->server_set['daemonize'] = 1;
|
||||
$this->swoole_config['daemonize'] = 1;
|
||||
Console::$theme = 'no-color';
|
||||
Console::log('已启用守护进程,输出重定向到 ' . $this->server_set['log_file']);
|
||||
Console::log('已启用守护进程,输出重定向到 ' . $this->swoole_config['log_file']);
|
||||
$terminal_id = null;
|
||||
break;
|
||||
case 'disable-console-input':
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace ZM\Utils;
|
||||
|
||||
use Iterator;
|
||||
use JsonSerializable;
|
||||
use RuntimeException;
|
||||
use Traversable;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
@@ -25,6 +26,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 返回工作目录,不带最右边文件夹的斜杠(/)
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getWorkingDir()
|
||||
@@ -34,6 +36,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 获取框架所在根目录
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getFrameworkRootDir()
|
||||
@@ -43,6 +46,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 获取源码根目录,除Phar模式外均与工作目录相同
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getSourceRootDir()
|
||||
@@ -52,6 +56,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 获取框架反代链接
|
||||
*
|
||||
* @return null|array|false|mixed
|
||||
*/
|
||||
public static function getFrameworkLink()
|
||||
@@ -61,6 +66,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 获取zm_data数据目录,如果二级目录不为空,则自动创建目录并返回
|
||||
*
|
||||
* @return null|array|false|mixed|string
|
||||
*/
|
||||
public static function getDataFolder(string $second = '')
|
||||
@@ -79,6 +85,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 将变量保存在zm_data下的数据目录,传入数组
|
||||
*
|
||||
* @param string $filename 文件名
|
||||
* @param array|int|Iterator|JsonSerializable|string|Traversable $file_array 文件内容数组
|
||||
* @return false|int 返回文件大小或false
|
||||
@@ -104,6 +111,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 从json加载变量到内存
|
||||
*
|
||||
* @param string $filename 文件名
|
||||
* @return null|mixed 返回文件内容数据或null
|
||||
*/
|
||||
@@ -118,6 +126,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
|
||||
*
|
||||
* @param string $dir 目录
|
||||
* @param bool $recursive 是否递归扫描子目录
|
||||
* @param bool|string $relative 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录
|
||||
@@ -161,6 +170,7 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 检查路径是否为相对路径(根据第一个字符是否为"/"来判断)
|
||||
*
|
||||
* @param string $path 路径
|
||||
* @return bool 返回结果
|
||||
* @since 2.5
|
||||
@@ -169,4 +179,16 @@ class DataProvider
|
||||
{
|
||||
return strlen($path) > 0 && $path[0] !== '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录(如果不存在)
|
||||
*
|
||||
* @param string $path 目录路径
|
||||
*/
|
||||
public static function createIfNotExists(string $path): void
|
||||
{
|
||||
if (!is_dir($path) && !mkdir($path, 0777, true) && !is_dir($path)) {
|
||||
throw new RuntimeException(sprintf('无法建立目录:%s', $path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ function get_annotations(): array
|
||||
*/
|
||||
function set_coroutine_params(array $params): void
|
||||
{
|
||||
$cid = Co::getCid();
|
||||
$cid = co::getCid();
|
||||
if ($cid === -1) {
|
||||
exit(zm_internal_errcode('E00061') . 'Cannot set coroutine params at none coroutine mode.');
|
||||
}
|
||||
@@ -233,7 +233,7 @@ function set_coroutine_params(array $params): void
|
||||
Context::$context[$cid] = $params;
|
||||
}
|
||||
foreach (Context::$context as $c => $v) {
|
||||
if (!Co::exists($c)) {
|
||||
if (!co::exists($c)) {
|
||||
unset(Context::$context[$c], ZMBuf::$context_class[$c]);
|
||||
}
|
||||
}
|
||||
@@ -252,13 +252,13 @@ function context(): ContextInterface
|
||||
*/
|
||||
function ctx(): ContextInterface
|
||||
{
|
||||
$cid = Co::getCid();
|
||||
$cid = co::getCid();
|
||||
$c_class = ZMConfig::get('global', 'context_class');
|
||||
if (isset(Context::$context[$cid])) {
|
||||
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
||||
}
|
||||
Console::debug("未找到当前协程的上下文({$cid}),正在找父进程的上下文");
|
||||
while (($parent_cid = Co::getPcid($cid)) !== -1) {
|
||||
while (($parent_cid = co::getPcid($cid)) !== -1) {
|
||||
$cid = $parent_cid;
|
||||
if (isset(Context::$context[$cid])) {
|
||||
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
||||
@@ -320,7 +320,7 @@ function zm_exec(string $command): array
|
||||
*/
|
||||
function zm_cid(): int
|
||||
{
|
||||
return Co::getCid();
|
||||
return co::getCid();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,7 +330,7 @@ function zm_cid(): int
|
||||
*/
|
||||
function zm_yield()
|
||||
{
|
||||
Co::yield();
|
||||
co::yield();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,7 +340,7 @@ function zm_yield()
|
||||
*/
|
||||
function zm_resume(int $cid)
|
||||
{
|
||||
Co::resume($cid);
|
||||
co::resume($cid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user