refactor(core): distinguish network errors from auth failures and refactor real-time messaging pipeline
- Add isNetworkError() helper and FetchCurrentUserResult discriminated union to prevent logout on network failures
- Refactor authService to return { kind: 'user' } | { kind: 'auth_failed' } | { kind: 'network_error' }
- Update authStore to preserve login state on network errors, only logout on auth failures
- Replace WSMessageHandler with RealtimeIngestionPipeline for improved real-time message handling
- Remove MessageDeduplication service; add store-level idempotent addOrReplaceMessage for message dedup
- Add atomic systemUnreadCount operations to prevent race conditions
- Add SearchHeader component for consistent search UI across screens
- Add 'home' TabBar variant with underline style matching HomeScreen
- Add Jest test infrastructure and exclude tests from tsconfig
- Fix ChatScreen history lock being stuck when scrolling to latest messages
- Remove unused call_participant_joined/left WS event types
This commit is contained in:
@@ -14,6 +14,14 @@ import { createDedupe } from '../utils/requestDedupe';
|
||||
|
||||
const dedupe = createDedupe(() => useUserManagerStore);
|
||||
|
||||
// 将 fetchCurrentUserFromAPI 的判别结果转为 User | null。
|
||||
// 网络故障/认证失败时返回 null,由上层缓存兜底(避免空数据覆盖缓存)。
|
||||
// 注意:UserManager 只负责缓存,不触发登出,登出由 authStore 统一处理。
|
||||
async function fetchCurrentUserOrNull(): Promise<UserDTO | null> {
|
||||
const result = await authService.fetchCurrentUserFromAPI();
|
||||
return result.kind === 'user' ? result.user : null;
|
||||
}
|
||||
|
||||
// ==================== UserManager 类 ====================
|
||||
|
||||
class UserManager {
|
||||
@@ -41,11 +49,11 @@ class UserManager {
|
||||
}
|
||||
|
||||
return dedupe('users:current', async () => {
|
||||
const user = await authService.fetchCurrentUserFromAPI();
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
|
||||
const user = await fetchCurrentUserOrNull();
|
||||
// 仅在拿到真实用户时刷新缓存;网络/认证失败时保留旧缓存,避免误清空
|
||||
if (user) {
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
userCacheRepository.saveCurrent(user).catch(() => {});
|
||||
userCacheRepository.save(user).catch(() => {});
|
||||
}
|
||||
@@ -56,11 +64,10 @@ class UserManager {
|
||||
private refreshCurrentUserInBackground(): void {
|
||||
dedupe('users:current:bg', async () => {
|
||||
const store = useUserManagerStore.getState();
|
||||
const user = await authService.fetchCurrentUserFromAPI();
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
|
||||
const user = await fetchCurrentUserOrNull();
|
||||
if (user) {
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
userCacheRepository.saveCurrent(user).catch(() => {});
|
||||
userCacheRepository.save(user).catch(() => {});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user