File size: 2,268 Bytes
bcce530
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { Redis } from '@upstash/redis'

// Singleton Redis client using Upstash REST API
let redis: Redis | null = null

export function getRedis(): Redis | null {
    if (!process.env.UPSTASH_REDIS_REST_URL || !process.env.UPSTASH_REDIS_REST_TOKEN) {
        console.warn('Redis not configured. Set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN')
        return null
    }

    if (!redis) {
        redis = new Redis({
            url: process.env.UPSTASH_REDIS_REST_URL,
            token: process.env.UPSTASH_REDIS_REST_TOKEN,
        })
    }

    return redis
}

// Helper functions with automatic fallback if Redis unavailable
export async function redisGet<T>(key: string): Promise<T | null> {
    const client = getRedis()
    if (!client) return null

    try {
        return await client.get<T>(key)
    } catch (error) {
        console.error('Redis GET error:', error)
        return null
    }
}

export async function redisSet(
    key: string,
    value: any,
    expirationSeconds?: number
): Promise<boolean> {
    const client = getRedis()
    if (!client) return false

    try {
        if (expirationSeconds) {
            await client.setex(key, expirationSeconds, value)
        } else {
            await client.set(key, value)
        }
        return true
    } catch (error) {
        console.error('Redis SET error:', error)
        return false
    }
}

export async function redisIncr(key: string): Promise<number | null> {
    const client = getRedis()
    if (!client) return null

    try {
        return await client.incr(key)
    } catch (error) {
        console.error('Redis INCR error:', error)
        return null
    }
}

export async function redisExpire(key: string, seconds: number): Promise<boolean> {
    const client = getRedis()
    if (!client) return false

    try {
        await client.expire(key, seconds)
        return true
    } catch (error) {
        console.error('Redis EXPIRE error:', error)
        return false
    }
}

export async function redisTTL(key: string): Promise<number | null> {
    const client = getRedis()
    if (!client) return null

    try {
        return await client.ttl(key)
    } catch (error) {
        console.error('Redis TTL error:', error)
        return null
    }
}