205 lines
6.7 KiB
Python
205 lines
6.7 KiB
Python
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# Add project root to Python path for imports in alembic migrations
|
|
project_root = Path(__file__).parent.absolute()
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app.api.routers import api_router
|
|
from app.core.config import settings
|
|
from app.db import init_db
|
|
|
|
# Initialize the database on startup
|
|
print("Starting database initialization...")
|
|
try:
|
|
# Get absolute path of the database file
|
|
from pathlib import Path
|
|
db_path = Path("/app/storage/db/db.sqlite").absolute()
|
|
print(f"Database path: {db_path}")
|
|
|
|
# Check directory permissions
|
|
db_dir = Path("/app/storage/db")
|
|
print(f"Database directory exists: {db_dir.exists()}")
|
|
print(f"Database directory is writable: {os.access(db_dir, os.W_OK)}")
|
|
|
|
# Initialize the database and create test task
|
|
init_db.init_db()
|
|
|
|
# Try to create a test task
|
|
try:
|
|
init_db.create_test_task()
|
|
except Exception as e:
|
|
print(f"Error creating test task: {e}")
|
|
# Continue anyway
|
|
except Exception as e:
|
|
print(f"Error initializing database: {e}")
|
|
import traceback
|
|
print(f"Detailed error: {traceback.format_exc()}")
|
|
# Continue with app startup even if DB init fails, to allow debugging
|
|
|
|
app = FastAPI(title=settings.PROJECT_NAME)
|
|
|
|
# Set all CORS enabled origins - Allow all origins
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Add exception handlers for better error reporting
|
|
@app.exception_handler(Exception)
|
|
async def validation_exception_handler(request: Request, exc: Exception):
|
|
import traceback
|
|
error_detail = {
|
|
"detail": f"Internal Server Error: {str(exc)}",
|
|
"type": str(type(exc).__name__),
|
|
"traceback": traceback.format_exc().split("\n")
|
|
}
|
|
print(f"Error processing request: {error_detail}")
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content=error_detail,
|
|
)
|
|
|
|
# Include the API router directly (no version prefix)
|
|
app.include_router(api_router)
|
|
|
|
|
|
@app.get("/", tags=["info"])
|
|
def api_info():
|
|
"""
|
|
API information endpoint with links to documentation and endpoints
|
|
"""
|
|
return {
|
|
"name": settings.PROJECT_NAME,
|
|
"version": "1.0.0",
|
|
"description": "A RESTful API for managing tasks",
|
|
"endpoints": {
|
|
"tasks": "/tasks",
|
|
"docs": "/docs",
|
|
"redoc": "/redoc",
|
|
"health": "/health",
|
|
"db_test": "/db-test"
|
|
}
|
|
}
|
|
|
|
@app.get("/health", tags=["health"])
|
|
def health_check():
|
|
"""
|
|
Health check endpoint to verify the application is running correctly
|
|
"""
|
|
return {"status": "ok"}
|
|
|
|
|
|
@app.get("/db-test", tags=["health"])
|
|
def test_db_connection():
|
|
"""
|
|
Test database connection and table creation
|
|
"""
|
|
from sqlalchemy import text, inspect
|
|
from app.db.session import engine
|
|
import traceback, os, subprocess
|
|
from app.core.config import DB_DIR
|
|
|
|
try:
|
|
# Check directory structure and permissions
|
|
storage_info = {
|
|
"app_dir_exists": os.path.exists("/app"),
|
|
"app_dir_writable": os.access("/app", os.W_OK),
|
|
"storage_dir_exists": os.path.exists("/app/storage"),
|
|
"storage_dir_writable": os.access("/app/storage", os.W_OK) if os.path.exists("/app/storage") else False,
|
|
"db_dir_exists": os.path.exists(str(DB_DIR)),
|
|
"db_dir_writable": os.access(str(DB_DIR), os.W_OK) if os.path.exists(str(DB_DIR)) else False,
|
|
}
|
|
|
|
# Get disk usage information
|
|
disk_usage = {}
|
|
try:
|
|
df_output = subprocess.check_output(["df", "-h", "/app/storage"]).decode()
|
|
disk_usage["df_output"] = df_output.strip().split('\n')
|
|
except Exception as e:
|
|
disk_usage["error"] = str(e)
|
|
|
|
# Try database connection
|
|
connection_info = {}
|
|
inspector = None
|
|
try:
|
|
with engine.connect() as conn:
|
|
connection_info["connection"] = "successful"
|
|
connection_info["test_query"] = conn.execute(text("SELECT 1")).scalar()
|
|
inspector = inspect(engine)
|
|
except Exception as e:
|
|
connection_info["connection"] = "failed"
|
|
connection_info["error"] = str(e)
|
|
|
|
# Get table information if connection successful
|
|
table_info = {}
|
|
if inspector:
|
|
tables = inspector.get_table_names()
|
|
connection_info["tables"] = tables
|
|
|
|
for table in tables:
|
|
columns = inspector.get_columns(table)
|
|
table_info[table] = [col['name'] for col in columns]
|
|
|
|
# Try to query task table if it exists
|
|
if 'task' in tables:
|
|
with engine.connect() as conn:
|
|
try:
|
|
task_count = conn.execute(text("SELECT COUNT(*) FROM task")).scalar()
|
|
connection_info["task_count"] = task_count
|
|
except Exception as e:
|
|
connection_info["task_query_error"] = str(e)
|
|
|
|
# Database file information
|
|
db_file = f"{DB_DIR}/db.sqlite"
|
|
db_file_info = {
|
|
"path": db_file,
|
|
"exists": os.path.exists(db_file),
|
|
"size_bytes": os.path.getsize(db_file) if os.path.exists(db_file) else 0,
|
|
"writable": os.access(db_file, os.W_OK) if os.path.exists(db_file) else False,
|
|
}
|
|
|
|
# SQLAlchemy configuration
|
|
from app.core.config import settings
|
|
db_config = {
|
|
"sqlalchemy_url": settings.SQLALCHEMY_DATABASE_URL,
|
|
"connect_args": {"check_same_thread": False}
|
|
}
|
|
|
|
# Test file creation
|
|
write_test = {}
|
|
try:
|
|
test_file = f"{DB_DIR}/test_db.txt"
|
|
with open(test_file, 'w') as f:
|
|
f.write("Test write access")
|
|
write_test["success"] = True
|
|
write_test["path"] = test_file
|
|
os.remove(test_file) # Clean up
|
|
except Exception as e:
|
|
write_test["success"] = False
|
|
write_test["error"] = str(e)
|
|
|
|
return {
|
|
"status": "ok",
|
|
"storage_info": storage_info,
|
|
"disk_usage": disk_usage,
|
|
"connection_info": connection_info,
|
|
"table_info": table_info,
|
|
"db_file_info": db_file_info,
|
|
"db_config": db_config,
|
|
"write_test": write_test
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"status": "error",
|
|
"global_error": str(e),
|
|
"traceback": traceback.format_exc()
|
|
} |