Files
frontend/src/stores/user/UserManager.ts

179 lines
5.1 KiB
TypeScript
Raw Normal View History

/**
* UserManager - <EFBFBD><EFBFBD>?
*
* 使 Zustand store <EFBFBD><EFBFBD>?
* API <EFBFBD><EFBFBD>?
*/
import type { UserDTO } from '../../types/dto';
import { authService } from '../../services/authService';
import {
getCurrentUserCache,
getUserCache,
saveCurrentUserCache,
saveUserCache,
} from '../../services/database';
import { useUserManagerStore } from './userStore';
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
// ==================== UserManager <20><>?====================
class UserManager {
/**
*
*
*/
async getCurrentUser(forceRefresh = false): Promise<UserDTO | null> {
const store = useUserManagerStore.getState();
const entry = store.currentUserEntry;
// 有效缓存
if (!forceRefresh && entry && !isCacheExpired(entry)) {
return entry.data;
}
// 过期缓存后台刷新立即返回旧数<E697A7><E695B0>?
if (!forceRefresh && entry && isCacheExpired(entry)) {
this.refreshCurrentUserInBackground();
return entry.data;
}
// 尝试从本地数据库加载
if (!forceRefresh) {
const cachedFromDb = await getCurrentUserCache();
if (cachedFromDb) {
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
store.setCurrentUserEntry(newEntry);
this.refreshCurrentUserInBackground();
return cachedFromDb;
}
}
// 发起 API 请求
return this.dedupe('users:current', async () => {
const user = await authService.fetchCurrentUserFromAPI();
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
store.setCurrentUserEntry(newEntry);
if (user) {
saveCurrentUserCache(user).catch(() => {});
saveUserCache(user).catch(() => {});
}
return user;
});
}
/**
*
*/
private refreshCurrentUserInBackground(): void {
this.dedupe('users:current:bg', async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchCurrentUserFromAPI();
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
store.setCurrentUserEntry(newEntry);
if (user) {
saveCurrentUserCache(user).catch(() => {});
saveUserCache(user).catch(() => {});
}
return user;
}).catch((error) => {
console.error('[UserManager] refreshCurrentUserInBackground error:', error);
});
}
/**
* ID
*/
async getUserById(userId: string, forceRefresh = false): Promise<UserDTO | null> {
const store = useUserManagerStore.getState();
const entry = store.usersMap.get(userId);
// 有效缓存
if (!forceRefresh && entry && !isCacheExpired(entry)) {
return entry.data;
}
// 过期缓存后台刷新立即返回旧数<E697A7><E695B0>?
if (!forceRefresh && entry && isCacheExpired(entry)) {
this.refreshUserByIdInBackground(userId);
return entry.data;
}
// 尝试从本地数据库加载
if (!forceRefresh) {
const cachedFromDb = await getUserCache(userId);
if (cachedFromDb) {
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
store.setUser(userId, cachedFromDb);
this.refreshUserByIdInBackground(userId);
return cachedFromDb;
}
}
// 发起 API 请求
return this.dedupe(`users:detail:${userId}`, async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchUserByIdFromAPI(userId);
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
store.setUser(userId, user);
if (user) {
saveUserCache(user).catch(() => {});
}
return user;
});
}
/**
*
*/
private refreshUserByIdInBackground(userId: string): void {
this.dedupe(`users:detail:bg:${userId}`, async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchUserByIdFromAPI(userId);
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
store.setUser(userId, user);
if (user) {
saveUserCache(user).catch(() => {});
}
return user;
}).catch((error) => {
console.error('[UserManager] refreshUserByIdInBackground error:', error);
});
}
/**
* 使<EFBFBD><EFBFBD>?
*/
invalidateUsers(): void {
useUserManagerStore.getState().invalidateAll();
}
/**
*
*/
private async dedupe<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
const store = useUserManagerStore.getState();
const pending = store.getPendingRequest<T>(key);
if (pending) return pending;
const request = fetcher().finally(() => {
useUserManagerStore.getState().deletePendingRequest(key);
});
store.setPendingRequest(key, request);
return request;
}
}
// ==================== 单例导出 ====================
export const userManager = new UserManager();
// 导出类以支持类型检查和测试
export { UserManager };
export default userManager;