152 lines
4.3 KiB
Python
152 lines
4.3 KiB
Python
# app/main.py
|
||
import threading
|
||
import time
|
||
from contextlib import asynccontextmanager
|
||
|
||
from fastapi import FastAPI, Request, Response
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
import uvicorn
|
||
|
||
import app.services.crawler as crawler
|
||
import tg_bot as tg_bot
|
||
from app.api.v1 import daily_news, web_tools, analysis
|
||
from app.utils.logger import log
|
||
from app.core import db, cache
|
||
from app.core.config import get_app_config, get_config
|
||
from app.services.browser_manager import BrowserManager
|
||
|
||
# 获取应用配置
|
||
app_config = get_app_config()
|
||
|
||
# 应用启动和关闭的生命周期管理
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
# 启动时执行
|
||
log.info("Application startup")
|
||
|
||
# 初始化数据库连接
|
||
db.init_db()
|
||
|
||
# 初始化缓存
|
||
cache.init_cache()
|
||
|
||
# 异步启动爬虫,避免阻塞应用启动
|
||
threading.Thread(target=crawler.crawlers_logic, daemon=True).start()
|
||
|
||
yield
|
||
|
||
# 关闭时执行
|
||
log.info("Application shutdown")
|
||
|
||
# 关闭浏览器管理器
|
||
try:
|
||
BrowserManager().shutdown()
|
||
log.info("Browser manager shutdown")
|
||
except Exception as e:
|
||
log.error(f"Error shutting down browser manager: {e}")
|
||
|
||
# 关闭数据库连接
|
||
db.close_db()
|
||
|
||
# 关闭缓存连接
|
||
cache.close_cache()
|
||
|
||
# 创建应用实例
|
||
app = FastAPI(
|
||
title=app_config.title,
|
||
description=app_config.description,
|
||
version=app_config.version,
|
||
lifespan=lifespan,
|
||
# Swagger/OpenAPI 配置
|
||
docs_url="/docs", # Swagger UI 路径
|
||
redoc_url="/redoc", # ReDoc 路径
|
||
openapi_url="/openapi.json", # OpenAPI schema 路径
|
||
openapi_tags=[
|
||
{
|
||
"name": "Daily News",
|
||
"description": "每日热点新闻数据接口,支持 22+ 个平台(百度、微博、知乎、GitHub 等)"
|
||
},
|
||
{
|
||
"name": "Website Meta",
|
||
"description": "网站元数据提取工具,可获取指定 URL 的标题、描述、图标等信息"
|
||
},
|
||
{
|
||
"name": "Analysis",
|
||
"description": "新闻趋势分析和预测功能"
|
||
},
|
||
{
|
||
"name": "Health",
|
||
"description": "健康检查接口"
|
||
}
|
||
],
|
||
openapi_extra={
|
||
"externalDocs": {
|
||
"description": "项目源码仓库",
|
||
"url": "https://github.com/hot-news/hot_news-main"
|
||
}
|
||
}
|
||
)
|
||
|
||
# 添加CORS中间件
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=app_config.cors["allow_origins"],
|
||
allow_credentials=app_config.cors["allow_credentials"],
|
||
allow_methods=app_config.cors["allow_methods"],
|
||
allow_headers=app_config.cors["allow_headers"],
|
||
)
|
||
|
||
# 请求计时中间件
|
||
@app.middleware("http")
|
||
async def add_process_time_header(request: Request, call_next):
|
||
start_time = time.time()
|
||
response = await call_next(request)
|
||
process_time = time.time() - start_time
|
||
response.headers["X-Process-Time"] = str(process_time)
|
||
return response
|
||
|
||
# 注册路由
|
||
app.include_router(daily_news.router, prefix="/api/v1/dailynews", tags=["Daily News"])
|
||
app.include_router(web_tools.router, prefix="/api/v1/tools/website-meta", tags=["Website Meta"])
|
||
app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["Analysis"])
|
||
|
||
# 健康检查端点
|
||
@app.get(
|
||
"/health",
|
||
summary="健康检查",
|
||
description="检查 API 服务运行状态,返回服务状态和版本号",
|
||
response_description="返回服务健康状态信息",
|
||
responses={
|
||
200: {
|
||
"description": "服务正常运行",
|
||
"content": {
|
||
"application/json": {
|
||
"example": {
|
||
"status": "healthy",
|
||
"version": "1.0.0"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
tags=["Health"]
|
||
)
|
||
async def health_check():
|
||
"""
|
||
**健康检查接口**
|
||
|
||
用于监控服务运行状态,可用于:
|
||
- 负载均衡器健康检查
|
||
- 容器编排平台存活探测
|
||
- 监控系统状态检测
|
||
|
||
**返回字段:**
|
||
- `status`: 服务状态(healthy/unhealthy)
|
||
- `version`: 当前服务版本
|
||
"""
|
||
return {"status": "healthy", "version": app_config.version}
|
||
|
||
# 如果直接运行此文件
|
||
if __name__ == "__main__":
|
||
uvicorn.run("app.main:app", host=app_config.host, port=app_config.port, reload=app_config.debug)
|