初始提交:chongming-task 任务控制库

单任务受控执行(15 态状态机 + 审计轨迹)、DAG 管道、Controller 门面。
执行器三个:线程(默认,含 async def 任务)、内联(同步 / 测试)、进程
(spawn 子进程:硬性停止、绕开 GIL、崩溃隔离)。
调度:并发额度 + 每桶限流 + 具名资源信号量(按标签)+ 优先级排队。
持久层:TaskStore 契约 + 内存 / SQLite / Postgres 实现,契约测试随包发布。
跨进程与多节点:写穿 / 读穿、指令通道与租约、owned_buckets 划界、reconcile。
CLI、12 个可直接运行的示例、docs/ 下 5 份文档。

门禁:ruff / ruff format / mypy(strict) 干净;
      pytest 563 passed(44 skipped 是需要真实 Postgres 的那批);
      带一台可连的 Postgres 时 607 passed。
This commit is contained in:
2026-10-08 23:47:50 +08:00
commit f4de43c743
85 changed files with 25809 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
"""示例 1:跑一个任务,并观察它在生命周期中经过的状态。
运行::
uv run python examples/01_quickstart.py
"""
from __future__ import annotations
import time
from chongming_task.run import TaskRun
from chongming_task.runtime.cancellation import CancellationToken
def extract(ctx: CancellationToken, source: str) -> list[int]:
"""模拟一次数据抽取。
要点:长耗时循环里必须周期性地调用 ``ctx.checkpoint()``。它同时做三件事:
响应停止请求、响应暂停请求、刷新心跳。
"""
rows: list[int] = []
for index in range(5):
ctx.checkpoint()
time.sleep(0.05)
rows.append(index)
print(f" 抽取完成:{source} -> {len(rows)} 行")
return rows
def main() -> None:
run = TaskRun(extract, ("s3://demo/rows",), task_id="demo-1", name="抽取")
run.start()
outcome = run.wait(timeout=30)
print("\n状态迁移历史(只追加、可审计):")
for record in run.transitions:
print(
f" {record.from_status.value:>10} -> {record.to_status.value:<10} by {record.trigger}"
)
print(f"\n最终状态:{outcome.status.value}")
print(f"返回值 :{outcome.value}")
elapsed = (outcome.snapshot.ended_at - outcome.snapshot.started_at).total_seconds()
print(f"耗时 :{elapsed:.2f}s")
if __name__ == "__main__":
main()