fastapi apscheduler 集成简单说明

对于 fastapi apscheduler 集成以及支持动态添加任务的简单说明

参考使用

  • 依赖
    包含了fastapi,apscheduler sqlalchemy uvicorn
pip install fastapi apscheduler sqlalchemy uvicorn
  • 代码简单说明
    代码使用了基于数据库jobstores,同时演示了一个简单的编程模式添加job(动态加载模块方式)以及基于配置的job 初始化
    yaml 格式配置的job 定义
version: v1
tasks:
 - name: baidu
   modulename: mytask
   taskname: task
   interval: 5
 - name: google
   modulename: mytaskv2
   taskname: task
   interval: 5

fastapi 集成代码

from fastapi import FastAPI
from apscheduler.schedulers.asyncio import AsyncIOScheduler as Scheduler
from apscheduler.triggers.interval import IntervalTrigger
from importlib import import_module
from contextlib import asynccontextmanager
import logging
logging.basicConfig()
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
 
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from sqlalchemy import create_engine
 
from config import config
from apscheduler.events import EVENT_ALL,JobEvent
 
# Database URL
DATABASE_URL = "sqlite:///./test.db"
 
# Create the database engine
engine = create_engine(DATABASE_URL)
 
# Configure the job store
jobstores = {
    'default': SQLAlchemyJobStore(engine=engine)
}
 
scheduler = Scheduler(jobstores=jobstores)
 
def listener(event:JobEvent) -> None:
    print(event)
 
@asynccontextmanager
async def lifespan(app: FastAPI):
    myconfig = config()
    app.state.scheduler = scheduler
    scheduler.add_listener(listener, EVENT_ALL)
    for task in myconfig.tasks:
        module = import_module(task.get('modulename'))
        interval = task.get('interval')
        print("interval", interval)
        scheduler.add_job(getattr(module, task.get('taskname')), IntervalTrigger(seconds=interval))
    scheduler.start()
    yield
    app.state.scheduler.shutdown()
 
app = FastAPI(lifespan=lifespan)
 
@app.get("/")
async def read_root():
    return {"message": "Hello World"}
 
 
@app.get("/lists")
async def tasklists():
    return [ item.id for item in  scheduler.get_jobs() ] 
 
@app.get("/add")
async def addtask():
    module = import_module("mytaskv3")
    interval = 3
    task = getattr(module, "task")
   # 动态加载模式
    job = scheduler.add_job(task,IntervalTrigger(seconds=interval),name="mydemo",id="mydemo")
    return dict(id=job.id, name=job.name, next_run_time=job.next_run_time)
 
if __name__ == "__main__":
    import uvicorn
    try:
        uvicorn.run(app, host="0.0.0.0", port=8000)
    except KeyboardInterrupt as e:
        print(e)

动态加载简单说明,核心是对于开发好的任务通过import_module 进行模块加载,之后通过属性获取实际的任务方法

说明

注意目前使用的apscheduler 版本是3.10.4 当前4.0 版本还处于预发布阶段,很多使用上变化还是比较大的,目前apscheduler 对于任务依赖上是缺少支持的,也是可以做,但是并不是很方便,此场景rocketry 是一个不错的选择,但是目前看着是缺少维护了,从使用上两个实际上可以配置起来使用,可以解决一些依赖的问题

参考资料

https://github.com/agronholm/apscheduler
https://fastapi.tiangolo.com/advanced/events/
https://apscheduler.readthedocs.io/en/3.x/versionhistory.html
https://github.com/Miksus/rocketry

posted on 2024-07-26 08:00  荣锋亮  阅读(44)  评论(0编辑  收藏  举报

导航