/* eslint-disable no-console, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ import { Redis } from '@upstash/redis'; import { UpstashRedisAdapter } from './redis-adapter'; import { BaseRedisStorage } from './redis-base.db'; // 添加Upstash Redis操作重试包装器 async function withRetry( operation: () => Promise, maxRetries = 3 ): Promise { for (let i = 0; i < maxRetries; i++) { try { return await operation(); } catch (err: any) { const isLastAttempt = i === maxRetries - 1; const isConnectionError = err.message?.includes('Connection') || err.message?.includes('ECONNREFUSED') || err.message?.includes('ENOTFOUND') || err.code === 'ECONNRESET' || err.code === 'EPIPE' || err.name === 'UpstashError'; if (isConnectionError && !isLastAttempt) { console.log( `Upstash Redis operation failed, retrying... (${i + 1}/${maxRetries})` ); console.error('Error:', err.message); // 等待一段时间后重试 await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1))); continue; } throw err; } } throw new Error('Max retries exceeded'); } export class UpstashRedisStorage extends BaseRedisStorage { constructor() { const client = getUpstashRedisClient(); const adapter = new UpstashRedisAdapter(client); super(adapter, withRetry); } } // 单例 Upstash Redis 客户端 function getUpstashRedisClient(): Redis { const globalKey = Symbol.for('__MOONTV_UPSTASH_REDIS_CLIENT__'); let client: Redis | undefined = (global as any)[globalKey]; if (!client) { const upstashUrl = process.env.UPSTASH_URL; const upstashToken = process.env.UPSTASH_TOKEN; if (!upstashUrl || !upstashToken) { throw new Error( 'UPSTASH_URL and UPSTASH_TOKEN env variables must be set' ); } // 创建 Upstash Redis 客户端 client = new Redis({ url: upstashUrl, token: upstashToken, // 可选配置 retry: { retries: 3, backoff: (retryCount: number) => Math.min(1000 * Math.pow(2, retryCount), 30000), }, }); console.log('Upstash Redis client created successfully'); (global as any)[globalKey] = client; } return client; }