ttl deletion for rate limits

This commit is contained in:
James Ketr 2025-06-18 12:30:42 -07:00
parent cbd6ead5f3
commit e5ac267935
8 changed files with 11 additions and 66 deletions

View File

@ -25,7 +25,7 @@ import hashlib
from .base import Agent, agent_registry, LLMMessage
from models import ActivityType, ApiActivityType, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Tunables
import model_cast
import helpers.model_cast as model_cast
from logger import logger
import defines
import backstory_traceback as traceback

View File

@ -27,7 +27,6 @@ from names_dataset import NameDataset, NameWrapper # type: ignore
from .base import Agent, agent_registry, LLMMessage
from models import ApiActivityType, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Tunables
import model_cast
from logger import logger
import defines
import backstory_traceback as traceback

View File

@ -20,7 +20,6 @@ import numpy as np # type: ignore
from .base import Agent, agent_registry, LLMMessage
from models import ApiActivityType, ApiMessage, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions, ChatSenderType, ApiStatusType, Job, JobRequirements, JobRequirementsMessage, Tunables
import model_cast
from logger import logger
import defines
import backstory_traceback as traceback

View File

@ -22,7 +22,6 @@ from .base import Agent, agent_registry, LLMMessage
from models import (ApiMessage, Candidate, ChatMessage, ChatMessageError, ChatMessageMetaData, ApiMessageType, ChatMessageRagSearch,
ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming, ChatMessageUser, ChatOptions,
ChatSenderType, ApiStatusType, EvidenceDetail, SkillAssessment, Tunables)
import model_cast
from logger import logger
import defines
import backstory_traceback as traceback

View File

@ -82,10 +82,8 @@ class BackgroundTaskManager:
logger.info("Skipping rate limit cleanup - application shutting down")
return 0
database = self.database_manager.get_database()
# Get Redis client safely (using the event loop safe method)
from backend.database.manager import redis_manager
from database.manager import redis_manager
redis = await redis_manager.get_client()
# Clean up rate limit keys older than specified days
@ -103,9 +101,13 @@ class BackgroundTaskManager:
try:
ttl = await redis.ttl(key)
if ttl == -1: # No expiration set, check creation time
# For simplicity, delete keys without TTL
await redis.delete(key)
deleted_count += 1
creation_time = await redis.hget(key, "created_at") # type: ignore
if creation_time:
creation_time = datetime.fromisoformat(creation_time).replace(tzinfo=UTC)
if creation_time < cutoff_time:
# Key is older than cutoff, delete it
await redis.delete(key)
deleted_count += 1
except Exception:
continue

View File

@ -60,7 +60,7 @@ from auth_utils import (
sanitize_login_input,
SecurityConfig
)
import model_cast
import helpers.model_cast as model_cast
import defines
from logger import logger
from database.manager import RedisDatabase, redis_manager, DatabaseManager

View File

@ -1,53 +0,0 @@
from typing import Type, TypeVar
from pydantic import BaseModel
import copy
from models import Candidate, CandidateAI, Employer, Guest, BaseUserWithType
# Ensure all user models inherit from BaseUserWithType
assert issubclass(Candidate, BaseUserWithType), "Candidate must inherit from BaseUserWithType"
assert issubclass(CandidateAI, BaseUserWithType), "CandidateAI must inherit from BaseUserWithType"
assert issubclass(Employer, BaseUserWithType), "Employer must inherit from BaseUserWithType"
assert issubclass(Guest, BaseUserWithType), "Guest must inherit from BaseUserWithType"
T = TypeVar('T', bound=BaseModel)
def cast_to_model(model_cls: Type[T], source: BaseModel) -> T:
data = {field: getattr(source, field) for field in model_cls.__fields__}
return model_cls(**data)
def cast_to_model_safe(model_cls: Type[T], source: BaseModel) -> T:
data = {field: copy.deepcopy(getattr(source, field)) for field in model_cls.__fields__}
return model_cls(**data)
def cast_to_base_user_with_type(user) -> BaseUserWithType:
"""
Casts a Candidate, CandidateAI, Employer, or Guest to BaseUserWithType.
This is useful for FastAPI dependencies that expect a common user type.
"""
if isinstance(user, BaseUserWithType):
return user
# If it's a dict, try to detect type
if isinstance(user, dict):
user_type = user.get("user_type") or user.get("type")
if user_type == "candidate":
if user.get("is_AI"):
return CandidateAI.model_validate(user)
return Candidate.model_validate(user)
elif user_type == "employer":
return Employer.model_validate(user)
elif user_type == "guest":
return Guest.model_validate(user)
else:
raise ValueError(f"Unknown user_type: {user_type}")
# If it's a model, check its type
if hasattr(user, "user_type"):
if getattr(user, "user_type", None) == "candidate":
if getattr(user, "is_AI", False):
return CandidateAI.model_validate(user.model_dump())
return Candidate.model_validate(user.model_dump())
elif getattr(user, "user_type", None) == "employer":
return Employer.model_validate(user.model_dump())
elif getattr(user, "user_type", None) == "guest":
return Guest.model_validate(user.model_dump())
raise TypeError(f"Cannot cast object of type {type(user)} to BaseUserWithType")

View File

@ -134,11 +134,10 @@ async def get_current_user(
# Check candidates
candidate_data = await database.get_candidate(user_id)
if candidate_data:
from helpers.model_cast import cast_to_base_user_with_type
if candidate_data.get("is_AI"):
from model_cast import cast_to_base_user_with_type
return cast_to_base_user_with_type(CandidateAI.model_validate(candidate_data))
else:
from model_cast import cast_to_base_user_with_type
return cast_to_base_user_with_type(Candidate.model_validate(candidate_data))
# Check employers