1.修复游戏实时对局/admin/game/live页面的报错
This commit is contained in:
@@ -151,6 +151,48 @@ final class GameHotDataRedis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 派彩宽限期已结束但缓存仍为 status=3(导致页面倒计时 0、无法开新期)。
|
||||||
|
*/
|
||||||
|
public static function isExpiredPayoutRecord(array $row): bool
|
||||||
|
{
|
||||||
|
if ((int) ($row['status'] ?? -1) !== 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$until = (int) ($row['payout_until'] ?? 0);
|
||||||
|
|
||||||
|
return $until <= 0 || $until <= time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下注/封盘期缓存与库不一致或已超时未开奖(period_start 过久仍为 0/1)。
|
||||||
|
*/
|
||||||
|
public static function isStaleOpenPeriodRecord(array $row, int $periodSeconds): bool
|
||||||
|
{
|
||||||
|
$st = (int) ($row['status'] ?? -1);
|
||||||
|
if (!in_array($st, [0, 1], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$start = (int) ($row['period_start_at'] ?? 0);
|
||||||
|
if ($start <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return time() - $start > $periodSeconds + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存行疑似过期时,按库回写 Redis 后再由调用方重新读取。
|
||||||
|
*/
|
||||||
|
public static function gameRecordRevalidateFromDbIfStale(array $row, int $periodSeconds = 30): void
|
||||||
|
{
|
||||||
|
if (!self::isExpiredPayoutRecord($row) && !self::isStaleOpenPeriodRecord($row, $periodSeconds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$id = (int) ($row['id'] ?? 0);
|
||||||
|
self::gameRecordSyncCachesAfterDbWrite($id > 0 ? $id : null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>|null
|
* @return array<string, mixed>|null
|
||||||
*/
|
*/
|
||||||
@@ -165,7 +207,11 @@ final class GameHotDataRedis
|
|||||||
if ($cached !== null && $cached !== '') {
|
if ($cached !== null && $cached !== '') {
|
||||||
$decoded = json_decode($cached, true);
|
$decoded = json_decode($cached, true);
|
||||||
if (is_array($decoded)) {
|
if (is_array($decoded)) {
|
||||||
return $decoded;
|
if (self::isExpiredPayoutRecord($decoded)) {
|
||||||
|
self::gameRecordSyncCachesAfterDbWrite($id);
|
||||||
|
} else {
|
||||||
|
return $decoded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,7 +238,11 @@ final class GameHotDataRedis
|
|||||||
if ($cached !== null && $cached !== '') {
|
if ($cached !== null && $cached !== '') {
|
||||||
$decoded = json_decode($cached, true);
|
$decoded = json_decode($cached, true);
|
||||||
if (is_array($decoded)) {
|
if (is_array($decoded)) {
|
||||||
return $decoded;
|
if (self::isExpiredPayoutRecord($decoded)) {
|
||||||
|
self::gameRecordRefreshAggregateCaches();
|
||||||
|
} else {
|
||||||
|
return $decoded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -261,6 +261,15 @@ final class GameLiveService
|
|||||||
public static function buildSnapshot(?int $recordId = null): array
|
public static function buildSnapshot(?int $recordId = null): array
|
||||||
{
|
{
|
||||||
$record = self::resolveRecord($recordId);
|
$record = self::resolveRecord($recordId);
|
||||||
|
if ($record) {
|
||||||
|
$periodSeconds = self::getConfigInt(self::KEY_PERIOD_SECONDS, 30);
|
||||||
|
GameHotDataRedis::gameRecordRevalidateFromDbIfStale($record, $periodSeconds);
|
||||||
|
$record = self::resolveRecord($recordId);
|
||||||
|
}
|
||||||
|
if ($record && GameHotDataRedis::isExpiredPayoutRecord($record)) {
|
||||||
|
self::finalizePayoutGrace();
|
||||||
|
$record = self::resolveRecord($recordId);
|
||||||
|
}
|
||||||
if (!$record) {
|
if (!$record) {
|
||||||
return self::emptySnapshotPayload();
|
return self::emptySnapshotPayload();
|
||||||
}
|
}
|
||||||
@@ -684,10 +693,14 @@ final class GameLiveService
|
|||||||
'payout_until' => null,
|
'payout_until' => null,
|
||||||
'update_time' => time(),
|
'update_time' => time(),
|
||||||
]);
|
]);
|
||||||
GameRecordService::createNextRecordAfterDraw();
|
if (GameRecordService::isLiveRuntimeEnabled()) {
|
||||||
|
GameRecordService::createNextRecordRow();
|
||||||
|
}
|
||||||
Db::commit();
|
Db::commit();
|
||||||
} catch (Throwable) {
|
} catch (Throwable $e) {
|
||||||
Db::rollback();
|
Db::rollback();
|
||||||
|
Log::warning('finalizePayoutGrace failed: ' . $e->getMessage(), ['record_id' => $id]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GameHotDataCoordinator::afterGameRecordCommitted($id);
|
GameHotDataCoordinator::afterGameRecordCommitted($id);
|
||||||
@@ -915,12 +928,15 @@ final class GameLiveService
|
|||||||
if ($payoutUntil === false || $payoutUntil <= 0) {
|
if ($payoutUntil === false || $payoutUntil <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$now = time();
|
||||||
|
if ($payoutUntil <= $now) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$periodId = filter_var($record['id'] ?? 0, FILTER_VALIDATE_INT);
|
$periodId = filter_var($record['id'] ?? 0, FILTER_VALIDATE_INT);
|
||||||
if ($periodId === false) {
|
if ($periodId === false) {
|
||||||
$periodId = 0;
|
$periodId = 0;
|
||||||
}
|
}
|
||||||
$periodNo = is_string($record['period_no'] ?? null) ? (string) $record['period_no'] : '';
|
$periodNo = is_string($record['period_no'] ?? null) ? (string) $record['period_no'] : '';
|
||||||
$now = time();
|
|
||||||
$resultNumber = null;
|
$resultNumber = null;
|
||||||
$resultParsed = filter_var($record['result_number'] ?? null, FILTER_VALIDATE_INT);
|
$resultParsed = filter_var($record['result_number'] ?? null, FILTER_VALIDATE_INT);
|
||||||
if ($resultParsed !== false && $resultParsed > 0) {
|
if ($resultParsed !== false && $resultParsed > 0) {
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ final class GameRecordService
|
|||||||
self::upsertConfig(self::KEY_AUTO_CREATE, $v, 'int', '是否允许自动创建下一局(全局仅一局)', $now);
|
self::upsertConfig(self::KEY_AUTO_CREATE, $v, 'int', '是否允许自动创建下一局(全局仅一局)', $now);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function createNextRecordRow(): string
|
/**
|
||||||
|
* 派彩结单后插入新一期(调用方须已保证无其它进行中局)。
|
||||||
|
*/
|
||||||
|
public static function createNextRecordRow(): string
|
||||||
{
|
{
|
||||||
$periodNo = self::generatePeriodNo();
|
$periodNo = self::generatePeriodNo();
|
||||||
$now = time();
|
$now = time();
|
||||||
|
|||||||
Reference in New Issue
Block a user