persona_service.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. from typing import List, Dict, Any, Optional
  2. from app.schemas import PersonaCreate
  3. from app.crud import create_persona
  4. from app.core.cache import cache_service
  5. from app.db.session import db_manager
  6. import json
  7. import logging
  8. logger = logging.getLogger(__name__)
  9. class PersonaService:
  10. @staticmethod
  11. def save_generated_persona(user_id: int, persona_data: Dict[str, Any], db=None) -> Optional[Any]:
  12. """
  13. Unified method to save a generated persona to the database.
  14. Handles data validation, JSON parsing, DB insertion, and cache invalidation.
  15. """
  16. try:
  17. # 1. Ensure 'theories' is a list
  18. if isinstance(persona_data.get('theories'), str):
  19. try:
  20. persona_data['theories'] = json.loads(persona_data['theories'])
  21. except:
  22. persona_data['theories'] = []
  23. # 2. Create Pydantic Model
  24. # Set default is_public to False for generated personas
  25. if 'is_public' not in persona_data:
  26. persona_data['is_public'] = False
  27. persona_create = PersonaCreate(**persona_data)
  28. # 3. Get DB Connection if not provided
  29. should_close = False
  30. if db is None:
  31. db = db_manager.get_connection()
  32. should_close = True
  33. try:
  34. # 4. Save to DB
  35. # This uses the underlying create_persona CRUD which is now transaction-safe via RetryingTransaction
  36. db_persona = create_persona(db=db, persona=persona_create, owner_id=user_id)
  37. # 5. Invalidate Cache
  38. # Crucial step to ensure frontend sees the new persona immediately
  39. cache_service.delete_keys_pattern(f"personas:list:{user_id}:*")
  40. logger.info(f"Successfully saved persona '{db_persona.name}' (ID: {db_persona.id}) for user {user_id}")
  41. return db_persona
  42. finally:
  43. if should_close:
  44. db.close()
  45. except Exception as e:
  46. logger.error(f"Failed to save generated persona: {e}")
  47. # Re-raise or return None? Let's log and return None so caller can handle gracefully
  48. print(f"[PersonaService] Error saving persona: {e}")
  49. return None
  50. persona_service = PersonaService()