Commit 7196ad06 by luoqi

merge: fix/refresh-single-flight → test(冷启动换票走共享单飞)

parents 504b0e19 2207d61b
Pipeline #3585 failed in 0 seconds
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useAuthStore } from '@/stores/auth-store'; import { useAuthStore } from '@/stores/auth-store';
import { exchangeCode, refreshToken } from '@/lib/auth-api'; import { exchangeCode } from '@/lib/auth-api';
import { tryRefresh } from '@/lib/api-client'; import { tryRefresh } from '@/lib/api-client';
import { env } from '@/lib/env'; import { env } from '@/lib/env';
...@@ -195,20 +195,33 @@ export function useAuthBootstrap() { ...@@ -195,20 +195,33 @@ export function useAuthBootstrap() {
} }
// ─── 3. 仅 refresh token 还在 → silent refresh ─── // ─── 3. 仅 refresh token 还在 → silent refresh ───
//
// 🔴 **必须走 api-client 的共享单飞 `tryRefresh`**,⛔ 不能直接调 `refreshToken()`。
// refresh token 是**一次性**的:服务端换票时 `redis.del(旧 jti)` 再发新的
// (auth.service.ts:468)。所以同一张票被两条路各换一次,后到的那条必得
// `10103 AUTH_INVALID_REFRESH_TOKEN` → 前端据此清会话 → 「登录已过期」。
//
// ── 2026-08-20 生产实录(client-diag)────────────────────────
// ev=start accessValid=N ← access 到点过期
// ev=refresh-ok ← 本函数直接换,成功,旧 jti 已作废
// ev=runtime-refresh-fail err=code=10103 ← 首屏请求 401 兜底刷,拿的是同一张旧票
// ev=runtime-auth-clear err=code=10106 ← 清凭据,弹「登录已过期」
// 主管当时什么都没做错,只是隔了 2 小时回到页面。
//
// ⚠️ 下面那个"过期前 60s 定时刷"**早就改成走单飞了**(见本文件末尾那段注释,
// 同一条根因),⛔ 唯独这里漏了 —— 而这里恰恰是**每次冷启动**都会走的路径,
// 比定时器常见得多。
if (s.refreshToken) { if (s.refreshToken) {
setStatus('authenticating'); setStatus('authenticating');
try { const ok = await tryRefresh(); // 成功即 setTokens、失败即 clear,内部已处理
const r = await refreshToken(s.refreshToken); if (ok) {
setTokens(r);
reportDiag({ ev: 'refresh-ok', codeTag }); reportDiag({ ev: 'refresh-ok', codeTag });
setStatus('ready'); setStatus('ready');
return; } else {
} catch {
reportDiag({ ev: 'refresh-fail', codeTag, ...storeSnap(), ...envInfo }); reportDiag({ ev: 'refresh-fail', codeTag, ...storeSnap(), ...envInfo });
clear();
setStatus('error'); setStatus('error');
return;
} }
return;
} }
// ─── 4. 全没了 → 弹「登录已过期」─── // ─── 4. 全没了 → 弹「登录已过期」───
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment