This commit is contained in:
2026-02-18 19:41:03 +08:00
parent a0c2350662
commit 6543e2ccdd
18 changed files with 4885 additions and 1196 deletions

View File

@@ -21,6 +21,16 @@ class WebSocketHandler implements WebSocketHandlerInterface
*/
protected $userOnlineService;
/**
* Get wsTable instance
*
* @return \Swoole\Table
*/
protected function getWsTable(): \Swoole\Table
{
return app('swoole')->wsTable;
}
/**
* WebSocketHandler constructor
*/
@@ -54,12 +64,12 @@ class WebSocketHandler implements WebSocketHandlerInterface
if ($userId && $token) {
// Store user connection mapping
$server->wsTable->set('uid:' . $userId, [
$this->getWsTable()->set('uid:' . $userId, [
'value' => $fd,
'expiry' => time() + 3600, // 1 hour expiry
]);
$server->wsTable->set('fd:' . $fd, [
$this->getWsTable()->set('fd:' . $fd, [
'value' => $userId,
'expiry' => time() + 3600
]);
@@ -231,7 +241,7 @@ class WebSocketHandler implements WebSocketHandlerInterface
$token = $data['token'] ?? null;
// Get the user ID from wsTable (set during connection)
$storedUserId = $server->wsTable->get('fd:' . $fd)['value'] ?? null;
$storedUserId = $this->getWsTable()->get('fd:' . $fd)['value'] ?? null;
if ($storedUserId && $storedUserId == $userId) {
// Authentication confirmed, send success response
@@ -291,13 +301,13 @@ class WebSocketHandler implements WebSocketHandlerInterface
}
// Get target user's connection
$targetFd = $server->wsTable->get('uid:' . $toUserId);
$targetFd = $this->getWsTable()->get('uid:' . $toUserId);
if ($targetFd && $targetFd['value']) {
$server->push((int)$targetFd['value'], json_encode([
'type' => 'chat',
'data' => [
'from_user_id' => $server->wsTable->get('fd:' . $fd)['value'] ?? null,
'from_user_id' => $this->getWsTable()->get('fd:' . $fd)['value'] ?? null,
'content' => $content,
'timestamp' => time()
]
@@ -334,7 +344,7 @@ class WebSocketHandler implements WebSocketHandlerInterface
protected function handleBroadcast(Server $server, int $fd, array $data): void
{
$message = $data['message'] ?? '';
$userId = $server->wsTable->get('fd:' . $fd)['value'] ?? null;
$userId = $this->getWsTable()->get('fd:' . $fd)['value'] ?? null;
// TODO: Check if user has admin permission to broadcast
// For now, allow any authenticated user
@@ -400,7 +410,7 @@ class WebSocketHandler implements WebSocketHandlerInterface
}
// Store subscription in wsTable
$server->wsTable->set('channel:' . $channel . ':fd:' . $fd, [
$this->getWsTable()->set('channel:' . $channel . ':fd:' . $fd, [
'value' => 1,
'expiry' => time() + 7200 // 2 hours
]);
@@ -443,7 +453,7 @@ class WebSocketHandler implements WebSocketHandlerInterface
}
// Remove subscription from wsTable
$server->wsTable->del('channel:' . $channel . ':fd:' . $fd);
$this->getWsTable()->del('channel:' . $channel . ':fd:' . $fd);
$server->push($fd, json_encode([
'type' => 'unsubscribed',
@@ -476,12 +486,12 @@ class WebSocketHandler implements WebSocketHandlerInterface
]);
// Get user ID from wsTable
$userId = $server->wsTable->get('fd:' . $fd)['value'] ?? null;
$userId = $this->getWsTable()->get('fd:' . $fd)['value'] ?? null;
if ($userId) {
// Remove user connection mapping
$server->wsTable->del('uid:' . $userId);
$server->wsTable->del('fd:' . $fd);
$this->getWsTable()->del('uid:' . $userId);
$this->getWsTable()->del('fd:' . $fd);
// Update user online status
$this->userOnlineService->updateUserOnlineStatus($userId, $fd, false);

View File

@@ -50,12 +50,14 @@ class WebSocketService
{
$server = $this->getServer();
if (!$server || !isset($server->wsTable)) {
if (!$server) {
Log::warning('WebSocket server not available', ['user_id' => $userId]);
return false;
}
$fdInfo = $server->wsTable->get('uid:' . $userId);
$wsTable = app('swoole')->wsTable;
$fdInfo = $wsTable->get('uid:' . $userId);
if (!$fdInfo || !$fdInfo['value']) {
Log::info('User not connected to WebSocket', ['user_id' => $userId]);
@@ -67,8 +69,8 @@ class WebSocketService
if (!$server->isEstablished($fd)) {
Log::info('WebSocket connection not established', ['user_id' => $userId, 'fd' => $fd]);
// Clean up stale connection
$server->wsTable->del('uid:' . $userId);
$server->wsTable->del('fd:' . $fd);
$wsTable->del('uid:' . $userId);
$wsTable->del('fd:' . $fd);
return false;
}
@@ -119,6 +121,7 @@ class WebSocketService
return 0;
}
$wsTable = app('swoole')->wsTable;
$message = json_encode($data);
$count = 0;
@@ -129,7 +132,7 @@ class WebSocketService
// Check if we should exclude this user
if ($excludeUserId) {
$fdInfo = $server->wsTable->get('fd:' . $fd);
$fdInfo = $wsTable->get('fd:' . $fd);
if ($fdInfo && $fdInfo['value'] == $excludeUserId) {
continue;
}
@@ -159,11 +162,12 @@ class WebSocketService
{
$server = $this->getServer();
if (!$server || !isset($server->wsTable)) {
if (!$server) {
Log::warning('WebSocket server not available for channel broadcast', ['channel' => $channel]);
return 0;
}
$wsTable = app('swoole')->wsTable;
$count = 0;
$message = json_encode($data);
@@ -173,7 +177,7 @@ class WebSocketService
continue;
}
$subscription = $server->wsTable->get('channel:' . $channel . ':fd:' . $fd);
$subscription = $wsTable->get('channel:' . $channel . ':fd:' . $fd);
if ($subscription) {
$server->push($fd, $message);
@@ -224,11 +228,13 @@ class WebSocketService
{
$server = $this->getServer();
if (!$server || !isset($server->wsTable)) {
if (!$server) {
return false;
}
$fdInfo = $server->wsTable->get('uid:' . $userId);
$wsTable = app('swoole')->wsTable;
$fdInfo = $wsTable->get('uid:' . $userId);
if (!$fdInfo || !$fdInfo['value']) {
return false;
@@ -249,11 +255,13 @@ class WebSocketService
{
$server = $this->getServer();
if (!$server || !isset($server->wsTable)) {
if (!$server) {
return false;
}
$fdInfo = $server->wsTable->get('uid:' . $userId);
$wsTable = app('swoole')->wsTable;
$fdInfo = $wsTable->get('uid:' . $userId);
if (!$fdInfo || !$fdInfo['value']) {
return false;
@@ -274,8 +282,8 @@ class WebSocketService
$server->disconnect($fd);
// Clean up
$server->wsTable->del('uid:' . $userId);
$server->wsTable->del('fd:' . $fd);
$wsTable->del('uid:' . $userId);
$wsTable->del('fd:' . $fd);
Log::info('User disconnected from WebSocket by server', [
'user_id' => $userId,
@@ -297,10 +305,12 @@ class WebSocketService
{
$server = $this->getServer();
if (!$server || !isset($server->wsTable)) {
if (!$server) {
return [];
}
$wsTable = app('swoole')->wsTable;
$userIds = [];
foreach ($server->connections as $fd) {
@@ -308,7 +318,7 @@ class WebSocketService
continue;
}
$fdInfo = $server->wsTable->get('fd:' . $fd);
$fdInfo = $wsTable->get('fd:' . $fd);
if ($fdInfo && $fdInfo['value']) {
$userIds[] = (int)$fdInfo['value'];