add life span manager to guarantee graceful db shutdown

parent 5b55ec50
This diff is collapsed.
......@@ -293,6 +293,3 @@ class AgentService:
except Exception as e:
logger.error(f"Error closing connection pools: {e}")
def __del__(self):
"""Destructor to ensure connection pools are closed"""
self.close()
\ No newline at end of file
......@@ -40,43 +40,44 @@ class ResponseManager:
def get_response(self, student_id: str) -> Dict:
"""
Atomically gets the response for a student and removes it from Redis
to ensure it's claimed only once.
Gets the response for a student without deleting it.
This allows the client to safely retry the request if it fails.
The key will be cleaned up automatically by Redis when its TTL expires.
"""
key = self._get_key(student_id)
# Use a pipeline to get and delete the key in a single, atomic operation
pipe = self.redis.pipeline()
pipe.get(key)
pipe.delete(key)
results = pipe.execute()
json_value = results[0]
# 1. Use a simple, non-destructive GET command. No pipeline needed.
json_value = self.redis.get(key)
if not json_value:
# If nothing was found, return the same empty structure as the old class
return {"text": None, "audio_filename": None, "audio_bytes": None}
return {"text": None, "audio_filepath": None, "audio_bytes": None}
# If data was found, decode it
# 2. Decode the payload as before.
payload = json.loads(json_value)
# Decode the Base64 string back into binary audio data
if payload.get("audio_bytes_b64"):
payload["audio_bytes"] = base64.b64decode(payload["audio_bytes_b64"])
else:
payload["audio_bytes"] = None
# Remove the temporary key before returning
del payload["audio_bytes_b64"]
return payload
def clear_response(self, student_id: str) -> None:
"""Clears a response for a specific student from Redis."""
"""
Clears a response for a specific student from Redis.
This is still important to call at the *beginning* of a new /chat request
to ensure old data is invalidated immediately.
"""
key = self._get_key(student_id)
self.redis.delete(key)
def is_response_fresh(self, student_id: str, max_age_seconds: int = 300) -> bool:
"""Checks if a response exists in Redis for the given student."""
def is_response_fresh(self, student_id: str) -> bool:
"""
Checks if a response exists in Redis for the given student.
This is much simpler and more reliable now.
"""
key = self._get_key(student_id)
# redis.exists() is the direct equivalent of checking if the key is present
# redis.exists() returns the number of keys that exist (0 or 1 in this case).
return self.redis.exists(key) > 0
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment