import { createClient } from 'redis';
export interface Todo {
id: string;
title: string;
description: string;
status: 'pending' | 'completed';
createdAt: string;
priority?: 'low' | 'medium' | 'high';
}
export class RedisClient {
private client: ReturnType<typeof createClient>;
private isConnected = false;
constructor(redisUrl: string) {
this.client = createClient({
url: redisUrl,
socket: {
reconnectStrategy: (retries) => {
if (retries > 10) {
console.error('Redis connection failed after 10 retries');
return new Error('Max retries reached');
}
return Math.min(retries * 100, 3000);
}
}
});
this.client.on('error', (err) => console.error('Redis Client Error:', err));
this.client.on('connect', () => console.log('Redis Client Connected'));
this.client.on('ready', () => {
console.log('Redis Client Ready');
this.isConnected = true;
});
this.client.on('reconnecting', () => console.log('Redis Client Reconnecting'));
}
async connect(): Promise<void> {
if (!this.isConnected) {
await this.client.connect();
}
}
async disconnect(): Promise<void> {
if (this.isConnected) {
await this.client.disconnect();
this.isConnected = false;
}
}
/**
* Get all todos for a session
*/
async getTodos(sessionId: string): Promise<Todo[]> {
const key = `session:${sessionId}:todos`;
const todosJson = await this.client.get(key);
if (!todosJson) {
return [];
}
return JSON.parse(todosJson) as Todo[];
}
/**
* Set todos for a session
*/
async setTodos(sessionId: string, todos: Todo[]): Promise<void> {
const key = `session:${sessionId}:todos`;
await this.client.set(key, JSON.stringify(todos));
// Set expiration to 7 days
await this.client.expire(key, 60 * 60 * 24 * 7);
}
/**
* Add a new todo
*/
async addTodo(sessionId: string, todo: Todo): Promise<Todo[]> {
const todos = await this.getTodos(sessionId);
todos.push(todo);
await this.setTodos(sessionId, todos);
return todos;
}
/**
* Remove a todo by ID
*/
async removeTodo(sessionId: string, todoId: string): Promise<Todo[]> {
const todos = await this.getTodos(sessionId);
const filtered = todos.filter(t => t.id !== todoId);
await this.setTodos(sessionId, filtered);
return filtered;
}
/**
* Mark a todo as done
*/
async markTodoDone(sessionId: string, todoId: string): Promise<Todo[]> {
const todos = await this.getTodos(sessionId);
const todo = todos.find(t => t.id === todoId);
if (todo) {
todo.status = 'completed';
await this.setTodos(sessionId, todos);
}
return todos;
}
/**
* Clear all todos for a session
*/
async clearTodos(sessionId: string): Promise<void> {
const key = `session:${sessionId}:todos`;
await this.client.del(key);
}
/**
* Get or create session
*/
async ensureSession(sessionId: string): Promise<void> {
const key = `session:${sessionId}:todos`;
const exists = await this.client.exists(key);
if (!exists) {
await this.setTodos(sessionId, []);
}
}
/**
* Health check
*/
async ping(): Promise<boolean> {
try {
const result = await this.client.ping();
return result === 'PONG';
} catch (error) {
console.error('Redis ping failed:', error);
return false;
}
}
}