celestialflow 3.2.3__tar.gz → 3.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {celestialflow-3.2.3 → celestialflow-3.2.5}/PKG-INFO +43 -66
- {celestialflow-3.2.3 → celestialflow-3.2.5}/README.md +42 -62
- {celestialflow-3.2.3 → celestialflow-3.2.5}/pyproject.toml +3 -4
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/__init__.py +11 -15
- celestialflow-3.2.5/src/celestialflow/funnel/core_inlet.py +48 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/funnel/core_spout.py +63 -28
- celestialflow-3.2.5/src/celestialflow/funnel/util_count.py +51 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/graph/core_graph.py +97 -156
- celestialflow-3.2.5/src/celestialflow/graph/util_graph.py +344 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/observability/__init__.py +1 -2
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/observability/core_observer.py +0 -16
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/observability/core_report.py +98 -108
- {celestialflow-3.2.3/src/celestialflow/graph → celestialflow-3.2.5/src/celestialflow/observability}/util_types.py +5 -4
- celestialflow-3.2.5/src/celestialflow/persistence/__init__.py +10 -0
- celestialflow-3.2.5/src/celestialflow/persistence/core_fallback.py +225 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/persistence/core_log.py +8 -23
- celestialflow-3.2.5/src/celestialflow/persistence/util_payload.py +24 -0
- celestialflow-3.2.5/src/celestialflow/persistence/util_sqlite.py +621 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/core_dispatch.py +22 -9
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/core_envelope.py +3 -18
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/core_metrics.py +5 -27
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/core_queue.py +11 -15
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/util_constant.py +4 -4
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/util_errors.py +58 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/util_estimators.py +8 -7
- celestialflow-3.2.5/src/celestialflow/runtime/util_event.py +63 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/util_types.py +0 -37
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/stage/__init__.py +0 -6
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/stage/core_executor.py +111 -128
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/stage/core_stage.py +236 -242
- celestialflow-3.2.5/src/celestialflow/stage/core_stages.py +287 -0
- celestialflow-3.2.5/src/celestialflow/stage/util_callable.py +31 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/utils/util_clone.py +5 -10
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/config.json +3 -3
- celestialflow-3.2.5/src/celestialflow/web/core_server.py +444 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/routes/pull_routes.py +149 -137
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/routes/push_routes.py +70 -89
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/base.css +40 -0
- celestialflow-3.2.5/src/celestialflow/web/static/css/dashboard_error_types.css +100 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/injection_editor.css +8 -17
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/injection_layout.css +0 -37
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/dashboard_analysis.js +5 -4
- celestialflow-3.2.5/src/celestialflow/web/static/js/dashboard_error_types.js +223 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/dashboard_history.js +25 -13
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/errors.js +9 -7
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/i18n.js +42 -12
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/injection.js +41 -21
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/layout_editor.js +1 -1
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/main.js +21 -3
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/web_config.js +28 -1
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/dashboard_analysis.ts +6 -3
- celestialflow-3.2.5/src/celestialflow/web/static/ts/dashboard_error_types.ts +247 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/dashboard_history.ts +25 -13
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/errors.ts +14 -10
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/globals.d.ts +157 -146
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/i18n.ts +524 -488
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/injection.ts +47 -22
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/layout_editor.ts +1 -1
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/main.ts +22 -3
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/web_config.ts +28 -1
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/templates/index.html +37 -8
- celestialflow-3.2.5/src/celestialflow/web/util_error.py +30 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/util_models.py +9 -10
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/PKG-INFO +43 -66
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/SOURCES.txt +11 -5
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/requires.txt +0 -3
- celestialflow-3.2.3/src/celestialflow/funnel/core_inlet.py +0 -22
- celestialflow-3.2.3/src/celestialflow/graph/util_analysis.py +0 -70
- celestialflow-3.2.3/src/celestialflow/persistence/__init__.py +0 -12
- celestialflow-3.2.3/src/celestialflow/persistence/core_fail.py +0 -179
- celestialflow-3.2.3/src/celestialflow/persistence/core_success.py +0 -43
- celestialflow-3.2.3/src/celestialflow/persistence/util_jsonl.py +0 -214
- celestialflow-3.2.3/src/celestialflow/stage/core_stages.py +0 -559
- celestialflow-3.2.3/src/celestialflow/web/core_server.py +0 -219
- celestialflow-3.2.3/src/celestialflow/web/util_error.py +0 -86
- {celestialflow-3.2.3 → celestialflow-3.2.5}/setup.cfg +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/funnel/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/graph/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/graph/core_structure.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/graph/util_serialize.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/observability/core_progress.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/runtime/util_hash.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/stage/util_types.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/utils/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/utils/util_benchmark.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/utils/util_collections.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/utils/util_format.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/routes/__init__.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/_colors.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard_analysis.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard_history.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard_statuses.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard_structure.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/dashboard_summary.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/errors.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/injection_nodes.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/css/injection_preview.css +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/favicon.ico +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/dashboard_statuses.js +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/dashboard_structure.js +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/dashboard_summary.js +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/js/utils.js +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/dashboard_statuses.ts +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/dashboard_structure.ts +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/dashboard_summary.ts +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/static/ts/utils.ts +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/util_cal.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow/web/util_config.py +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/dependency_links.txt +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/entry_points.txt +0 -0
- {celestialflow-3.2.3 → celestialflow-3.2.5}/src/celestialflow.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: celestialflow
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.5
|
|
4
4
|
Summary: A flexible GRAPH-based task orchestration framework.
|
|
5
5
|
Author-email: Mr-xiaotian <mingxiaomingtian@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -18,10 +18,7 @@ Requires-Dist: tqdm
|
|
|
18
18
|
Requires-Dist: fastapi
|
|
19
19
|
Requires-Dist: uvicorn
|
|
20
20
|
Requires-Dist: requests
|
|
21
|
-
Requires-Dist: networkx
|
|
22
|
-
Requires-Dist: redis
|
|
23
21
|
Requires-Dist: jinja2
|
|
24
|
-
Requires-Dist: celestialtree>=0.1.3
|
|
25
22
|
|
|
26
23
|
# CelestialFlow ——一个轻量级、可并行、基于图结构的 Python 任务调度框架
|
|
27
24
|
|
|
@@ -39,8 +36,8 @@ Requires-Dist: celestialtree>=0.1.3
|
|
|
39
36
|
<p align="center">
|
|
40
37
|
<img src="https://img.shields.io/badge/Task%20Graph-DAG-blueviolet">
|
|
41
38
|
<img src="https://img.shields.io/badge/Workflow-Orchestrator-7c3aed">
|
|
42
|
-
<img src="https://img.shields.io/badge/
|
|
43
|
-
<img src="https://img.shields.io/badge/
|
|
39
|
+
<img src="https://img.shields.io/badge/Event%20Tracing-CelestialTree-0ea5e9">
|
|
40
|
+
<img src="https://img.shields.io/badge/Web-Dashboard-FastAPI-ec4899">
|
|
44
41
|
</p>
|
|
45
42
|
|
|
46
43
|
<p align="center">
|
|
@@ -73,7 +70,7 @@ TaskGraph 能构建完整的 **有向图结构(Directed Graph)**,不仅支
|
|
|
73
70
|
|
|
74
71
|
在执行与调度之外,CelestialFlow 进一步引入 **CelestialTree(简称: ctree) 事件追踪系统**,为每一个任务及其衍生行为(成功、失败、重试、拆分、路由等)记录明确的因果关系。借助 ctree,可以从任意一个初始任务出发,完整还原其在 TaskGraph 中的传播路径与执行轨迹,使任务系统可以进行完整的**追溯、分析、解释**。
|
|
75
72
|
|
|
76
|
-
在此基础上,CelestialFlow 支持 Web
|
|
73
|
+
在此基础上,CelestialFlow 支持 Web 可视化监控,并提供基于 Redis 的 demo 与 Go Worker 外部协作示例,用于展示按需构建跨进程、跨设备任务协作的方式。
|
|
77
74
|
|
|
78
75
|
## 项目结构(Project Structure)
|
|
79
76
|
|
|
@@ -136,6 +133,18 @@ uv pip install celestialflow
|
|
|
136
133
|
pip install celestialflow
|
|
137
134
|
```
|
|
138
135
|
|
|
136
|
+
如果你只使用 CelestialFlow 的核心调度、Web、持久化与 demo/test 之外的常规功能,上面的安装已经足够。
|
|
137
|
+
|
|
138
|
+
如果你还需要启用 CelestialTree 事件追踪能力,则需要**额外安装** `celestialtree`:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# 对已发布包使用者
|
|
142
|
+
uv pip install celestialtree
|
|
143
|
+
|
|
144
|
+
# 如果你是 clone 仓库后的开发者/贡献者
|
|
145
|
+
uv sync --group dev
|
|
146
|
+
```
|
|
147
|
+
|
|
139
148
|
一个简单的可运行代码:
|
|
140
149
|
|
|
141
150
|
```python
|
|
@@ -215,7 +224,7 @@ flowchart TD
|
|
|
215
224
|
- [runtime/util_hash.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_hash.md)
|
|
216
225
|
- [runtime/util_types.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_types.md)
|
|
217
226
|
- [runtime/util_errors.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_errors.md)
|
|
218
|
-
- [persistence/
|
|
227
|
+
- [persistence/core_fallback.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_fallback.md)
|
|
219
228
|
- [persistence/core_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_log.md)
|
|
220
229
|
|
|
221
230
|
如果你更喜欢通过完整案例理解框架的运行方式,可以参考这篇利用 TaskGraph 从零开始构建项目的教程:
|
|
@@ -228,20 +237,20 @@ flowchart TD
|
|
|
228
237
|
|
|
229
238
|
你可以继续运行更多的演示代码,这里记录了各个演示文件与其中的演示函数说明:
|
|
230
239
|
|
|
231
|
-
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
240
|
+
[🎮demo/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/demo/README.md)
|
|
232
241
|
|
|
233
|
-
|
|
242
|
+
如果你想运行测试代码,可以先查看如下文档内容:
|
|
234
243
|
|
|
235
|
-
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
244
|
+
[🧪tests/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/tests/README.md)
|
|
236
245
|
|
|
237
|
-
如果你想查看bench
|
|
246
|
+
如果你想查看 bench 内容,这些数据也是框架中部分设计取舍的依据:
|
|
238
247
|
|
|
239
|
-
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
248
|
+
[⚡bench/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/bench/README.md)
|
|
240
249
|
|
|
241
250
|
## 环境要求(Requirements)
|
|
242
251
|
|
|
243
|
-
**CelestialFlow** 基于 Python 3.12
|
|
244
|
-
|
|
252
|
+
**CelestialFlow** 基于 Python 3.12+,默认运行时依赖以下核心组件。
|
|
253
|
+
其中 `celestialtree` 不再属于默认运行时依赖,而是额外安装的可选组件。
|
|
245
254
|
|
|
246
255
|
| 依赖包 | 说明 |
|
|
247
256
|
| ----------------- | ---- |
|
|
@@ -249,76 +258,44 @@ flowchart TD
|
|
|
249
258
|
| **fastapi** | Web 服务接口框架(用于任务可视化与远程控制) |
|
|
250
259
|
| **uvicorn** | FastAPI 的高性能 ASGI 服务器 |
|
|
251
260
|
| **requests** | HTTP 客户端库,用于任务状态上报与远程调用 |
|
|
252
|
-
| **networkx** | 任务图(TaskGraph)结构与依赖分析 |
|
|
253
261
|
| **jinja2** | FastAPI 模板引擎,用于 Web 可视化界面渲染 |
|
|
254
262
|
| **tqdm** | 可选组件,进度条显示,用于任务执行可视化 |
|
|
255
|
-
|
|
256
|
-
|
|
263
|
+
|
|
264
|
+
如需运行 `demo/demo_redis.py` 或 Go Worker 示例,请额外安装 `redis` 并准备 Redis 服务;这部分不属于默认运行时依赖。
|
|
265
|
+
|
|
266
|
+
如需运行依赖 CelestialTree 的 demo / bench / 追踪查询,请额外安装 `celestialtree`,或直接在源码仓库中执行 `uv sync --group dev`。
|
|
257
267
|
|
|
258
268
|
## 文件结构(File Structure)
|
|
259
269
|
|
|
260
270
|
<p align="center">
|
|
261
271
|
<img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
|
|
262
272
|
<br/>
|
|
263
|
-
<em>celestial-flow 3.2.
|
|
273
|
+
<em>celestial-flow 3.2.5</em>
|
|
264
274
|
</p>
|
|
265
275
|
|
|
266
276
|
(该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
|
|
267
277
|
|
|
268
278
|
## 版本日志(Version Log)
|
|
269
|
-
- 3.2.
|
|
279
|
+
- 3.2.5
|
|
270
280
|
- feat:
|
|
271
|
-
-
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
|
|
275
|
-
- **[IMPORTANT]** 移除 `TaskExecutor` 中 `get_args` 与 `process_result` 两个方法, 以及 `unpack_task_args` 属性
|
|
276
|
-
- 这是为引入泛型必要的修改
|
|
277
|
-
- `process_result` 功能很简单, 对func输出的result进行再次处理, 但事实上在输入func前对齐进行包装也能达到一样的效果
|
|
278
|
-
- `get_args` 功能更为复杂, 可以直接将前一节点提供的 `result` 转为当前节点所需的 `task` 类型, 非常灵活; 但问题在于太过灵活, 导致使用心智负担很大
|
|
279
|
-
- `unpack_task_args` 就是 `get_args` 带来的一项心智负担, 默认 `get_args` 会把 `task` 进行 `(task, )` 包裹后发送给func, 开启 `unpack_task_args` 后则直接发送
|
|
280
|
-
- **[IMPORTANT]** `graph` 的init参数中添加 `name`, 以与 `executor` `stage` 一致
|
|
281
|
-
- 破坏接口破坏性更新
|
|
282
|
-
- 在日志的 `start_graph` `end_graph` 与web端的 `graph_anaylysis` 中都有显示
|
|
283
|
-
- 彻底移除前后端通信中的 `graph_summary` , 原本残余的 `全局剩余时间` 现在拆为各个节点的 `全局等待` 与 `全局剩余时间`
|
|
284
|
-
- 这里所说的 `全局` 意为根据图论关系, 由上游剩余的任务数估算下游总共能获得多少任务
|
|
285
|
-
- 例如: 图关系 `A -> B`, A已处理任务2, 未处理任务3, B已处理任务4, 未处理任务2. 这意味着A成功的2个任务为B带来总共了6个任务, 那么我们可以据此估计B总功能获取"3/2*6=9"个任务, 因此B的 `等待` 任务数量为2, 但 `全局等待` 任务数量为5
|
|
286
|
-
- 前端中添加部分提示气泡, 鼠标放上去后可以介绍相关信息, 例如本次新加入的节点 `全局等待` 的含义
|
|
287
|
-
- 移除前端中节点卡片的拖拽功能
|
|
288
|
-
- 这个功能是在最早加入web页面时添加的, 当时感觉很帅, 但现在有点玩腻了
|
|
289
|
-
- 前端错误日志页面添加 `任务注入` 按钮, 可以把选定任务直接添加到任务注入页面中节点的代注入任务列表中
|
|
290
|
-
- 在 `TaskSplitter` 中添加 `split_item` 方法, 可自由定义
|
|
291
|
-
- 原本的 `splitter` 非常依赖于 `get_args`, 现在通过 `split_item` 方法稍微弥补其缺失的灵活性
|
|
281
|
+
- 在 `Spout` 和 `Inlet` 中 添加 `counter`, 对 `queue` 中未消费任务的数量进行记录
|
|
282
|
+
- 在上版本大幅修改 `fallback` 机制后, `FallbackSpout` 中很有可能出现任务堆积, 进而导致误判
|
|
283
|
+
- 在web端错误日志页面对当前显示的错误数量可能与node_status中的error数量不一致的情况进行说明
|
|
284
|
+
- 在web端仪表盘页面添加错误分类的饼图
|
|
292
285
|
- refactor:
|
|
293
|
-
-
|
|
294
|
-
|
|
295
|
-
-
|
|
296
|
-
-
|
|
297
|
-
- 在已经有config配置文件的情况下意义不大, 反而会带来困扰
|
|
298
|
-
- 将任务队列的drain操作从graph层移至stage层
|
|
299
|
-
- 之前不能这样做是因为节点的 `stage_mode` 可能为 `process`, 此时在主进程持有的节点非真实运行的节点
|
|
300
|
-
- 算是3.2.0版本带来的持久影响之一
|
|
301
|
-
- 优化 `TaskMetric` 中对锁的使用
|
|
302
|
-
- 移除 `TaskEnvelope` 中的 `change_id()` 方法, 现在默认envelope不可变, 同时 `emit_retry_envelope` 中不再把原有的envelope的id修改后继续提交给worker, 而是直接使用新生成的envelope
|
|
303
|
-
- 移除错误日志中的 `error` `error_repr` `task_repr` 字段
|
|
304
|
-
- 修改前后端通信中任务注入数据的格式, 以方便同时提交多个节点的任务数据
|
|
305
|
-
- 前端代码中开启strict检查
|
|
306
|
-
- 将前端中 `injection.css` 文件拆分成多个文件
|
|
307
|
-
- 修改 `config.json` 的数据格式, 现在按照生效区域进行分类
|
|
308
|
-
- 收紧前端中的数据类型
|
|
309
|
-
- 添加 `ReportTaskGraph` 类型, 专门用于给reporter做类型声明
|
|
286
|
+
- 移除对 `networkx` 的依赖, 添加 `util_graph`, 实现所有图论分析
|
|
287
|
+
- `TaskExecutor` 中将 `enable_duplicate_check` 默认改为 `False`
|
|
288
|
+
- 在duplicate机制中一直有一个内存持续增长点: `processed_set`, 这导致 `enable_duplicate_check` 在大规模的任务下会导致很大的内存压力
|
|
289
|
+
- 分离server端的 `push_task` 和 `push_termination`
|
|
310
290
|
- fix:
|
|
311
|
-
-
|
|
312
|
-
- 直接点击仪表盘中错误数字跳转到错误日志页后, 设置面板显示的还是仪表盘页面的设置
|
|
313
|
-
- 前端中为各项仪表盘请求添加 `RequestSeq`, 以避免前后发送两个请求, 但因为延迟关系, 先发送的请求的返回覆盖掉后发送请求的返回
|
|
314
|
-
- 修复前端中各项空字段需要在第一次refresh才显示的问题, 体感上会导致"加载"很慢
|
|
291
|
+
- 修复 `UnconsumedError` 在 `drain_task_queue` 中被计算两次的问题
|
|
315
292
|
- chore:
|
|
316
|
-
-
|
|
317
|
-
|
|
293
|
+
- `img/` 中添加全新的 `web_display.png` 图片
|
|
294
|
+
- 完善几个skill, 现在对主agent与子agent的prompt进行分离
|
|
318
295
|
|
|
319
296
|
更多过往日志可看:
|
|
320
297
|
|
|
321
|
-
[change_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/change_log.md
|
|
298
|
+
[change_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/change_log.md)
|
|
322
299
|
|
|
323
300
|
## Star 历史趋势(Star History)
|
|
324
301
|
|
|
@@ -327,7 +304,7 @@ flowchart TD
|
|
|
327
304
|

|
|
328
305
|
|
|
329
306
|
## 许可(License)
|
|
330
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
307
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/LICENSE) file for details.
|
|
331
308
|
|
|
332
309
|
## 作者(Author)
|
|
333
310
|
Author: Mr-xiaotian
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
<p align="center">
|
|
15
15
|
<img src="https://img.shields.io/badge/Task%20Graph-DAG-blueviolet">
|
|
16
16
|
<img src="https://img.shields.io/badge/Workflow-Orchestrator-7c3aed">
|
|
17
|
-
<img src="https://img.shields.io/badge/
|
|
18
|
-
<img src="https://img.shields.io/badge/
|
|
17
|
+
<img src="https://img.shields.io/badge/Event%20Tracing-CelestialTree-0ea5e9">
|
|
18
|
+
<img src="https://img.shields.io/badge/Web-Dashboard-FastAPI-ec4899">
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
@@ -48,7 +48,7 @@ TaskGraph 能构建完整的 **有向图结构(Directed Graph)**,不仅支
|
|
|
48
48
|
|
|
49
49
|
在执行与调度之外,CelestialFlow 进一步引入 **CelestialTree(简称: ctree) 事件追踪系统**,为每一个任务及其衍生行为(成功、失败、重试、拆分、路由等)记录明确的因果关系。借助 ctree,可以从任意一个初始任务出发,完整还原其在 TaskGraph 中的传播路径与执行轨迹,使任务系统可以进行完整的**追溯、分析、解释**。
|
|
50
50
|
|
|
51
|
-
在此基础上,CelestialFlow 支持 Web
|
|
51
|
+
在此基础上,CelestialFlow 支持 Web 可视化监控,并提供基于 Redis 的 demo 与 Go Worker 外部协作示例,用于展示按需构建跨进程、跨设备任务协作的方式。
|
|
52
52
|
|
|
53
53
|
## 项目结构(Project Structure)
|
|
54
54
|
|
|
@@ -111,6 +111,18 @@ uv pip install celestialflow
|
|
|
111
111
|
pip install celestialflow
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
如果你只使用 CelestialFlow 的核心调度、Web、持久化与 demo/test 之外的常规功能,上面的安装已经足够。
|
|
115
|
+
|
|
116
|
+
如果你还需要启用 CelestialTree 事件追踪能力,则需要**额外安装** `celestialtree`:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# 对已发布包使用者
|
|
120
|
+
uv pip install celestialtree
|
|
121
|
+
|
|
122
|
+
# 如果你是 clone 仓库后的开发者/贡献者
|
|
123
|
+
uv sync --group dev
|
|
124
|
+
```
|
|
125
|
+
|
|
114
126
|
一个简单的可运行代码:
|
|
115
127
|
|
|
116
128
|
```python
|
|
@@ -190,7 +202,7 @@ flowchart TD
|
|
|
190
202
|
- [runtime/util_hash.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_hash.md)
|
|
191
203
|
- [runtime/util_types.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_types.md)
|
|
192
204
|
- [runtime/util_errors.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_errors.md)
|
|
193
|
-
- [persistence/
|
|
205
|
+
- [persistence/core_fallback.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_fallback.md)
|
|
194
206
|
- [persistence/core_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_log.md)
|
|
195
207
|
|
|
196
208
|
如果你更喜欢通过完整案例理解框架的运行方式,可以参考这篇利用 TaskGraph 从零开始构建项目的教程:
|
|
@@ -203,20 +215,20 @@ flowchart TD
|
|
|
203
215
|
|
|
204
216
|
你可以继续运行更多的演示代码,这里记录了各个演示文件与其中的演示函数说明:
|
|
205
217
|
|
|
206
|
-
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
218
|
+
[🎮demo/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/demo/README.md)
|
|
207
219
|
|
|
208
|
-
|
|
220
|
+
如果你想运行测试代码,可以先查看如下文档内容:
|
|
209
221
|
|
|
210
|
-
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
222
|
+
[🧪tests/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/tests/README.md)
|
|
211
223
|
|
|
212
|
-
如果你想查看bench
|
|
224
|
+
如果你想查看 bench 内容,这些数据也是框架中部分设计取舍的依据:
|
|
213
225
|
|
|
214
|
-
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
226
|
+
[⚡bench/ 总览](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/bench/README.md)
|
|
215
227
|
|
|
216
228
|
## 环境要求(Requirements)
|
|
217
229
|
|
|
218
|
-
**CelestialFlow** 基于 Python 3.12
|
|
219
|
-
|
|
230
|
+
**CelestialFlow** 基于 Python 3.12+,默认运行时依赖以下核心组件。
|
|
231
|
+
其中 `celestialtree` 不再属于默认运行时依赖,而是额外安装的可选组件。
|
|
220
232
|
|
|
221
233
|
| 依赖包 | 说明 |
|
|
222
234
|
| ----------------- | ---- |
|
|
@@ -224,76 +236,44 @@ flowchart TD
|
|
|
224
236
|
| **fastapi** | Web 服务接口框架(用于任务可视化与远程控制) |
|
|
225
237
|
| **uvicorn** | FastAPI 的高性能 ASGI 服务器 |
|
|
226
238
|
| **requests** | HTTP 客户端库,用于任务状态上报与远程调用 |
|
|
227
|
-
| **networkx** | 任务图(TaskGraph)结构与依赖分析 |
|
|
228
239
|
| **jinja2** | FastAPI 模板引擎,用于 Web 可视化界面渲染 |
|
|
229
240
|
| **tqdm** | 可选组件,进度条显示,用于任务执行可视化 |
|
|
230
|
-
|
|
231
|
-
|
|
241
|
+
|
|
242
|
+
如需运行 `demo/demo_redis.py` 或 Go Worker 示例,请额外安装 `redis` 并准备 Redis 服务;这部分不属于默认运行时依赖。
|
|
243
|
+
|
|
244
|
+
如需运行依赖 CelestialTree 的 demo / bench / 追踪查询,请额外安装 `celestialtree`,或直接在源码仓库中执行 `uv sync --group dev`。
|
|
232
245
|
|
|
233
246
|
## 文件结构(File Structure)
|
|
234
247
|
|
|
235
248
|
<p align="center">
|
|
236
249
|
<img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
|
|
237
250
|
<br/>
|
|
238
|
-
<em>celestial-flow 3.2.
|
|
251
|
+
<em>celestial-flow 3.2.5</em>
|
|
239
252
|
</p>
|
|
240
253
|
|
|
241
254
|
(该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
|
|
242
255
|
|
|
243
256
|
## 版本日志(Version Log)
|
|
244
|
-
- 3.2.
|
|
257
|
+
- 3.2.5
|
|
245
258
|
- feat:
|
|
246
|
-
-
|
|
247
|
-
-
|
|
248
|
-
-
|
|
249
|
-
|
|
250
|
-
- **[IMPORTANT]** 移除 `TaskExecutor` 中 `get_args` 与 `process_result` 两个方法, 以及 `unpack_task_args` 属性
|
|
251
|
-
- 这是为引入泛型必要的修改
|
|
252
|
-
- `process_result` 功能很简单, 对func输出的result进行再次处理, 但事实上在输入func前对齐进行包装也能达到一样的效果
|
|
253
|
-
- `get_args` 功能更为复杂, 可以直接将前一节点提供的 `result` 转为当前节点所需的 `task` 类型, 非常灵活; 但问题在于太过灵活, 导致使用心智负担很大
|
|
254
|
-
- `unpack_task_args` 就是 `get_args` 带来的一项心智负担, 默认 `get_args` 会把 `task` 进行 `(task, )` 包裹后发送给func, 开启 `unpack_task_args` 后则直接发送
|
|
255
|
-
- **[IMPORTANT]** `graph` 的init参数中添加 `name`, 以与 `executor` `stage` 一致
|
|
256
|
-
- 破坏接口破坏性更新
|
|
257
|
-
- 在日志的 `start_graph` `end_graph` 与web端的 `graph_anaylysis` 中都有显示
|
|
258
|
-
- 彻底移除前后端通信中的 `graph_summary` , 原本残余的 `全局剩余时间` 现在拆为各个节点的 `全局等待` 与 `全局剩余时间`
|
|
259
|
-
- 这里所说的 `全局` 意为根据图论关系, 由上游剩余的任务数估算下游总共能获得多少任务
|
|
260
|
-
- 例如: 图关系 `A -> B`, A已处理任务2, 未处理任务3, B已处理任务4, 未处理任务2. 这意味着A成功的2个任务为B带来总共了6个任务, 那么我们可以据此估计B总功能获取"3/2*6=9"个任务, 因此B的 `等待` 任务数量为2, 但 `全局等待` 任务数量为5
|
|
261
|
-
- 前端中添加部分提示气泡, 鼠标放上去后可以介绍相关信息, 例如本次新加入的节点 `全局等待` 的含义
|
|
262
|
-
- 移除前端中节点卡片的拖拽功能
|
|
263
|
-
- 这个功能是在最早加入web页面时添加的, 当时感觉很帅, 但现在有点玩腻了
|
|
264
|
-
- 前端错误日志页面添加 `任务注入` 按钮, 可以把选定任务直接添加到任务注入页面中节点的代注入任务列表中
|
|
265
|
-
- 在 `TaskSplitter` 中添加 `split_item` 方法, 可自由定义
|
|
266
|
-
- 原本的 `splitter` 非常依赖于 `get_args`, 现在通过 `split_item` 方法稍微弥补其缺失的灵活性
|
|
259
|
+
- 在 `Spout` 和 `Inlet` 中 添加 `counter`, 对 `queue` 中未消费任务的数量进行记录
|
|
260
|
+
- 在上版本大幅修改 `fallback` 机制后, `FallbackSpout` 中很有可能出现任务堆积, 进而导致误判
|
|
261
|
+
- 在web端错误日志页面对当前显示的错误数量可能与node_status中的error数量不一致的情况进行说明
|
|
262
|
+
- 在web端仪表盘页面添加错误分类的饼图
|
|
267
263
|
- refactor:
|
|
268
|
-
-
|
|
269
|
-
|
|
270
|
-
-
|
|
271
|
-
-
|
|
272
|
-
- 在已经有config配置文件的情况下意义不大, 反而会带来困扰
|
|
273
|
-
- 将任务队列的drain操作从graph层移至stage层
|
|
274
|
-
- 之前不能这样做是因为节点的 `stage_mode` 可能为 `process`, 此时在主进程持有的节点非真实运行的节点
|
|
275
|
-
- 算是3.2.0版本带来的持久影响之一
|
|
276
|
-
- 优化 `TaskMetric` 中对锁的使用
|
|
277
|
-
- 移除 `TaskEnvelope` 中的 `change_id()` 方法, 现在默认envelope不可变, 同时 `emit_retry_envelope` 中不再把原有的envelope的id修改后继续提交给worker, 而是直接使用新生成的envelope
|
|
278
|
-
- 移除错误日志中的 `error` `error_repr` `task_repr` 字段
|
|
279
|
-
- 修改前后端通信中任务注入数据的格式, 以方便同时提交多个节点的任务数据
|
|
280
|
-
- 前端代码中开启strict检查
|
|
281
|
-
- 将前端中 `injection.css` 文件拆分成多个文件
|
|
282
|
-
- 修改 `config.json` 的数据格式, 现在按照生效区域进行分类
|
|
283
|
-
- 收紧前端中的数据类型
|
|
284
|
-
- 添加 `ReportTaskGraph` 类型, 专门用于给reporter做类型声明
|
|
264
|
+
- 移除对 `networkx` 的依赖, 添加 `util_graph`, 实现所有图论分析
|
|
265
|
+
- `TaskExecutor` 中将 `enable_duplicate_check` 默认改为 `False`
|
|
266
|
+
- 在duplicate机制中一直有一个内存持续增长点: `processed_set`, 这导致 `enable_duplicate_check` 在大规模的任务下会导致很大的内存压力
|
|
267
|
+
- 分离server端的 `push_task` 和 `push_termination`
|
|
285
268
|
- fix:
|
|
286
|
-
-
|
|
287
|
-
- 直接点击仪表盘中错误数字跳转到错误日志页后, 设置面板显示的还是仪表盘页面的设置
|
|
288
|
-
- 前端中为各项仪表盘请求添加 `RequestSeq`, 以避免前后发送两个请求, 但因为延迟关系, 先发送的请求的返回覆盖掉后发送请求的返回
|
|
289
|
-
- 修复前端中各项空字段需要在第一次refresh才显示的问题, 体感上会导致"加载"很慢
|
|
269
|
+
- 修复 `UnconsumedError` 在 `drain_task_queue` 中被计算两次的问题
|
|
290
270
|
- chore:
|
|
291
|
-
-
|
|
292
|
-
|
|
271
|
+
- `img/` 中添加全新的 `web_display.png` 图片
|
|
272
|
+
- 完善几个skill, 现在对主agent与子agent的prompt进行分离
|
|
293
273
|
|
|
294
274
|
更多过往日志可看:
|
|
295
275
|
|
|
296
|
-
[change_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/change_log.md
|
|
276
|
+
[change_log.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/change_log.md)
|
|
297
277
|
|
|
298
278
|
## Star 历史趋势(Star History)
|
|
299
279
|
|
|
@@ -302,7 +282,7 @@ flowchart TD
|
|
|
302
282
|

|
|
303
283
|
|
|
304
284
|
## 许可(License)
|
|
305
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
285
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/LICENSE) file for details.
|
|
306
286
|
|
|
307
287
|
## 作者(Author)
|
|
308
288
|
Author: Mr-xiaotian
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "celestialflow"
|
|
7
|
-
version = "3.2.
|
|
7
|
+
version = "3.2.5"
|
|
8
8
|
description = "A flexible GRAPH-based task orchestration framework."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -17,10 +17,7 @@ dependencies = [
|
|
|
17
17
|
"fastapi",
|
|
18
18
|
"uvicorn",
|
|
19
19
|
"requests",
|
|
20
|
-
"networkx",
|
|
21
|
-
"redis",
|
|
22
20
|
"jinja2",
|
|
23
|
-
"celestialtree>=0.1.3",
|
|
24
21
|
]
|
|
25
22
|
|
|
26
23
|
classifiers = [
|
|
@@ -72,6 +69,8 @@ dev = [
|
|
|
72
69
|
"python-dotenv>=1.2.2",
|
|
73
70
|
"ruff>=0.15.0",
|
|
74
71
|
"pyright>=1.1.409",
|
|
72
|
+
"redis",
|
|
73
|
+
"celestialtree>=0.1.3",
|
|
75
74
|
]
|
|
76
75
|
|
|
77
76
|
[tool.pyright]
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
提供任务图构建、执行调度、实时监控、Web 可视化和持久化等核心能力。
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from .funnel import BaseInlet, BaseSpout
|
|
7
8
|
from .graph import (
|
|
8
9
|
TaskChain,
|
|
9
10
|
TaskComplete,
|
|
@@ -13,19 +14,16 @@ from .graph import (
|
|
|
13
14
|
TaskLoop,
|
|
14
15
|
TaskWheel,
|
|
15
16
|
)
|
|
16
|
-
from .observability import BaseObserver,
|
|
17
|
-
from .persistence.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
from .observability import BaseObserver, TaskProgress
|
|
18
|
+
from .persistence.util_sqlite import (
|
|
19
|
+
load_records,
|
|
20
|
+
load_records_grouped_by_stage,
|
|
21
|
+
load_tasks_grouped_by_stage,
|
|
21
22
|
)
|
|
22
23
|
from .runtime.util_hash import make_hashable
|
|
23
24
|
from .runtime.util_types import TerminationSignal
|
|
24
25
|
from .stage import (
|
|
25
26
|
TaskExecutor,
|
|
26
|
-
TaskRedisAck,
|
|
27
|
-
TaskRedisSource,
|
|
28
|
-
TaskRedisTransport,
|
|
29
27
|
TaskRouter,
|
|
30
28
|
TaskSplitter,
|
|
31
29
|
TaskStage,
|
|
@@ -35,8 +33,9 @@ from .utils.util_format import format_table
|
|
|
35
33
|
from .web import TaskWebServer
|
|
36
34
|
|
|
37
35
|
__all__ = [
|
|
36
|
+
"BaseInlet",
|
|
38
37
|
"BaseObserver",
|
|
39
|
-
"
|
|
38
|
+
"BaseSpout",
|
|
40
39
|
"TaskChain",
|
|
41
40
|
"TaskComplete",
|
|
42
41
|
"TaskCross",
|
|
@@ -45,9 +44,6 @@ __all__ = [
|
|
|
45
44
|
"TaskGrid",
|
|
46
45
|
"TaskLoop",
|
|
47
46
|
"TaskProgress",
|
|
48
|
-
"TaskRedisAck",
|
|
49
|
-
"TaskRedisSource",
|
|
50
|
-
"TaskRedisTransport",
|
|
51
47
|
"TaskRouter",
|
|
52
48
|
"TaskSplitter",
|
|
53
49
|
"TaskStage",
|
|
@@ -57,8 +53,8 @@ __all__ = [
|
|
|
57
53
|
"benchmark_executor",
|
|
58
54
|
"benchmark_graph",
|
|
59
55
|
"format_table",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
56
|
+
"load_records",
|
|
57
|
+
"load_records_grouped_by_stage",
|
|
58
|
+
"load_tasks_grouped_by_stage",
|
|
63
59
|
"make_hashable",
|
|
64
60
|
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# funnel/core_inlet.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from queue import Queue
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
6
|
+
|
|
7
|
+
from ..runtime.util_errors import InitializationError
|
|
8
|
+
from .util_count import PendingCounter
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .core_spout import BaseSpout
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseInlet:
|
|
15
|
+
"""数据收集器基类,负责将记录通过队列发送到对应的监听器。"""
|
|
16
|
+
|
|
17
|
+
_queue: Queue[Any]
|
|
18
|
+
_counter: PendingCounter
|
|
19
|
+
|
|
20
|
+
def bind_spout(self, spout: BaseSpout) -> Self:
|
|
21
|
+
"""
|
|
22
|
+
将当前 inlet 绑定到给定 spout。
|
|
23
|
+
|
|
24
|
+
:param spout: 目标监听器
|
|
25
|
+
:return: 当前已绑定的 inlet 实例
|
|
26
|
+
:rtype: Self
|
|
27
|
+
"""
|
|
28
|
+
self._queue = spout.get_queue()
|
|
29
|
+
self._counter = spout.get_counter()
|
|
30
|
+
return self
|
|
31
|
+
|
|
32
|
+
def _funnel(self, record: Any) -> None:
|
|
33
|
+
"""
|
|
34
|
+
将记录放入队列。
|
|
35
|
+
|
|
36
|
+
:param record: 待发送的记录
|
|
37
|
+
:return: ``None``
|
|
38
|
+
"""
|
|
39
|
+
if not hasattr(self, '_queue') or not hasattr(self, '_counter'):
|
|
40
|
+
raise InitializationError("inlet is not bound to spout")
|
|
41
|
+
|
|
42
|
+
# 先增加待处理数量,再入队;若入队失败则立即回滚计数。
|
|
43
|
+
self._counter.increment()
|
|
44
|
+
try:
|
|
45
|
+
self._queue.put(record)
|
|
46
|
+
except Exception:
|
|
47
|
+
self._counter.decrement()
|
|
48
|
+
raise
|
|
@@ -8,31 +8,19 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
from ..runtime.util_errors import CelestialFlowError
|
|
10
10
|
from ..runtime.util_types import TERMINATION_SIGNAL, TerminationSignal
|
|
11
|
+
from .util_count import PendingCounter
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class BaseSpout:
|
|
14
15
|
"""数据监听器基类,在独立后台线程中消费队列记录。"""
|
|
15
16
|
|
|
16
17
|
def __init__(self) -> None:
|
|
17
|
-
"""
|
|
18
|
-
self.
|
|
18
|
+
"""初始化监听器及其内部队列、待处理计数器和线程引用。"""
|
|
19
|
+
self._queue: Queue[Any] = Queue()
|
|
20
|
+
self._counter = PendingCounter()
|
|
19
21
|
self._thread: Thread | None = None
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
"""在后台线程启动前调用,子类可覆写以做初始化(如打开文件、清空缓存)。"""
|
|
23
|
-
return None
|
|
24
|
-
|
|
25
|
-
def _handle_record(self, _record: Any) -> None:
|
|
26
|
-
"""
|
|
27
|
-
处理单条队列记录,子类必须覆写。
|
|
28
|
-
|
|
29
|
-
:param _record: 队列中取出的记录
|
|
30
|
-
"""
|
|
31
|
-
raise CelestialFlowError("_handle_record must be implemented by subclasses")
|
|
32
|
-
|
|
33
|
-
def _after_stop(self) -> None:
|
|
34
|
-
"""在后台线程停止后调用,子类可覆写以做清理(如关闭文件句柄)。"""
|
|
35
|
-
return None
|
|
23
|
+
# ==== 外部调用函数 ====
|
|
36
24
|
|
|
37
25
|
def start(self) -> None:
|
|
38
26
|
"""启动后台监听线程(若未运行)。"""
|
|
@@ -42,30 +30,77 @@ class BaseSpout:
|
|
|
42
30
|
self._thread.start()
|
|
43
31
|
|
|
44
32
|
def _spout(self) -> None:
|
|
45
|
-
"""
|
|
33
|
+
"""
|
|
34
|
+
后台线程主循环。
|
|
35
|
+
|
|
36
|
+
持续从队列拉取记录并调用 ``_handle_record()``,收到终止信号时退出。
|
|
37
|
+
待处理数量在记录处理完成后递减,因此统计口径包含“已出队但仍在处理”的记录。
|
|
38
|
+
"""
|
|
46
39
|
while True:
|
|
47
40
|
try:
|
|
48
|
-
record = self.
|
|
49
|
-
if isinstance(record, TerminationSignal):
|
|
50
|
-
break
|
|
51
|
-
self._handle_record(record)
|
|
41
|
+
record = self._queue.get(timeout=0.5)
|
|
52
42
|
except Empty:
|
|
53
43
|
continue
|
|
44
|
+
|
|
45
|
+
if isinstance(record, TerminationSignal):
|
|
46
|
+
break
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
self._handle_record(record)
|
|
54
50
|
except Exception:
|
|
55
|
-
#
|
|
51
|
+
# 单条记录处理失败不致死线程。
|
|
56
52
|
traceback.print_exc()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"""获取监听器的输入队列。"""
|
|
60
|
-
return self.queue
|
|
53
|
+
finally:
|
|
54
|
+
self._counter.decrement()
|
|
61
55
|
|
|
62
56
|
def stop(self) -> None:
|
|
63
57
|
"""发送终止信号并等待后台线程结束。"""
|
|
64
58
|
if self._thread is None:
|
|
65
59
|
return
|
|
66
60
|
|
|
67
|
-
self.
|
|
61
|
+
self._queue.put(TERMINATION_SIGNAL)
|
|
68
62
|
if self._thread.is_alive():
|
|
69
63
|
self._thread.join(timeout=5)
|
|
64
|
+
|
|
70
65
|
self._thread = None
|
|
71
66
|
self._after_stop()
|
|
67
|
+
|
|
68
|
+
def get_queue(self) -> Queue[Any]:
|
|
69
|
+
"""获取监听器的输入队列。"""
|
|
70
|
+
return self._queue
|
|
71
|
+
|
|
72
|
+
def get_counter(self) -> PendingCounter:
|
|
73
|
+
"""
|
|
74
|
+
获取与当前监听器绑定的待处理计数器。
|
|
75
|
+
|
|
76
|
+
:return: 待处理计数器
|
|
77
|
+
:rtype: PendingCounter
|
|
78
|
+
"""
|
|
79
|
+
return self._counter
|
|
80
|
+
|
|
81
|
+
def get_pending_count(self) -> int:
|
|
82
|
+
"""
|
|
83
|
+
读取当前仍未处理完成的记录数量。
|
|
84
|
+
|
|
85
|
+
:return: 当前待处理数量
|
|
86
|
+
:rtype: int
|
|
87
|
+
"""
|
|
88
|
+
return self._counter.get_count()
|
|
89
|
+
|
|
90
|
+
# ==== 生命周期回调 ====
|
|
91
|
+
|
|
92
|
+
def _before_start(self) -> None:
|
|
93
|
+
"""在后台线程启动前调用,子类可覆写以做初始化(如打开文件、清空缓存)。"""
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
def _handle_record(self, _record: Any) -> None:
|
|
97
|
+
"""
|
|
98
|
+
处理单条队列记录,子类必须覆写。
|
|
99
|
+
|
|
100
|
+
:param _record: 队列中取出的记录
|
|
101
|
+
"""
|
|
102
|
+
raise CelestialFlowError("_handle_record must be implemented by subclasses")
|
|
103
|
+
|
|
104
|
+
def _after_stop(self) -> None:
|
|
105
|
+
"""在后台线程停止后调用,子类可覆写以做清理(如关闭文件句柄)。"""
|
|
106
|
+
return None
|