""" Neo4j database initialization module for ClassroomCopilot Handles database creation, schema setup, and calendar structure """ import os import json import time from typing import Dict, Any, Optional from datetime import datetime, timedelta from modules.database.services.neo4j_service import Neo4jService from modules.database.init.init_calendar import create_calendar from modules.logger_tool import initialise_logger logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), 'default', True) class Neo4jInitializer: """Handles Neo4j database initialization including database, schema, and calendar structure""" def __init__(self): self.neo4j_service = Neo4jService() # Use lowercase to avoid case sensitivity issues self.db_name = os.getenv("NEO4J_CC_DB", "classroomcopilot") def initialize_database(self) -> Dict[str, Any]: """Initialize the single ClassroomCopilot database""" logger.info(f"Initializing Neo4j database: {self.db_name}") try: # Create the main database result = self.neo4j_service.create_database(self.db_name) if result["status"] != "success": return { "success": False, "message": f"Failed to create {self.db_name} database: {result['message']}" } logger.info(f"Successfully created {self.db_name} database") # Wait for database to be fully available logger.info("Waiting for database to be fully available...") time.sleep(5) # Wait 5 seconds for database to be ready # Verify database exists and is accessible max_retries = 10 retry_delay = 2 for attempt in range(max_retries): try: # Try to check if the database exists to verify it's ready test_result = self.neo4j_service.check_database_exists(self.db_name) if test_result["status"] == "success" and test_result["exists"]: logger.info(f"Database {self.db_name} is ready and accessible") break else: logger.info(f"Database not ready yet (attempt {attempt + 1}/{max_retries}), waiting {retry_delay}s...") time.sleep(retry_delay) except Exception as e: if attempt < max_retries - 1: logger.info(f"Database existence check failed (attempt {attempt + 1}/{max_retries}), waiting {retry_delay}s...") time.sleep(retry_delay) else: logger.warning(f"Database existence check failed after {max_retries} attempts: {str(e)}") # Continue anyway as the database was created successfully return { "success": True, "message": f"Successfully created {self.db_name} database", "result": result } except Exception as e: logger.error(f"Error creating database: {str(e)}") return { "success": False, "message": f"Error creating database: {str(e)}" } def initialize_schema(self) -> Dict[str, Any]: """Initialize Neo4j schema on the ClassroomCopilot database""" logger.info(f"Initializing Neo4j schema on {self.db_name}...") try: result = self.neo4j_service.initialize_schema(self.db_name) if result["status"] != "success": return { "success": False, "message": f"Failed to initialize schema on {self.db_name}: {result['message']}" } logger.info(f"Successfully initialized schema on {self.db_name}") return { "success": True, "message": f"Successfully initialized schema on {self.db_name}", "result": result } except Exception as e: logger.error(f"Error initializing schema: {str(e)}") return { "success": False, "message": f"Error initializing schema: {str(e)}" } def initialize_calendar_structure(self) -> Dict[str, Any]: """Initialize the calendar structure with days, weeks, months, and years""" logger.info("Initializing calendar structure...") try: # Create calendar structure for the next 1 year start_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) end_date = start_date + timedelta(days=365) # 1 year # Create calendar structure directly (no calendar node needed) calendar_nodes = create_calendar( db_name=self.db_name, start_date=start_date, end_date=end_date, time_chunk_node_length=0, storage_tools=None ) if calendar_nodes: logger.info("Calendar structure created successfully") return { "success": True, "message": "Calendar structure created successfully", "calendar_nodes": calendar_nodes } else: return { "success": False, "message": "Failed to create calendar structure" } except Exception as e: logger.error(f"Error creating calendar structure: {str(e)}") return { "success": False, "message": f"Error creating calendar structure: {str(e)}" } def initialize_neo4j() -> Dict[str, Any]: """Initialize Neo4j database setup""" logger.info("Starting Neo4j database initialization...") initializer = Neo4jInitializer() # 1. Create the single database db_result = initializer.initialize_database() if not db_result["success"]: return db_result # 2. Initialize schema schema_result = initializer.initialize_schema() if not schema_result["success"]: return schema_result # 3. Initialize calendar structure calendar_result = initializer.initialize_calendar_structure() if not calendar_result["success"]: return calendar_result logger.info("Neo4j database initialization completed successfully") return { "success": True, "message": "Neo4j database initialization completed successfully", "database": db_result, "schema": schema_result, "calendar": calendar_result }