feat(WebSocket): 添加数据库连接检查和文件预览功能

- 在DefaultWebSocketController中添加数据库连接检查功能
- 实现文件预览和下载功能及相关API接口
- 更新测试页面支持文件预览和下载操作
- 移除旧的数据库维护子进程机制,改为函数检查
- 在构建请求数据时添加文件字段支持
This commit is contained in:
2026-01-26 08:40:07 +08:00
parent 0a7301f39d
commit ef708e6b40
3 changed files with 417 additions and 167 deletions

View File

@@ -371,10 +371,14 @@ class DefaultWebSocketController implements MessageComponentInterface
]));
}
public function onMessage(ConnectionInterface $conn, $msg)
{
public function onMessage(ConnectionInterface $conn, $msg) {
ws_echo("[默认路径] Received message from {$conn->resourceId}: $msg");
try {
// 检查数据库连接状态
if (function_exists('checkDatabaseConnection')) {
checkDatabaseConnection();
}
$data = json_decode($msg, true);
if (isset($data['action']) && $data['action'] === 'ping') {
$conn->send(json_encode(['type' => 'pong']));
@@ -409,6 +413,52 @@ class DefaultWebSocketController implements MessageComponentInterface
$ratchetApp->route('/ws', new DefaultWebSocketController(), array('*'), '');
ws_echo("已注册默认WebSocket测试控制器到路径 /ws");
/**
* 检查数据库连接状态并在需要时重新初始化
* @return bool 连接是否有效
*/
function checkDatabaseConnection() {
global $app, $cache;
try {
// 检查缓存中的连接状态
$connStatus = $cache->get('db_connection_status');
if ($connStatus === 'error') {
ws_echo("[WebSocket服务器] 检测到数据库连接错误,尝试重新初始化...");
$app->initialize();
$cache = $app->cache;
}
// 测试连接
$addon_model = new \app\model\system\Addon();
$addon_model->getAddonList([], 'name', 1, 1);
// 更新连接状态
$cache->set('db_connection_status', 'active', 60);
return true;
} catch (\Exception $e) {
ws_echo("[WebSocket服务器] 数据库连接检查失败: {$e->getMessage()}", 'warning');
// 尝试重新初始化
try {
$app->initialize();
$cache = $app->cache;
// 再次测试
$addon_model = new \app\model\system\Addon();
$addon_model->getAddonList([], 'name', 1, 1);
$cache->set('db_connection_status', 'active', 60);
ws_echo("[WebSocket服务器] 数据库连接已重新初始化成功");
return true;
} catch (\Exception $retryEx) {
ws_echo("[WebSocket服务器] 数据库连接重新初始化失败: {$retryEx->getMessage()}", 'error');
$cache->set('db_connection_status', 'error', 60);
return false;
}
}
}
// 缓存WebSocket服务器信息可选用于其他服务查询
$serverInfoKey = 'websocket_server_info';
$cache->set($serverInfoKey, [
@@ -419,6 +469,11 @@ $cache->set($serverInfoKey, [
'registered_addons' => $registeredAddons
], 0); // 0表示永久缓存直到手动删除
// 启动时检查数据库连接
ws_echo("[WebSocket服务器] 启动时检查数据库连接...");
checkDatabaseConnection();
ws_echo("[WebSocket服务器] 数据库连接检查完成");
ws_echo("WebSocket服务器已启动监听地址: ws://{$httpHost}:{$port}");
// 显示已注册WebSocket控制器的addon路径
@@ -461,105 +516,14 @@ if (!empty($missingDirAddons)) {
ws_echo(" - 所有已启用的addon目录都存在");
}
// 添加定期检查数据库连接的机制
// 创建一个单独的进程来定期检查和维护数据库连接
// 添加信号处理,确保当父进程停止时,子进程也会被终止
// 设置基本的信号处理
if (extension_loaded('pcntl')) {
// 记录子进程PID
$dbMaintenancePid = null;
// 创建数据库连接维护子进程
$pid = pcntl_fork();
if ($pid == -1) {
ws_echo("[WebSocket服务器] 无法创建子进程来维护数据库连接", 'error');
} elseif ($pid == 0) {
// 子进程:定期检查数据库连接
ws_echo("[WebSocket服务器] 启动数据库连接维护进程");
// 每30秒检查一次数据库连接
$checkInterval = 30; // 秒
// 检查是否在Windows平台
$isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// 保存父进程PID仅在非Windows平台
$parentPid = null;
if (!$isWindows && function_exists('getppid')) {
$parentPid = getppid();
ws_echo("[数据库维护子进程] 父进程PID: {$parentPid}");
} else {
ws_echo("[数据库维护子进程] 运行在Windows平台跳过父进程PID检查");
}
// 设置子进程的信号处理
pcntl_signal(SIGTERM, function() {
ws_echo("[数据库维护子进程] 收到终止信号,正在退出...");
exit(0);
});
while (true) {
// 检查是否有信号需要处理
pcntl_signal_dispatch();
// 检查父进程是否仍然存在仅在非Windows平台
if (!$isWindows && function_exists('getppid')) {
$currentParentPid = getppid();
if ($currentParentPid === 1) {
ws_echo("[数据库维护子进程] 父进程已退出,正在退出...");
exit(0);
}
}
try {
// 尝试执行一个简单的数据库查询来测试连接
$addon_model = new Addon();
$addon_model->getAddonList([], 'name', 1, 1); // 只查询一条记录
ws_echo("[数据库维护子进程] 数据库连接正常");
} catch (\Exception $e) {
ws_echo("[数据库维护子进程] 数据库连接异常: {$e->getMessage()}", 'error');
ws_echo("[数据库维护子进程] 尝试重新初始化数据库连接...");
try {
// 重新初始化应用和数据库连接
$app->initialize();
$cache = $app->cache;
ws_echo("[数据库维护子进程] 重新初始化应用成功");
} catch (\Exception $retryEx) {
ws_echo("[数据库维护子进程] 重新初始化应用失败: {$retryEx->getMessage()}", 'error');
}
}
// 等待指定的时间间隔
sleep($checkInterval);
}
} else {
// 父进程记录子进程PID并设置信号处理
$dbMaintenancePid = $pid;
// 检查是否在Windows平台
$isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// 设置父进程的信号处理
pcntl_signal(SIGINT, function() use ($dbMaintenancePid, $isWindows) {
ws_echo("[WebSocket服务器] 收到终止信号,正在停止...");
// 如果子进程存在,发送终止信号
if ($dbMaintenancePid) {
ws_echo("[WebSocket服务器] 停止数据库连接维护进程");
if (!$isWindows && function_exists('posix_kill')) {
posix_kill($dbMaintenancePid, SIGTERM);
// 等待子进程退出
pcntl_wait($status);
} else {
ws_echo("[WebSocket服务器] 运行在Windows平台跳过子进程终止信号发送");
}
}
ws_echo("[WebSocket服务器] 已停止");
exit(0);
});
}
}
pcntl_signal(SIGINT, function() {
ws_echo("[WebSocket服务器] 收到终止信号,正在停止...");
ws_echo("[WebSocket服务器] 已停止");
exit(0);
});
}
// 运行服务器
ws_echo("[WebSocket服务器] 启动主服务器进程");