Files
chongming-utils-task/examples/04_controller.py
T
chakcy f4de43c743 初始提交: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。
2026-10-08 23:47:50 +08:00

83 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""示例 4:用 Controller 管理一批任务(注册 / 提交 / 排队 / 查询 / 控制)。
这是管理后台的核心:**一个统一入口**持有任务定义、运行中的任务与并发额度。
将来的 CLI 或看板都只是这一层的薄适配。
运行::
uv run python examples/04_controller.py
"""
from __future__ import annotations
import time
from chongming_task.controller import Controller, render_table
def transform(ctx, rows: int) -> int:
"""转换:逐行推进。"""
for _ in range(30):
ctx.checkpoint()
time.sleep(0.02)
return rows * 2
def extract(ctx, source: str) -> str:
"""抽取:比转换慢一倍。"""
for _ in range(60):
ctx.checkpoint()
time.sleep(0.02)
return f"{source} -> 1200 行"
def main() -> None:
controller = Controller(max_parallel=2)
controller.register("transform", transform, tags={"cpu"})
controller.register("extract", extract, tags={"io"})
controller.register("load", transform, description="写回目标库")
print("已注册任务:", "、".join(controller.registry.names()))
print("并发上限:2\n")
for index in range(4):
controller.submit(
"transform", 100 * (index + 1), task_id=f"t{index}", label=f"转换-{index + 1}"
)
print(f"提交了 4 个任务;此刻排队 {controller.queued_count} 个(超出并发上限的部分)")
time.sleep(0.4)
print("\n--- 查询:运行中的视图 ---")
print(render_table(controller.list_tasks()))
stats = controller.stats()
print(
f" 未结束 {stats.unfinished}"
f"(其中排队 {controller.queued_count},占用执行额度 {controller.active_count})"
)
controller.wait_all(timeout=30)
print("\n--- 查询:全部结束 ---")
print(render_table(controller.list_tasks()))
print("\n>>> 提交一个长任务,然后中途停止它")
controller.submit("extract", "s3://demo/big", task_id="t-long", label="抽取(大)")
time.sleep(0.3)
print(f" 当前状态:{controller.get('t-long').status.value}")
controller.stop("t-long", reason="手工干预")
outcome = controller.wait("t-long", timeout=10)
print(
f" 终态:{outcome.status.value}"
f"(失败归类 {outcome.failure.kind.value},可重试 {outcome.failure.retryable})"
)
print("\n--- 最终统计 ---")
final = controller.stats()
for status, count in sorted(final.by_status.items(), key=lambda item: item[0].value):
print(f" {status.value:<10} {count}")
print("\n提示:另一个进程里的 chongming-task ps 看不到这些任务——内存不共享,")
print(" 跨进程查询需要共享存储(stdlib sqlite3),那是下一步。")
if __name__ == "__main__":
main()