1.优化websocket中的jackpot.hit
This commit is contained in:
@@ -94,7 +94,9 @@ final class GameWebSocketDispatcher
|
|||||||
}
|
}
|
||||||
if ($userScoped && $payloadUserId > 0) {
|
if ($userScoped && $payloadUserId > 0) {
|
||||||
$boundUid = GameWebSocketSubscriptionRegistry::userIdOf($cid);
|
$boundUid = GameWebSocketSubscriptionRegistry::userIdOf($cid);
|
||||||
if ($boundUid !== $payloadUserId) {
|
// admin/ws 联调场景:admin 连接在握手时绑定 user_id=0,允许观测所有 user-scoped topic(例如 bet.win)
|
||||||
|
// mobile 用户连接则必须严格匹配 data.user_id,避免泄露其它用户事件
|
||||||
|
if ($boundUid !== 0 && $boundUid !== $payloadUserId) {
|
||||||
$skippedNotOwner++;
|
$skippedNotOwner++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,20 +20,25 @@ final class GameWebSocketSubscriptionRegistry
|
|||||||
/** @var array<string, array<int, true>> topic => { connection_id: true } */
|
/** @var array<string, array<int, true>> topic => { connection_id: true } */
|
||||||
private static array $topicIndex = [];
|
private static array $topicIndex = [];
|
||||||
|
|
||||||
/** @var array<int, array{topics: list<string>, user_id: int, last_seen_at: int, remote_ip: string}> */
|
/** @var array<int, array{topics: list<string>, user_id: int, mode: string, last_seen_at: int, remote_ip: string}> */
|
||||||
private static array $connectionMeta = [];
|
private static array $connectionMeta = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册新连接(onConnect 调用)。
|
* 注册新连接(onConnect 调用)。
|
||||||
*/
|
*/
|
||||||
public static function registerConnection(int $connectionId, int $userId, string $remoteIp = ''): void
|
public static function registerConnection(int $connectionId, int $userId, string $mode = 'mobile', string $remoteIp = ''): void
|
||||||
{
|
{
|
||||||
if ($connectionId <= 0) {
|
if ($connectionId <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$mode = trim($mode);
|
||||||
|
if ($mode !== 'admin') {
|
||||||
|
$mode = 'mobile';
|
||||||
|
}
|
||||||
self::$connectionMeta[$connectionId] = [
|
self::$connectionMeta[$connectionId] = [
|
||||||
'topics' => [],
|
'topics' => [],
|
||||||
'user_id' => max(0, $userId),
|
'user_id' => max(0, $userId),
|
||||||
|
'mode' => $mode,
|
||||||
'last_seen_at' => time(),
|
'last_seen_at' => time(),
|
||||||
'remote_ip' => $remoteIp,
|
'remote_ip' => $remoteIp,
|
||||||
];
|
];
|
||||||
@@ -139,6 +144,11 @@ final class GameWebSocketSubscriptionRegistry
|
|||||||
return self::$connectionMeta[$connectionId]['user_id'] ?? 0;
|
return self::$connectionMeta[$connectionId]['user_id'] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isAdmin(int $connectionId): bool
|
||||||
|
{
|
||||||
|
return (self::$connectionMeta[$connectionId]['mode'] ?? '') === 'admin';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 找出所有 last_seen_at 早于 $cutoff 的连接 id(用于服务端主动关闭僵尸连接)。
|
* 找出所有 last_seen_at 早于 $cutoff 的连接 id(用于服务端主动关闭僵尸连接)。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -114,7 +114,12 @@ class GameWebSocketServer
|
|||||||
|
|
||||||
$connection->wsAuth = $auth;
|
$connection->wsAuth = $auth;
|
||||||
self::$connectionAuth[$connection->id] = $auth;
|
self::$connectionAuth[$connection->id] = $auth;
|
||||||
GameWebSocketSubscriptionRegistry::registerConnection($connection->id, (int) $auth['user_id'], $remoteIp);
|
GameWebSocketSubscriptionRegistry::registerConnection(
|
||||||
|
$connection->id,
|
||||||
|
(int) $auth['user_id'],
|
||||||
|
is_string($auth['mode'] ?? null) ? (string) $auth['mode'] : 'mobile',
|
||||||
|
$remoteIp
|
||||||
|
);
|
||||||
|
|
||||||
Log::channel('ws')->info('handshake ok', [
|
Log::channel('ws')->info('handshake ok', [
|
||||||
'connection_id' => $connection->id,
|
'connection_id' => $connection->id,
|
||||||
|
|||||||
@@ -95,6 +95,14 @@ GameLiveService::ensurePeriodDrawNotifications(
|
|||||||
|
|
||||||
$payloads = GameBetSettleService::buildBetWinPayloadsFromSettledOrders($periodId, $resultNumber);
|
$payloads = GameBetSettleService::buildBetWinPayloadsFromSettledOrders($periodId, $resultNumber);
|
||||||
if ($payloads !== []) {
|
if ($payloads !== []) {
|
||||||
|
// 同时触发 jackpot.hit(若 bet.win 判定为大奖则应广播);publishSettlementWinsAfterCommit 内含 jackpot.hit 独立去重与从 bet_wins 重建兜底
|
||||||
|
GameBetSettleService::publishSettlementWinsAfterCommit([
|
||||||
|
'jackpot_hits' => [],
|
||||||
|
'bet_wins' => $payloads,
|
||||||
|
'user_streak_events' => [],
|
||||||
|
'wallet_events' => [],
|
||||||
|
'settled_order_count' => 0,
|
||||||
|
], $periodId, $periodNo, $resultNumber);
|
||||||
GameBetSettleService::publishBetWinsAfterCommit($payloads, $periodId);
|
GameBetSettleService::publishBetWinsAfterCommit($payloads, $periodId);
|
||||||
echo 'bet.win republished for user_ids: ' . implode(',', array_map(static fn (array $p): int => (int) ($p['user_id'] ?? 0), $payloads)) . PHP_EOL;
|
echo 'bet.win republished for user_ids: ' . implode(',', array_map(static fn (array $p): int => (int) ($p['user_id'] ?? 0), $payloads)) . PHP_EOL;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user