File size: 6,202 Bytes
84b0fa3
276a5e7
 
84b0fa3
 
 
276a5e7
 
 
84b0fa3
976eb67
276a5e7
84b0fa3
276a5e7
 
 
 
 
 
 
 
 
 
84b0fa3
276a5e7
 
 
976eb67
276a5e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84b0fa3
276a5e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84b0fa3
 
276a5e7
 
 
 
 
 
 
84b0fa3
276a5e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
976eb67
276a5e7
 
 
 
84b0fa3
276a5e7
 
84b0fa3
276a5e7
 
 
 
 
 
84b0fa3
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
Robust startup script for Hugging Face Spaces deployment.
Initializes the database and starts the FastAPI server with comprehensive error handling.
"""
import os
import sys
import time
import logging
import asyncio
from pathlib import Path
import subprocess
from datetime import datetime

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/startup.log'),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)

def check_environment():
    """Check if required environment variables are set."""
    logger.info("πŸ” Checking environment variables...")

    required_vars = ['OPENAI_API_KEY', 'OPENROUTER_API_KEY']
    missing_vars = []

    for var in required_vars:
        if not os.getenv(var):
            missing_vars.append(var)
            logger.error(f"❌ {var} is not set")
        else:
            logger.info(f"βœ… {var} is set")

    # Optional variables
    optional_vars = ['DATABASE_URL', 'QDRANT_URL', 'HF_SPACE_ID']
    for var in optional_vars:
        if os.getenv(var):
            logger.info(f"βœ… {var} is set")
        else:
            logger.info(f"⚠️ {var} is not set (optional)")

    if missing_vars:
        logger.error(f"❌ Missing required environment variables: {missing_vars}")
        return False

    return True

def initialize_database():
    """Initialize the database with retries."""
    logger.info("πŸ“¦ Initializing database...")
    max_retries = 3

    for attempt in range(max_retries):
        try:
            # Check if init_database.py exists
            if not Path("init_database.py").exists():
                logger.warning("⚠️ init_database.py not found, skipping database initialization")
                return True

            result = subprocess.run(
                [sys.executable, "init_database.py"],
                capture_output=True,
                text=True,
                timeout=30
            )

            if result.returncode == 0:
                logger.info("βœ… Database initialization completed successfully!")
                if result.stdout:
                    logger.info(f"Database init output: {result.stdout}")
                return True
            else:
                logger.error(f"⚠️ Database initialization attempt {attempt + 1} failed: {result.stderr}")
                if attempt < max_retries - 1:
                    time.sleep(2)

        except subprocess.TimeoutExpired:
            logger.error(f"⚠️ Database initialization timeout on attempt {attempt + 1}")
            if attempt < max_retries - 1:
                time.sleep(2)
        except Exception as e:
            logger.error(f"⚠️ Database initialization error on attempt {attempt + 1}: {str(e)}")
            if attempt < max_retries - 1:
                time.sleep(2)

    logger.error("❌ Database initialization failed after all attempts")
    return False

def verify_database_file():
    """Check if database file exists and is accessible."""
    db_path = Path("database/auth.db")
    if db_path.exists():
        try:
            size = db_path.stat().st_size
            logger.info(f"βœ… Database file found! Size: {size} bytes")
            return True
        except Exception as e:
            logger.error(f"❌ Error accessing database file: {str(e)}")
            return False
    else:
        logger.info("⚠️ Database file not found. The server will create it on startup.")
        return True

def create_directories():
    """Create necessary directories."""
    directories = ['database', 'logs', '.cache/huggingface', '.cache/transformers']
    for directory in directories:
        Path(directory).mkdir(parents=True, exist_ok=True)
        logger.info(f"βœ… Directory {directory} ready")

def start_server():
    """Start the FastAPI server with error handling."""
    logger.info("🌟 Starting FastAPI server...")

    # Get port from environment or use default
    port = int(os.getenv('PORT', 7860))
    host = os.getenv('HOST', '0.0.0.0')
    workers = int(os.getenv('WORKERS', 1))

    cmd = [
        sys.executable, "-m", "uvicorn",
        "main:app",
        "--host", host,
        "--port", str(port),
        "--workers", str(workers),
        "--log-level", "info",
        "--access-log"
    ]

    logger.info(f"Command: {' '.join(cmd)}")

    try:
        # Replace current process with uvicorn
        os.execvp(sys.executable, cmd)
    except Exception as e:
        logger.error(f"❌ Failed to start server: {str(e)}")
        sys.exit(1)

def main():
    """Main startup function."""
    logger.info("πŸš€ Starting server initialization for Hugging Face Spaces...")
    logger.info(f"πŸ“… Timestamp: {datetime.utcnow().isoformat()}")
    logger.info(f"🐍 Python version: {sys.version}")
    logger.info(f"πŸ“ Working directory: {os.getcwd()}")

    # Change to backend directory if needed
    if os.path.exists("backend") and not os.getcwd().endswith("backend"):
        os.chdir("backend")
        logger.info(f"Changed to backend directory: {os.getcwd()}")

    try:
        # Create necessary directories
        create_directories()

        # Check environment
        if not check_environment():
            logger.error("❌ Environment check failed. Exiting...")
            sys.exit(1)

        # Initialize database
        if not initialize_database():
            logger.error("❌ Database initialization failed. Continuing anyway...")

        # Verify database file
        verify_database_file()

        # Print final status
        logger.info("πŸŽ‰ Initialization completed successfully!")
        logger.info(f"🌍 Environment: {'HF Spaces' if os.getenv('SPACE_ID') else 'Local'}")
        logger.info(f"πŸ”§ Port: {os.getenv('PORT', 7860)}")

        # Start server
        start_server()

    except KeyboardInterrupt:
        logger.info("⏹️ Startup interrupted by user")
        sys.exit(0)
    except Exception as e:
        logger.error(f"πŸ’₯ Fatal error during startup: {str(e)}", exc_info=True)
        sys.exit(1)

if __name__ == "__main__":
    main()