mirror of
https://github.com/furyhawk/ai_agent.git
synced 2026-07-21 02:05:42 +00:00
- Implemented `conversation-store` for managing conversations and messages. - Created `file-preview-store` to handle file preview state. - Added `sidebar-store` for sidebar visibility management. - Developed `theme-store` for theme persistence and management. - Introduced `kb-selection-store` for managing active knowledge base selections with persistence. chore: define API and chat types - Added types for API responses, authentication, chat messages, conversations, and projects. - Defined interfaces for various entities including users, sessions, and message ratings. build: configure TypeScript and testing setup - Set up `tsconfig.json` for TypeScript configuration. - Created `vitest.config.ts` for testing configuration with Vitest. - Added `vitest.setup.ts` for global test setup including mocks for Next.js router and media queries. - Configured Vercel deployment settings in `vercel.json`.
85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
"""Redis client wrapper.
|
|
|
|
Provides a class-based Redis client for connection management and operations.
|
|
"""
|
|
|
|
from redis import asyncio as aioredis
|
|
|
|
from app.core.config import settings
|
|
|
|
|
|
class RedisClient:
|
|
"""Redis client wrapper for connection lifecycle management.
|
|
|
|
Usage in FastAPI lifespan:
|
|
async with contextmanager():
|
|
redis = RedisClient(settings.REDIS_URL)
|
|
await redis.connect()
|
|
yield {"redis": redis}
|
|
await redis.close()
|
|
"""
|
|
|
|
def __init__(self, url: str | None = None):
|
|
self.url = url or settings.REDIS_URL
|
|
self.client: aioredis.Redis | None = None
|
|
|
|
async def connect(self) -> None:
|
|
"""Connect to Redis server."""
|
|
self.client = aioredis.from_url( # type: ignore[no-untyped-call]
|
|
self.url,
|
|
encoding="utf-8",
|
|
decode_responses=True,
|
|
)
|
|
|
|
async def close(self) -> None:
|
|
"""Close Redis connection."""
|
|
if self.client:
|
|
await self.client.close()
|
|
self.client = None
|
|
|
|
async def get(self, key: str) -> str | None:
|
|
"""Get a value by key."""
|
|
if not self.client:
|
|
raise RuntimeError("Redis client not connected")
|
|
return await self.client.get(key) # type: ignore[no-any-return]
|
|
|
|
async def set(
|
|
self,
|
|
key: str,
|
|
value: str,
|
|
ttl: int | None = None,
|
|
) -> None:
|
|
"""Set a value with optional TTL (in seconds)."""
|
|
if not self.client:
|
|
raise RuntimeError("Redis client not connected")
|
|
await self.client.set(key, value, ex=ttl)
|
|
|
|
async def delete(self, key: str) -> int:
|
|
"""Delete a key. Returns number of keys deleted."""
|
|
if not self.client:
|
|
raise RuntimeError("Redis client not connected")
|
|
return await self.client.delete(key) # type: ignore[no-any-return]
|
|
|
|
async def exists(self, key: str) -> bool:
|
|
"""Check if key exists."""
|
|
if not self.client:
|
|
raise RuntimeError("Redis client not connected")
|
|
return bool(await self.client.exists(key))
|
|
|
|
async def ping(self) -> bool:
|
|
"""Ping Redis server. Returns True if connected."""
|
|
if not self.client:
|
|
return False
|
|
try:
|
|
await self.client.ping()
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
@property
|
|
def raw(self) -> aioredis.Redis:
|
|
"""Access the underlying aioredis client for advanced operations."""
|
|
if not self.client:
|
|
raise RuntimeError("Redis client not connected")
|
|
return self.client
|