1.优化游戏实时对局/admin/game/live页面卡顿的问题

This commit is contained in:
2026-05-26 13:42:34 +08:00
parent ae7af24565
commit 3a2af4d7c2
3 changed files with 95 additions and 51 deletions

View File

@@ -258,16 +258,16 @@ final class GameLiveService
self::publishSnapshot(null);
}
public static function buildSnapshot(?int $recordId = null, bool $freshFromDb = false): array
public static function buildSnapshot(?int $recordId = null): array
{
$record = $freshFromDb ? self::resolveRecordFromDb($recordId) : self::resolveRecord($recordId);
$record = self::resolveRecord($recordId);
if (!$record) {
return self::emptySnapshotPayload();
}
$rid = (int) $record['id'];
self::ensureAiLocked($rid);
$record = $freshFromDb ? self::reloadRecordFromDb($rid) : self::reloadRecord($rid);
$record = self::reloadRecord($rid);
if (!$record) {
return self::emptySnapshotPayload();
}
@@ -280,10 +280,12 @@ final class GameLiveService
$betRemaining = max(0, $betSeconds - $elapsed);
$status = (int) $record['status'];
$now = time();
$payoutUntil = isset($record['payout_until']) ? (int) $record['payout_until'] : 0;
$payoutRemaining = 0;
if ($status === 3 && $payoutUntil > 0) {
$payoutRemaining = max(0, $payoutUntil - time());
$isPayoutPhase = $status === 3 && $payoutUntil > $now;
if ($isPayoutPhase) {
$payoutRemaining = $payoutUntil - $now;
}
$bets = Db::name('bet_order')
@@ -328,9 +330,8 @@ final class GameLiveService
&& $elapsed < $periodSeconds;
$runtimeEnabled = GameRecordService::isLiveRuntimeEnabled();
$hasActiveRound = GameRecordService::hasActiveRecord();
/** 关服且已无进行中局:派彩结束后的「完整维护」态(仅此时展示维护中 UI */
$maintenanceUi = !$runtimeEnabled && !$hasActiveRound;
$maintenanceUi = !$runtimeEnabled && !in_array($status, [0, 1, 2, 3], true);
return [
'record' => $record,
@@ -357,14 +358,14 @@ final class GameLiveService
'remaining_seconds' => $remaining,
'bet_remaining_seconds' => $betRemaining,
'payout_remaining_seconds' => $payoutRemaining,
'is_payout_phase' => $status === 3,
'is_payout_phase' => $isPayoutPhase,
'runtime_enabled' => $runtimeEnabled,
'maintenance_ui' => $maintenanceUi,
/** 关闭游戏(维护)时仍允许完成当局、计算与预约开奖;仅阻止新用户下注与结束后自动开新期 */
'can_calculate' => $canCalculate,
'can_draw' => $canScheduleDraw,
'can_schedule_draw' => $canScheduleDraw,
'server_time' => time(),
'server_time' => $now,
];
}
@@ -374,7 +375,8 @@ final class GameLiveService
private static function emptySnapshotPayload(): array
{
$runtimeEnabled = GameRecordService::isLiveRuntimeEnabled();
$hasActiveRound = GameRecordService::hasActiveRecord();
$active = GameHotDataRedis::gameRecordActive();
$hasActiveRound = is_array($active) && in_array((int) ($active['status'] ?? -1), [0, 1, 2, 3], true);
$maintenanceUi = !$runtimeEnabled && !$hasActiveRound;
return [
@@ -655,10 +657,10 @@ final class GameLiveService
*/
public static function finalizePayoutGrace(): void
{
$now = time();
$row = Db::name('game_record')
->where('status', 3)
->where('payout_until', '>', 0)
->where('payout_until', '<=', time())
->whereRaw('((payout_until > 0 AND payout_until <= ?) OR payout_until IS NULL OR payout_until = 0)', [$now])
->order('id', 'desc')
->find();
if (!$row) {
@@ -690,8 +692,6 @@ final class GameLiveService
}
GameHotDataCoordinator::afterGameRecordCommitted($id);
GameRecordStatService::refreshForRecordId($id);
GameHotDataRedis::gameRecordForget($id);
GameHotDataRedis::gameRecordForget(null);
self::publishPublicPeriodFinished($id, $periodNo, $resultNumber);
self::publishSnapshot(null);
self::publishImmediateBettingTickAfterFinalize();
@@ -893,7 +893,7 @@ final class GameLiveService
public static function publishSnapshot(?int $recordId = null): void
{
$snapshot = self::buildSnapshot($recordId, true);
$snapshot = self::buildSnapshot($recordId);
self::publishPublicPeriodPayoutCountdown($snapshot);
self::publishPublicPeriodTick($snapshot);
}
@@ -943,7 +943,7 @@ final class GameLiveService
*/
private static function publishImmediateBettingTickAfterFinalize(): void
{
$record = self::resolveRecordFromDb(null);
$record = GameHotDataRedis::gameRecordActive();
if (!is_array($record)) {
return;
}
@@ -1177,44 +1177,12 @@ final class GameLiveService
return GameHotDataRedis::gameRecordActive();
}
/**
* WebSocket 推送专用:始终读库,避免 game_record 热缓存仍指向上一期 payouting 导致长时间不推 period.tick。
*
* @return array<string, mixed>|null
*/
private static function resolveRecordFromDb(?int $recordId): ?array
{
if ($recordId !== null && $recordId > 0) {
$row = Db::name('game_record')->where('id', $recordId)->find();
return is_array($row) ? $row : null;
}
$row = Db::name('game_record')
->whereIn('status', [0, 1, 2, 3])
->order('id', 'desc')
->find();
return is_array($row) ? $row : null;
}
private static function reloadRecord(int $id): ?array
{
$row = GameHotDataRedis::gameRecordById($id);
return $row ?: null;
}
/**
* @return array<string, mixed>|null
*/
private static function reloadRecordFromDb(int $id): ?array
{
if ($id <= 0) {
return null;
}
$row = Db::name('game_record')->where('id', $id)->find();
return is_array($row) ? $row : null;
}
/**
* 封盘后计算并锁定 AI 号码本期不变并封盘status 0→1
*/