1.ws优化订阅,修复中大奖没有推送

This commit is contained in:
2026-05-27 10:40:55 +08:00
parent 8f5ba977a4
commit a96aa0fb41
3 changed files with 241 additions and 13 deletions

View File

@@ -114,27 +114,43 @@ foreach ($records as $gr) {
continue;
}
echo " -- bet.win dedup keys --\n";
foreach (array_keys($winUserIds) as $uid) {
$key = 'dfw:v1:ws:betwin:' . $pid . ':' . $uid;
echo " -- draw / bet.win dedup keys --\n";
foreach (['dfw:v1:ws:period_opened:' . $pid => 'period.opened', 'dfw:v1:ws:period_payout:' . $pid => 'period.payout'] as $key => $label) {
try {
$val = Redis::get($key);
$ttl = Redis::ttl($key);
} catch (\Throwable $e) {
} catch (\Throwable) {
$val = false;
$ttl = -2;
}
$exists = ($val !== false && $val !== null && $val !== '');
echo sprintf(
" %s user=%d exists=%s ttl=%s %s\n",
$key,
" %s exists=%s ttl=%s %s\n",
$label,
$exists ? 'YES' : 'NO',
(string) $ttl,
$exists ? '(已推送)' : '(未推送)'
);
}
foreach (array_keys($winUserIds) as $uid) {
$key = 'dfw:v1:ws:betwin:' . $pid . ':' . $uid;
try {
$val = Redis::get($key);
$ttl = Redis::ttl($key);
} catch (\Throwable) {
$val = false;
$ttl = -2;
}
$exists = ($val !== false && $val !== null && $val !== '');
echo sprintf(
" bet.win user=%d exists=%s ttl=%s %s\n",
$uid,
$exists ? 'YES' : 'NO',
(string) $ttl,
$exists ? '(已推送)' : '(未推送 → 重启 webman 后用 republish_bet_win.php 补发)'
$exists ? '(已推送)' : '(未推送)'
);
}
echo "\n";
}
echo "如需补发php scripts/republish_bet_win.php --period-no=<no> --force\n";
echo "补发php scripts/republish_period_draw.php --period-no=<no> --force\n";

View File

@@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
/**
* 补发本期开奖推送period.opened + period.payout + bet.win已结算中奖用户
*
* 用法(在生产服务器执行,需 Redis 与 gameWebSocketServer 同机):
* php scripts/republish_period_draw.php --period-no=20260527-103109-7fbbbb5e
* php scripts/republish_period_draw.php --play-record-id=1388
* php scripts/republish_period_draw.php --period-id=74992 --force
*/
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../support/bootstrap.php';
use app\common\service\GameBetSettleService;
use app\common\service\GameLiveService;
use support\Redis;
use support\think\Db;
$opts = getopt('', ['period-id:', 'play-record-id:', 'period-no:', 'force']);
$force = array_key_exists('force', $opts);
$periodId = isset($opts['period-id']) ? (int) $opts['period-id'] : 0;
if (isset($opts['play-record-id'])) {
$playId = (int) $opts['play-record-id'];
if ($playId > 0) {
$pid = Db::name('game_play_record')->where('id', $playId)->value('period_id');
$periodId = is_numeric((string) $pid) ? (int) $pid : 0;
echo "play_record_id={$playId} => period_id={$periodId}" . PHP_EOL;
}
}
if ($periodId <= 0 && isset($opts['period-no'])) {
$periodNo = trim((string) $opts['period-no']);
if ($periodNo !== '') {
$pid = Db::name('game_record')->where('period_no', $periodNo)->value('id');
$periodId = is_numeric((string) $pid) ? (int) $pid : 0;
echo "period_no={$periodNo} => period_id={$periodId}" . PHP_EOL;
}
}
if ($periodId <= 0) {
fwrite(STDERR, "请指定 --period-id、--play-record-id 或 --period-no\n");
exit(1);
}
$row = Db::name('game_record')->where('id', $periodId)->find();
if (!is_array($row)) {
fwrite(STDERR, "对局不存在: period_id={$periodId}\n");
exit(1);
}
$resultNumber = filter_var($row['result_number'] ?? 0, FILTER_VALIDATE_INT);
if ($resultNumber === false || $resultNumber < 1) {
fwrite(STDERR, "对局尚未开奖,无法补发\n");
exit(1);
}
$periodNo = (string) ($row['period_no'] ?? '');
$drawMode = filter_var($row['draw_mode'] ?? 0, FILTER_VALIDATE_INT);
$payoutUntil = filter_var($row['payout_until'] ?? 0, FILTER_VALIDATE_INT);
$openTime = filter_var($row['update_time'] ?? time(), FILTER_VALIDATE_INT);
if ($openTime === false || $openTime <= 0) {
$openTime = time();
}
if ($force) {
try {
Redis::del('dfw:v1:ws:period_opened:' . $periodId);
Redis::del('dfw:v1:ws:period_payout:' . $periodId);
} catch (Throwable) {
}
$payloads = GameBetSettleService::buildBetWinPayloadsFromSettledOrders($periodId, $resultNumber);
foreach ($payloads as $payload) {
$uid = (int) ($payload['user_id'] ?? 0);
if ($uid > 0) {
try {
Redis::del('dfw:v1:ws:betwin:' . $periodId . ':' . $uid);
} catch (Throwable) {
}
}
}
echo "已清除 dedup 键(--force\n";
}
GameLiveService::ensurePeriodDrawNotifications(
$periodId,
$periodNo,
$resultNumber,
$drawMode === false ? 0 : $drawMode,
$payoutUntil !== false && $payoutUntil > 0 ? $payoutUntil : time(),
$openTime
);
$payloads = GameBetSettleService::buildBetWinPayloadsFromSettledOrders($periodId, $resultNumber);
if ($payloads !== []) {
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;
} else {
echo "本期无已结算中奖注单。\n";
}
echo "done period_id={$periodId} period_no={$periodNo} result={$resultNumber}\n";