66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
|
|
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||
|
|
import { ConfigService } from '@nestjs/config';
|
||
|
|
import Redis from 'ioredis';
|
||
|
|
|
||
|
|
@Injectable()
|
||
|
|
export class CacheService implements OnModuleInit {
|
||
|
|
private redis: Redis;
|
||
|
|
|
||
|
|
constructor(private configService: ConfigService) {}
|
||
|
|
|
||
|
|
onModuleInit() {
|
||
|
|
const redisUrl = this.configService.get('REDIS_URL', 'redis://localhost:6379');
|
||
|
|
this.redis = new Redis(redisUrl);
|
||
|
|
}
|
||
|
|
|
||
|
|
async get<T>(key: string): Promise<T | null> {
|
||
|
|
const value = await this.redis.get(key);
|
||
|
|
return value ? JSON.parse(value) : null;
|
||
|
|
}
|
||
|
|
|
||
|
|
async set(key: string, value: any, ttlSeconds?: number): Promise<void> {
|
||
|
|
const serialized = JSON.stringify(value);
|
||
|
|
if (ttlSeconds) {
|
||
|
|
await this.redis.setex(key, ttlSeconds, serialized);
|
||
|
|
} else {
|
||
|
|
await this.redis.set(key, serialized);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async del(key: string): Promise<void> {
|
||
|
|
await this.redis.del(key);
|
||
|
|
}
|
||
|
|
|
||
|
|
async delPattern(pattern: string): Promise<void> {
|
||
|
|
const keys = await this.redis.keys(pattern);
|
||
|
|
if (keys.length > 0) {
|
||
|
|
await this.redis.del(...keys);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async exists(key: string): Promise<boolean> {
|
||
|
|
return (await this.redis.exists(key)) === 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Cache key builders for consistency
|
||
|
|
buildKey(prefix: string, userId: string, ...parts: string[]): string {
|
||
|
|
return [prefix, userId, ...parts].join(':');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Common cache patterns
|
||
|
|
async getOrSet<T>(
|
||
|
|
key: string,
|
||
|
|
fetcher: () => Promise<T>,
|
||
|
|
ttlSeconds: number = 300,
|
||
|
|
): Promise<T> {
|
||
|
|
const cached = await this.get<T>(key);
|
||
|
|
if (cached !== null) {
|
||
|
|
return cached;
|
||
|
|
}
|
||
|
|
|
||
|
|
const fresh = await fetcher();
|
||
|
|
await this.set(key, fresh, ttlSeconds);
|
||
|
|
return fresh;
|
||
|
|
}
|
||
|
|
}
|