Spaces:
Running
Running
| import os | |
| import sys | |
| import django | |
| import chromadb | |
| from pathlib import Path | |
| # Setup Project Paths | |
| PROJECT_ROOT = Path(__file__).resolve().parent.parent | |
| # Since it's in Double_scenario_Project/scripts/reconcile_db.py | |
| # parent is scripts, parent.parent is Double_scenario_Project | |
| sys.path.append(str(PROJECT_ROOT / "src" / "backend")) | |
| sys.path.append(str(PROJECT_ROOT / "src")) | |
| # Setup Django | |
| os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'animetix_project.settings') | |
| django.setup() | |
| from animetix.models import MediaItem | |
| from pipeline.chroma_client import chroma_manager | |
| from pipeline.neo4j_client import neo4j_manager | |
| def reconcile(): | |
| print("🔍 Starting Database Reconciliation...") | |
| # 1. Get Source of Truth (Django) | |
| items = MediaItem.objects.all() | |
| count = items.count() | |
| print(f"📊 Catalog Source: {count} items in Django.") | |
| if count == 0: | |
| print("⚠️ Django catalog is empty. Run 'python manage.py sync_catalog' first.") | |
| return | |
| # 2. Check ChromaDB | |
| collections = { | |
| 'Anime': ['anime_thematic', 'anime_visual_vibe', 'anime_plot'], | |
| 'Manga': ['manga_thematic', 'manga_visual_vibe'], | |
| 'Character': ['character_vibe', 'character_visual_vibe'], | |
| 'Movie': ['movie_thematic', 'movie_plot', 'movie_vibe'], | |
| 'Game': ['game_thematic', 'game_plot', 'game_vibe'], | |
| 'Actor': ['actor_vibe'] | |
| } | |
| discrepancies = [] | |
| # Sample check for performance (or full if count < 1000) | |
| check_items = items[:1000] if count > 1000 else items | |
| print(f"🕵️ Verifying {len(check_items)} sample items across DBs...") | |
| for item in check_items: | |
| issues = [] | |
| # Chroma Check | |
| colls = collections.get(item.media_type, []) | |
| for coll_name in colls: | |
| try: | |
| coll = chroma_manager.get_collection(coll_name) | |
| res = coll.get(ids=[str(item.external_id)], include=[]) | |
| if not res.get('ids'): | |
| issues.append(f"Missing in Chroma:{coll_name}") | |
| except Exception as e: | |
| issues.append(f"Chroma Error:{coll_name}") | |
| # Neo4j Check (Simplified) | |
| try: | |
| # Assumes nodes have 'id' property and label matches media_type | |
| query = f"MATCH (n:{item.media_type} {{id: $id}}) RETURN n LIMIT 1" | |
| res = neo4j_manager.execute_query(query, {"id": item.external_id}) | |
| if not res: | |
| issues.append("Missing in Neo4j") | |
| except: | |
| issues.append("Neo4j Check Failed") | |
| if issues: | |
| discrepancies.append({ | |
| "item": str(item), | |
| "issues": issues | |
| }) | |
| # 3. Report | |
| if not discrepancies: | |
| print("✅ SUCCESS: All sampled items are synchronized across Django, ChromaDB, and Neo4j.") | |
| else: | |
| print(f"❌ FOUND {len(discrepancies)} DISCREPANCIES:") | |
| for d in discrepancies[:20]: # Show first 20 | |
| print(f" - {d['item']}: {', '.join(d['issues'])}") | |
| if len(discrepancies) > 20: | |
| print(f" ... and {len(discrepancies) - 20} more.") | |
| if __name__ == "__main__": | |
| reconcile() | |