快速上手#
安装#
# uv
uv add binomic
# pip
pip install binomic
声明任务#
在应用包内的 tasks.py 模块中用装饰器声明任务(Worker 通过
autodiscover 自动发现所有 tasks.py 模块):
# myapp/tasks.py
import time
from binomic.task import task
@task("default")
def example(index: int = 0) -> None:
print(f"[{index}] Current time: {time.time()}")
@task("default", mode="delay", delay=10) # 延迟 10 秒执行
def delayed() -> None: ...
@task("default", mode="cron", cron="*/5 * * * *") # 每 5 分钟执行
def periodic() -> None: ...
@task("default", mode="interval", interval=30) # 每 30 秒执行
def poll() -> None: ...
第一个位置参数是队列名,需与客户端配置中的 queues 对应。任务以函数名的小写形式
注册(上例中为 example、delayed、periodic、poll),投递时用它来指定要执行的任务。
cron 与 interval 两种周期模式的函数不能带参数 —— 周期触发时没有调用参数可传,
声明时会直接抛 ValueError。四种模式的完整说明见任务模式与调度。
启动并投递#
from binomic.client import Binomic, BinomicFactory
from binomic.config import BinomicConfig
from binomic.message import Message
from binomic.task import autodiscover
# 发现 myapp 包内所有 tasks.py 模块并注册任务
autodiscover("myapp")
factory = BinomicFactory(
broker_dsn="redis://localhost:6379/0",
module_name="myapp",
config=BinomicConfig(queues=["default"], workers=2, concurrency=5),
)
binomic: Binomic = factory.create()
# 进入上下文后启动 Master(拉起 worker 子进程)并提供提交入口
async with binomic:
await binomic.submit(Message(name="example", args=[1]))
broker_dsn是唯一需要提供的 Redis 连接:消息投递与消费都走它指向的 Redis Streams;Master 对 Worker 的存活监督走进程间 IPC,不需要 Redis;BinomicConfig中workers是 Master 拉起的 Worker 子进程数量,concurrency是每个 Worker 并发执行的任务数,max_attempts是单条消息的最大尝试 次数 —— 其语义见可靠性;Message的name是任务名,args/kwargs承载调用参数(上例会以index=1调用example)。消息进到哪条 Stream 由任务声明里的队列决定,消息上不需要 也不能指定队列;enqueued_at无需手工赋值:它在实际投递时由客户端写入该消息的 Stream entry (不是Message上的字段),延迟与周期任务也因此每次投递都拿到当前时间。