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

This commit is contained in:
2026-05-27 09:47:42 +08:00
parent 4c69a8c77f
commit a7c2a29764
3 changed files with 151 additions and 16 deletions

View File

@@ -5,17 +5,136 @@ declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../support/bootstrap.php';
use support\Redis;
use support\think\Db;
$periodNo = $argv[1] ?? '20260526-190442-c340448b';
$gr = Db::name('game_record')->where('period_no', $periodNo)->find();
if (!is_array($gr)) {
fwrite(STDERR, "period not found: {$periodNo}\n");
exit(1);
/**
* bet.win 推送链路诊断脚本(线上排查专用)。
*
* 用法:
* php scripts/debug_period_bet_win.php # 默认查最近 5 期
* php scripts/debug_period_bet_win.php <period_no> # 指定单期
* php scripts/debug_period_bet_win.php --recent=10 # 查最近 N 期
*
* 输出维度:
* 1) 期次基本信息(开奖号、状态)
* 2) 中奖注单user_id / win_amount / status
* 3) Redis bet.win 去重键dfw:v1:ws:betwin:{period_id}:{user_id}
* —— 若库内有中奖、Redis 无键 ⇒ publish 未执行(请重启 webman + 看 runtime/logs 是否有 'bet.win published'
* 4) Redis 事件队列 dfw:v1:ws:event:queue 当前 bet.win 待消费数(>0 说明 WS 消费滞后或进程未启动)
*/
$argvList = $argv;
array_shift($argvList);
$periodNo = '';
$recent = 0;
foreach ($argvList as $a) {
if (str_starts_with($a, '--recent=')) {
$recent = max(1, (int) substr($a, 9));
continue;
}
if ($a !== '' && $a[0] !== '-') {
$periodNo = $a;
}
}
$pid = (int) $gr['id'];
$bets = Db::name('bet_order')->where('period_id', $pid)->select()->toArray();
echo "period_id={$pid} status={$gr['status']} result={$gr['result_number']}\n";
foreach ($bets as $b) {
echo "bet {$b['id']} user={$b['user_id']} status={$b['status']} win={$b['win_amount']}\n";
if ($periodNo === '' && $recent === 0) {
$recent = 5;
}
$queueKey = 'dfw:v1:ws:event:queue';
try {
$queueLen = (int) Redis::lLen($queueKey);
} catch (\Throwable $e) {
$queueLen = -1;
}
echo "[redis] {$queueKey} length = {$queueLen}\n";
if ($queueLen > 0) {
try {
$sample = Redis::lRange($queueKey, 0, 49);
$betWinPending = 0;
if (is_array($sample)) {
foreach ($sample as $raw) {
if (is_string($raw) && str_contains($raw, '"bet.win"')) {
$betWinPending++;
}
}
}
echo "[redis] bet.win pending in first 50 = {$betWinPending}\n";
} catch (\Throwable) {
}
}
echo "\n";
$records = [];
if ($periodNo !== '') {
$row = Db::name('game_record')->where('period_no', $periodNo)->find();
if (!is_array($row)) {
fwrite(STDERR, "period not found: {$periodNo}\n");
exit(1);
}
$records[] = $row;
} else {
$records = Db::name('game_record')
->whereIn('status', [2, 3, 4])
->whereNotNull('result_number')
->order('id', 'desc')
->limit($recent)
->select()
->toArray();
}
foreach ($records as $gr) {
$pid = (int) ($gr['id'] ?? 0);
$rn = (int) ($gr['result_number'] ?? 0);
$status = (int) ($gr['status'] ?? 0);
$pno = (string) ($gr['period_no'] ?? '');
echo "==== period_id={$pid} no={$pno} status={$status} result={$rn} ====\n";
$bets = Db::name('bet_order')
->where('period_id', $pid)
->order('id', 'asc')
->select()
->toArray();
$winUserIds = [];
foreach ($bets as $b) {
$win = (string) ($b['win_amount'] ?? '0');
$uid = (int) ($b['user_id'] ?? 0);
$bs = (int) ($b['status'] ?? 0);
$tag = bccomp($win, '0', 2) > 0 ? 'WIN' : '----';
echo sprintf(" bet=%d user=%d status=%d win=%s [%s]\n", (int) ($b['id'] ?? 0), $uid, $bs, $win, $tag);
if ($tag === 'WIN' && $uid > 0) {
$winUserIds[$uid] = true;
}
}
if ($winUserIds === []) {
echo " (no winners)\n\n";
continue;
}
echo " -- bet.win dedup keys --\n";
foreach (array_keys($winUserIds) as $uid) {
$key = 'dfw:v1:ws:betwin:' . $pid . ':' . $uid;
try {
$val = Redis::get($key);
$ttl = Redis::ttl($key);
} catch (\Throwable $e) {
$val = false;
$ttl = -2;
}
$exists = ($val !== false && $val !== null && $val !== '');
echo sprintf(
" %s user=%d exists=%s ttl=%s %s\n",
$key,
$uid,
$exists ? 'YES' : 'NO',
(string) $ttl,
$exists ? '(已推送过)' : '(未推送 → 重启 webman 后用 republish_bet_win.php 补发)'
);
}
echo "\n";
}
echo "如需补发php scripts/republish_bet_win.php --period-no=<no> --force\n";