You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
1.8 KiB
88 lines
1.8 KiB
import Redis from 'ioredis'
|
|
import type { CacheDriver } from '../types'
|
|
|
|
export interface RedisDriverOptions {
|
|
host: string
|
|
port: number
|
|
password?: string
|
|
db?: number
|
|
}
|
|
|
|
export class RedisDriver implements CacheDriver {
|
|
name = 'redis'
|
|
private redis: Redis
|
|
|
|
constructor(options: RedisDriverOptions) {
|
|
this.redis = new Redis({
|
|
host: options.host,
|
|
port: options.port,
|
|
password: options.password,
|
|
db: options.db ?? 0,
|
|
lazyConnect: true,
|
|
})
|
|
}
|
|
|
|
private serialize<T>(value: T): string {
|
|
return JSON.stringify(value)
|
|
}
|
|
|
|
private deserialize<T>(data: string): T {
|
|
try {
|
|
return JSON.parse(data) as T
|
|
} catch {
|
|
throw new Error(`[cache] Failed to deserialize data: ${data.substring(0, 100)}`)
|
|
}
|
|
}
|
|
|
|
async get<T>(key: string): Promise<T | null> {
|
|
try {
|
|
const data = await this.redis.get(key)
|
|
if (!data) return null
|
|
return this.deserialize<T>(data)
|
|
} catch (err) {
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async set<T>(key: string, value: T, ttl = 0): Promise<void> {
|
|
try {
|
|
const serialized = this.serialize(value)
|
|
if (ttl > 0) {
|
|
await this.redis.set(key, serialized, 'EX', ttl)
|
|
} else {
|
|
await this.redis.set(key, serialized)
|
|
}
|
|
} catch (err) {
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async del(key: string): Promise<void> {
|
|
try {
|
|
await this.redis.del(key)
|
|
} catch (err) {
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async exists(key: string): Promise<boolean> {
|
|
try {
|
|
const result = await this.redis.exists(key)
|
|
return result === 1
|
|
} catch (err) {
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async clear(): Promise<void> {
|
|
try {
|
|
await this.redis.flushdb()
|
|
} catch (err) {
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async disconnect(): Promise<void> {
|
|
await this.redis.quit()
|
|
}
|
|
}
|