FastAPI-utils 重复任务指南:使用@repeat_every实现周期性任务

FastAPI-utils 重复任务指南:使用@repeat_every实现周期性任务

引言

在FastAPI应用开发中,我们经常需要执行一些周期性任务,比如定时清理缓存、定期更新数据库记录等。传统做法是在启动事件中创建循环,但这会带来几个技术挑战:

  1. 启动事件需要快速完成,否则会阻塞服务器启动
  2. 同步IO操作会阻塞事件循环
  3. 异常处理机制不完善

fastapi-utils项目提供的@repeat_every装饰器优雅地解决了这些问题,让开发者能够轻松实现可靠的周期性任务。

基本用法

@repeat_every装饰器的基本使用非常简单。下面是一个典型的使用场景:

from fastapi import FastAPI
from fastapi_utils.tasks import repeat_every
from fastapi_utils.session import FastAPISessionMaker

app = FastAPI()
sessionmaker = FastAPISessionMaker("sqlite:///./test.db")

@app.on_event("startup")
@repeat_every(seconds=60 * 60)  # 每小时执行一次
async def remove_expired_tokens() -> None:
    async with sessionmaker.context_session() as session:
        # 执行清理过期token的逻辑
        pass

关键点说明:

  • 同时使用@app.on_event("startup")@repeat_every确保任务在启动时立即执行并周期性重复
  • seconds参数指定执行间隔(秒)
  • 函数可以是异步(async def)或同步(def)形式

高级配置选项

@repeat_every提供了多个参数来满足不同场景需求:

首次执行时机控制

@repeat_every(seconds=60, wait_first=True)  # 首次执行等待60秒
def task():
    pass
  • wait_first=False(默认):立即执行第一次,然后周期性执行
  • wait_first=True:先等待一个周期,再执行第一次

异常处理机制

import logging

logger = logging.getLogger(__name__)

@repeat_every(seconds=60, logger=logger, raise_exceptions=False)
def risky_task():
    # 可能抛出异常的操作
    pass
  • logger:指定日志记录器,异常会被记录
  • raise_exceptions
    • False(默认):捕获异常不中断任务
    • True:抛出异常并停止任务

执行次数限制

@repeat_every(seconds=60, max_repetitions=10)  # 只执行10次
def limited_task():
    pass
  • max_repetitions=None(默认):无限次执行
  • 设置整数值:限制最大执行次数

技术实现原理

理解@repeat_every的内部机制有助于更好地使用它:

  1. 非阻塞设计:对于同步函数,会自动使用线程池执行,避免阻塞事件循环
  2. 异常隔离:默认捕获任务异常,防止影响主程序
  3. 生命周期管理:与FastAPI生命周期事件无缝集成
  4. 资源清理:服务器关闭时会自动取消周期性任务

最佳实践建议

  1. 日志记录:始终为关键任务配置logger参数,避免静默失败
  2. 超时处理:确保任务执行时间远小于间隔时间
  3. 资源管理:使用上下文管理器管理数据库连接等资源
  4. 测试策略:在测试环境中减小间隔时间,验证任务可靠性
  5. 监控集成:考虑将任务执行情况集成到应用监控系统

常见问题解答

Q:任务执行时间超过间隔时间会怎样? A:@repeat_every会等待当前任务完成后再开始计算下一个间隔,不会并发执行。

Q:如何在开发环境快速测试? A:可以临时设置较小的seconds值(如5秒),但生产环境要恢复合理值。

Q:任务抛异常后如何恢复? A:默认配置下任务会继续执行,如需停止需设置raise_exceptions=True。

Q:能否动态修改间隔时间? A:目前不支持运行时修改,需要重启应用。

通过fastapi-utils的@repeat_every装饰器,开发者可以轻松实现各种周期性任务,同时保证了代码的简洁性和可靠性。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

管雅姝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值