"""示例 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()