Showing
1 changed file
with
71 additions
and
46 deletions
| ... | ... | @@ -62,46 +62,50 @@ $config = require __DIR__ . '/config.php'; |
| 62 | 62 | // Define Heartbeat Interval |
| 63 | 63 | define('HEARTBEAT_TIME', $config['heartbeat']['interval']); |
| 64 | 64 | |
| 65 | -// Database Connection | |
| 66 | -$pdo = null; | |
| 67 | -try { | |
| 68 | - $db_config = $config['database']; | |
| 69 | - $dsn = "mysql:host={$db_config['host']};port={$db_config['port']};dbname={$db_config['database']};charset=utf8mb4"; | |
| 70 | - $pdo = new PDO($dsn, $db_config['username'], $db_config['password'], [ | |
| 71 | - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, | |
| 72 | - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC | |
| 73 | - ]); | |
| 74 | - echo "✅ Connected to MySQL at {$db_config['host']}:{$db_config['port']}\n"; | |
| 75 | -} catch (Exception $e) { | |
| 76 | - echo "⚠️ MySQL Connection Failed: " . $e->getMessage() . "\n"; | |
| 77 | -} | |
| 78 | - | |
| 79 | -// Redis Connection | |
| 80 | -$redis = null; | |
| 81 | -try { | |
| 82 | - $redis_config = $config['redis']; | |
| 83 | - | |
| 84 | - $params = [ | |
| 85 | - 'scheme' => 'tcp', | |
| 86 | - 'host' => $redis_config['host'], | |
| 87 | - 'port' => $redis_config['port'], | |
| 88 | - ]; | |
| 65 | +// --------------------------------------------------------- | |
| 66 | +// Helper: Initialize Connections & Services | |
| 67 | +// --------------------------------------------------------- | |
| 68 | +$initConnections = function($config) { | |
| 69 | + // Database Connection | |
| 70 | + $pdo = null; | |
| 71 | + try { | |
| 72 | + $db_config = $config['database']; | |
| 73 | + $dsn = "mysql:host={$db_config['host']};port={$db_config['port']};dbname={$db_config['database']};charset=utf8mb4"; | |
| 74 | + $pdo = new PDO($dsn, $db_config['username'], $db_config['password'], [ | |
| 75 | + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, | |
| 76 | + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, | |
| 77 | + PDO::ATTR_TIMEOUT => 5, | |
| 78 | + ]); | |
| 79 | + echo "✅ Connected to MySQL at {$db_config['host']}:{$db_config['port']}\n"; | |
| 80 | + } catch (Exception $e) { | |
| 81 | + echo "⚠️ MySQL Connection Failed: " . $e->getMessage() . "\n"; | |
| 82 | + } | |
| 89 | 83 | |
| 90 | - if (!empty($redis_config['password'])) { | |
| 91 | - $params['password'] = $redis_config['password']; | |
| 84 | + // Redis Connection | |
| 85 | + $redis = null; | |
| 86 | + try { | |
| 87 | + $redis_config = $config['redis']; | |
| 88 | + $params = [ | |
| 89 | + 'scheme' => 'tcp', | |
| 90 | + 'host' => $redis_config['host'], | |
| 91 | + 'port' => $redis_config['port'], | |
| 92 | + ]; | |
| 93 | + if (!empty($redis_config['password'])) { | |
| 94 | + $params['password'] = $redis_config['password']; | |
| 95 | + } | |
| 96 | + $redis = new Predis\Client($params, ['prefix' => $redis_config['prefix']]); | |
| 97 | + $redis->connect(); | |
| 98 | + echo "✅ Connected to Redis at {$redis_config['host']}:{$redis_config['port']} ({$redis_config['prefix']})\n"; | |
| 99 | + } catch (Exception $e) { | |
| 100 | + echo "⚠️ Redis Connection Failed: " . $e->getMessage() . "\n"; | |
| 92 | 101 | } |
| 93 | 102 | |
| 94 | - // Predis Client | |
| 95 | - $redis = new Predis\Client($params, ['prefix' => $redis_config['prefix']]); | |
| 96 | - $redis->connect(); | |
| 97 | - echo "✅ Connected to Redis at {$redis_config['host']}:{$redis_config['port']} ({$redis_config['prefix']})\n"; | |
| 98 | -} catch (Exception $e) { | |
| 99 | - echo "⚠️ Redis Connection Failed: " . $e->getMessage() . "\n"; | |
| 100 | -} | |
| 103 | + // Initialize Services | |
| 104 | + $authService = $pdo ? new AuthService($pdo, $config, $redis) : null; | |
| 105 | + $deviceService = $pdo ? new DeviceService($pdo, $config) : null; | |
| 101 | 106 | |
| 102 | -// Initialize Services | |
| 103 | -$authService = $pdo ? new AuthService($pdo, $config, $redis) : null; | |
| 104 | -$deviceService = $pdo ? new DeviceService($pdo, $config) : null; | |
| 107 | + return [$pdo, $redis, $authService, $deviceService]; | |
| 108 | +}; | |
| 105 | 109 | |
| 106 | 110 | // Create a WebSocket worker |
| 107 | 111 | $ws_host = $config['server']['websocket_host']; |
| ... | ... | @@ -112,7 +116,11 @@ $ws_worker = new Worker("websocket://{$ws_host}:{$ws_port}"); |
| 112 | 116 | $clients = []; // ClientID -> Connection |
| 113 | 117 | $devices = []; // DeviceID -> Connection |
| 114 | 118 | |
| 115 | -$ws_worker->onWorkerStart = function ($worker) use ($config) { | |
| 119 | +$ws_worker->onWorkerStart = function ($worker) use ($config, $initConnections) { | |
| 120 | + // Each worker process needs its own connection | |
| 121 | + global $pdo, $redis, $authService, $deviceService; | |
| 122 | + list($pdo, $redis, $authService, $deviceService) = $initConnections($config); | |
| 123 | + | |
| 116 | 124 | $ws_host = $config['server']['websocket_host']; |
| 117 | 125 | $ws_port = $config['server']['websocket_port']; |
| 118 | 126 | echo "Relay Server Started on {$ws_host}:{$ws_port}\n"; |
| ... | ... | @@ -123,14 +131,23 @@ $ws_worker->onWorkerStart = function ($worker) use ($config) { |
| 123 | 131 | file_put_contents(__DIR__ . '/debug.log', $logMsg, FILE_APPEND); |
| 124 | 132 | echo $logMsg; // Keep echo just in case |
| 125 | 133 | |
| 126 | - // Heartbeat check | |
| 134 | + // MySQL Heartbeat to prevent "MySQL server has gone away" | |
| 135 | + Timer::add(60, function() use (&$pdo) { | |
| 136 | + if ($pdo) { | |
| 137 | + try { | |
| 138 | + $pdo->query('SELECT 1'); | |
| 139 | + } catch (Exception $e) { | |
| 140 | + // Connection lost, will attempt to reconnect on next needed activity if handled, | |
| 141 | + // but Workerman long-running processes prefer proactive ping | |
| 142 | + echo "⚠️ Database heartbeat failed: " . $e->getMessage() . "\n"; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + }); | |
| 146 | + | |
| 147 | + // Heartbeat check for connections | |
| 127 | 148 | $check_interval = $config['heartbeat']['check_interval']; |
| 128 | 149 | Timer::add($check_interval, function () use ($worker) { |
| 129 | - $time_now = time(); | |
| 130 | - foreach ($worker->connections as $connection) { | |
| 131 | - // Check if connection is alive possibly? | |
| 132 | - // Workerman handles basic disconnects, but we can enforce ping logic here if needed | |
| 133 | - } | |
| 150 | + // ...Existing connection check logic (if any) | |
| 134 | 151 | }); |
| 135 | 152 | }; |
| 136 | 153 | |
| ... | ... | @@ -139,7 +156,8 @@ $ws_worker->onConnect = function ($connection) { |
| 139 | 156 | $connection->authVerified = false; |
| 140 | 157 | }; |
| 141 | 158 | |
| 142 | -$ws_worker->onMessage = function ($connection, $data) use (&$clients, &$devices, $authService, $deviceService) { | |
| 159 | +$ws_worker->onMessage = function ($connection, $data) use (&$clients, &$devices, $config) { | |
| 160 | + global $authService, $deviceService; | |
| 143 | 161 | $msg = json_decode($data, true); |
| 144 | 162 | if (!$msg || !isset($msg['type'])) { |
| 145 | 163 | return; |
| ... | ... | @@ -280,7 +298,8 @@ $ws_worker->onMessage = function ($connection, $data) use (&$clients, &$devices, |
| 280 | 298 | } |
| 281 | 299 | }; |
| 282 | 300 | |
| 283 | -$ws_worker->onClose = function ($connection) use (&$clients, &$devices, $deviceService) { | |
| 301 | +$ws_worker->onClose = function ($connection) use (&$clients, &$devices) { | |
| 302 | + global $deviceService; | |
| 284 | 303 | if (isset($connection->role)) { |
| 285 | 304 | if ($connection->role === 'device' && isset($connection->deviceId)) { |
| 286 | 305 | unset($devices[$connection->deviceId]); |
| ... | ... | @@ -303,7 +322,13 @@ $http_host = $config['server']['http_host']; |
| 303 | 322 | $http_port = $config['server']['http_port']; |
| 304 | 323 | $http_worker = new Worker("http://{$http_host}:{$http_port}"); |
| 305 | 324 | $http_worker->count = $config['server']['worker_count']; |
| 306 | -$http_worker->onMessage = function ($connection, $request) use ($config, $authService, $deviceService) { | |
| 325 | +$http_worker->onWorkerStart = function($worker) use ($config, $initConnections) { | |
| 326 | + global $pdo, $redis, $authService, $deviceService; | |
| 327 | + list($pdo, $redis, $authService, $deviceService) = $initConnections($config); | |
| 328 | +}; | |
| 329 | + | |
| 330 | +$http_worker->onMessage = function ($connection, $request) use ($config) { | |
| 331 | + global $authService, $deviceService; | |
| 307 | 332 | $path = $request->path(); |
| 308 | 333 | $method = $request->method(); |
| 309 | 334 | ... | ... |
Please
register
or
login
to post a comment