1.优化ws中的jackpot.hit
This commit is contained in:
@@ -35,6 +35,9 @@ final class GameBetSettleService
|
|||||||
/** 每期每用户 bet.win 去重(与 streak/wallet 分离,避免整期 dedup 吞掉中奖推送) */
|
/** 每期每用户 bet.win 去重(与 streak/wallet 分离,避免整期 dedup 吞掉中奖推送) */
|
||||||
private const BET_WIN_NOTIFY_DEDUP_PREFIX = 'dfw:v1:ws:betwin:';
|
private const BET_WIN_NOTIFY_DEDUP_PREFIX = 'dfw:v1:ws:betwin:';
|
||||||
|
|
||||||
|
/** jackpot.hit 去重(独立于 settleNotify,避免 recover/补偿路径漏广播) */
|
||||||
|
private const JACKPOT_HIT_DEDUP_PREFIX = 'dfw:v1:ws:jackpot_hit:';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对指定期次按开奖号码结算所有「待开奖」注单;同一注单幂等(仅 status=1 会更新)。
|
* 对指定期次按开奖号码结算所有「待开奖」注单;同一注单幂等(仅 status=1 会更新)。
|
||||||
*
|
*
|
||||||
@@ -435,13 +438,40 @@ final class GameBetSettleService
|
|||||||
if ($jackpotHits === [] || $periodId <= 0 || $resultNumber < 1) {
|
if ($jackpotHits === [] || $periodId <= 0 || $resultNumber < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GameWebSocketEventBus::publish(self::TOPIC_JACKPOT_HIT, [
|
$dedupKey = self::JACKPOT_HIT_DEDUP_PREFIX . $periodId;
|
||||||
|
try {
|
||||||
|
$already = Redis::get($dedupKey);
|
||||||
|
if ($already !== false && $already !== null && $already !== '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (Throwable) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
$ok = GameWebSocketEventBus::publish(self::TOPIC_JACKPOT_HIT, [
|
||||||
'period_id' => $periodId,
|
'period_id' => $periodId,
|
||||||
'period_no' => $periodNo,
|
'period_no' => $periodNo,
|
||||||
'result_number' => $resultNumber,
|
'result_number' => $resultNumber,
|
||||||
'hits' => $jackpotHits,
|
'hits' => $jackpotHits,
|
||||||
'server_time' => time(),
|
'server_time' => time(),
|
||||||
]);
|
]);
|
||||||
|
if ($ok) {
|
||||||
|
try {
|
||||||
|
Redis::setEx($dedupKey, 86400, '1');
|
||||||
|
} catch (Throwable) {
|
||||||
|
}
|
||||||
|
Log::channel('ws')->info('jackpot.hit published', [
|
||||||
|
'period_id' => $periodId,
|
||||||
|
'period_no' => $periodNo,
|
||||||
|
'result_number' => $resultNumber,
|
||||||
|
'hit_count' => count($jackpotHits),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
Log::channel('ws')->warning('jackpot.hit publish failed', [
|
||||||
|
'period_id' => $periodId,
|
||||||
|
'period_no' => $periodNo,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -473,6 +503,10 @@ final class GameBetSettleService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// jackpot.hit 独立去重:即使 settleNotify 已被占位(recover/补偿路径)也允许补广播一次
|
||||||
|
$jackpotHits = is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [];
|
||||||
|
self::publishJackpotHitsAfterCommit($jackpotHits, $periodId, $periodNo, $resultNumber);
|
||||||
|
|
||||||
if (($settledCount !== false && $settledCount > 0) || $hasStreak || $hasWallet) {
|
if (($settledCount !== false && $settledCount > 0) || $hasStreak || $hasWallet) {
|
||||||
if (self::markSettlementNotifyOnce($periodId)) {
|
if (self::markSettlementNotifyOnce($periodId)) {
|
||||||
$streakEvents = is_array($settleOut['user_streak_events'] ?? null) ? $settleOut['user_streak_events'] : [];
|
$streakEvents = is_array($settleOut['user_streak_events'] ?? null) ? $settleOut['user_streak_events'] : [];
|
||||||
@@ -500,9 +534,6 @@ final class GameBetSettleService
|
|||||||
}
|
}
|
||||||
GameWebSocketEventBus::publish('wallet.changed', GameWebSocketPayloadHelper::mergeUserStreakInto($payload, $userId));
|
GameWebSocketEventBus::publish('wallet.changed', GameWebSocketPayloadHelper::mergeUserStreakInto($payload, $userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
$jackpotHits = is_array($settleOut['jackpot_hits'] ?? null) ? $settleOut['jackpot_hits'] : [];
|
|
||||||
self::publishJackpotHitsAfterCommit($jackpotHits, $periodId, $periodNo, $resultNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,8 +125,17 @@ final class GameWebSocketPayloadHelper
|
|||||||
if ($userId <= 0) {
|
if ($userId <= 0) {
|
||||||
return $payload;
|
return $payload;
|
||||||
}
|
}
|
||||||
|
// 注意:部分业务事件(尤其 bet.win)的 is_jackpot 语义为“本期中奖是否大奖”,
|
||||||
|
// 而赔率字段 is_jackpot 语义为“下一注下注是否处于大奖档”。二者字段名相同但语义不同,
|
||||||
|
// 这里以 payload 里已有字段为准,避免被 userStreakData 覆盖导致“1胜被误判为中大奖”。
|
||||||
|
$streak = self::userStreakData($userId, $currentStreak);
|
||||||
|
foreach ($streak as $k => $v) {
|
||||||
|
if (!array_key_exists($k, $payload)) {
|
||||||
|
$payload[$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return array_merge($payload, self::userStreakData($userId, $currentStreak));
|
return $payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user