-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.py
More file actions
80 lines (68 loc) · 2.76 KB
/
Copy pathrun.py
File metadata and controls
80 lines (68 loc) · 2.76 KB
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
import logging
from contextlib import asynccontextmanager
from collections.abc import AsyncGenerator
import uvicorn
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from app.config import migrate_providers_to_db, settings
from app.database import async_session, init_db
from app.routes.api import router as api_router
from app.routes.api import run_all_crawlers
from app.routes.settings import router as settings_router
from app.routes.web import router as web_router
from app.summarizer.ai_summarizer import generate_weekly_summary
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
scheduler = AsyncIOScheduler()
async def generate_weekly_summary_job() -> None:
"""定时生成周报,避免调度异常影响主服务。"""
try:
async with async_session() as session:
summary = await generate_weekly_summary(session)
if summary is None:
logger.info("周报周期内没有新增职位,跳过生成")
except Exception:
logger.exception("定时生成周报失败")
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""应用生命周期:启动时初始化数据库和调度器,关闭时停止调度器。"""
await init_db()
await migrate_providers_to_db()
if not scheduler.running:
scheduler.add_job(
run_all_crawlers,
"interval",
hours=settings.crawl_interval_hours,
id="crawl_jobs",
replace_existing=True,
max_instances=1,
)
scheduler.add_job(
generate_weekly_summary_job,
"cron",
day_of_week="sun",
hour=20,
minute=0,
id="weekly_summary",
replace_existing=True,
max_instances=1,
)
scheduler.start()
logger.info("定时采集已启动,间隔 %s 小时", settings.crawl_interval_hours)
logger.info("定时周报已启动:每周日 20:00")
yield
if scheduler.running:
scheduler.shutdown(wait=False)
app = FastAPI(title="招聘信息自动化收集系统", lifespan=lifespan)
app.mount("/static", StaticFiles(directory="app/static"), name="static")
# 当前依赖组合中 include_router 会把 APIRouter 本身挂成空路径 route,
# 不会展开子路由;直接追加已带路径前缀的 route,确保 API/Web 路由注册。
app.router.routes.extend(api_router.routes)
app.router.routes.extend(settings_router.routes)
app.router.routes.extend(web_router.routes)
if __name__ == "__main__":
uvicorn.run("run:app", host="0.0.0.0", port=8000, reload=True)