import { RequestCacheService, RequestAdapter } from '@jolibox/common'; import { IHttpClient } from '../http'; import { StandardResponse, GlobalConfig } from '@jolibox/types'; import { IJolicoinRewardOption, IUnlockOption, IJoliCoin, IGem } from './type'; import { IUseModalFrequencyConfig } from './reward-emitter'; // 定义请求参数类型 interface RewardRequest { endpoint: string; body?: Record; method?: 'GET' | 'POST'; } interface UnlockOptionsCacheData { unlockOptions: IUnlockOption[]; joliCoin: IJoliCoin; joliGem: IGem; } interface UnlockOptionsRealTimeData { timestamp?: number; } // 定义全局配置的缓存数据 interface GlobalConfigCacheData { joliCoinUseAndCharge: IUseModalFrequencyConfig['joliCoinUseAndCharge']; loginGuide: IUseModalFrequencyConfig['loginGuide']; // 其他全局配置字段 [key: string]: unknown; } // 奖励接口适配器 class RewardRequestAdapter implements RequestAdapter { constructor(private httpClient: IHttpClient) {} async execute(endpoint: string, options?: RewardRequest): Promise { const method = options?.method || 'POST'; const body = options?.body || {}; if (method === 'GET') { return await this.httpClient.get(endpoint, body); } else { return await this.httpClient.post(endpoint, body); } } extractCacheableData(response: IJolicoinRewardOption): UnlockOptionsCacheData { return { unlockOptions: response.data?.unlockOptions || [], joliCoin: response.extra?.joliCoin || { balance: 0, enableAutoDeduct: false }, joliGem: response.extra?.joliGem || { balance: 0, enableAutoDeduct: false } }; } extractRealTimeData?: undefined; mergeData(cached: UnlockOptionsCacheData, realTime: UnlockOptionsRealTimeData): IJolicoinRewardOption { return { code: 'SUCCESS', message: 'success', data: { unlockOptions: cached.unlockOptions }, extra: { joliCoin: cached.joliCoin || { balance: 0, enableAutoDeduct: false }, joliGem: cached.joliGem || { balance: 0, enableAutoDeduct: false } } }; } processCachedData(cached: UnlockOptionsCacheData): IJolicoinRewardOption { return { code: 'SUCCESS', message: 'success from cache', data: { unlockOptions: cached.unlockOptions }, extra: { joliCoin: cached.joliCoin, joliGem: cached.joliGem } }; } } class GlobalConfigRequestAdapter implements RequestAdapter< RewardRequest, StandardResponse, GlobalConfigCacheData, undefined > { constructor(private httpClient: IHttpClient) {} async execute( endpoint: string, options?: RewardRequest ): Promise> { const method = options?.method || 'GET'; const body = options?.body || {}; if (method === 'GET') { return await this.httpClient.get>( endpoint, body ); } else { return await this.httpClient.post>( endpoint, body ); } } extractCacheableData( response: StandardResponse ): GlobalConfigCacheData { const data = response.data; return { joliCoinUseAndCharge: data?.joliCoinUseAndCharge, loginGuide: data?.loginGuide, ...data // 包含其他所有配置字段 } as GlobalConfigCacheData; } extractRealTimeData?: undefined; mergeData?: undefined; processCachedData( cached: GlobalConfigCacheData ): StandardResponse { return { code: 'SUCCESS', message: 'success from cache', data: cached as GlobalConfig & IUseModalFrequencyConfig }; } } export class CachedRewardService { private unlockOptionsService: RequestCacheService< RewardRequest, IJolicoinRewardOption, UnlockOptionsCacheData, UnlockOptionsRealTimeData >; private globalConfigService: RequestCacheService< RewardRequest, StandardResponse, GlobalConfigCacheData, undefined >; constructor(httpClient: IHttpClient) { // 创建 unlock-options 服务,缓存 unlockOptions,实时获取余额 this.unlockOptionsService = new (RequestCacheService as new (...args: unknown[]) => RequestCacheService< RewardRequest, IJolicoinRewardOption, UnlockOptionsCacheData, UnlockOptionsRealTimeData >)(new RewardRequestAdapter(httpClient), { duration: 30 * 60 * 1000, // 30分钟缓存 timeout: 1000, // 1s timeout for request keyGenerator: (endpoint: string) => endpoint, // unlockOptions 结构一致性检查 consistencyChecker: (cached: UnlockOptionsCacheData, serverData: UnlockOptionsCacheData) => { if (cached.unlockOptions.length !== serverData.unlockOptions.length) { return false; } return cached.unlockOptions.every((cachedOption: IUnlockOption, index: number) => { const serverOption = serverData.unlockOptions[index]; return ( cachedOption.type === serverOption.type && cachedOption.joliGemChoice?.joliGemQuantity === serverOption.joliGemChoice?.joliGemQuantity ); }); } }); this.globalConfigService = new (RequestCacheService as new (...args: unknown[]) => RequestCacheService< RewardRequest, StandardResponse, GlobalConfigCacheData, undefined >)(new GlobalConfigRequestAdapter(httpClient), { duration: 60 * 60 * 1000, // 60分钟缓存 timeout: 1000, // 1s timeout for request keyGenerator: (endpoint: string) => endpoint }); } async getUnlockOptions(body: Record = {}): Promise { return await this.unlockOptionsService.request('/api/games/unlock-options', { endpoint: '/api/games/unlock-options', body, method: 'POST' }); } async getGlobalConfig(): Promise> { return await this.globalConfigService.request('/api/fe-configs/web-common/global-config', { endpoint: '/api/fe-configs/web-common/global-config', method: 'GET' }); } async refreshUnlockOptions(body: Record = {}): Promise { return await this.unlockOptionsService.forceRequest('/api/games/unlock-options', { endpoint: '/api/games/unlock-options', body, method: 'POST' }); } async refreshGlobalConfig(): Promise> { return await this.globalConfigService.forceRequest('/api/fe-configs/web-common/global-config', { endpoint: '/api/fe-configs/web-common/global-config', method: 'GET' }); } async warmupCache(): Promise { await Promise.all([ this.unlockOptionsService.warmupCache('/api/games/unlock-options', { endpoint: '/api/games/unlock-options', method: 'POST' }), this.globalConfigService.warmupCache('/api/fe-configs/web-common/global-config', { endpoint: '/api/fe-configs/web-common/global-config', method: 'GET' }) ]); } clearAllCache(): void { this.unlockOptionsService.clearCache(); this.globalConfigService.clearCache(); } getCacheStats() { return { unlockOptions: this.unlockOptionsService.getCacheStats(), globalConfig: this.globalConfigService.getCacheStats() }; } clearExpiredCache(): void { this.unlockOptionsService.clearExpiredCache(); this.globalConfigService.clearExpiredCache(); } }