feat(WebSocket): 添加数据库连接检查和文件预览功能
- 在DefaultWebSocketController中添加数据库连接检查功能 - 实现文件预览和下载功能及相关API接口 - 更新测试页面支持文件预览和下载操作 - 移除旧的数据库维护子进程机制,改为函数检查 - 在构建请求数据时添加文件字段支持
This commit is contained in:
@@ -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服务器] 启动主服务器进程");
|
||||
|
||||
Reference in New Issue
Block a user