celestialflow 3.2.1__tar.gz → 3.2.2__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.1 → celestialflow-3.2.2}/PKG-INFO +21 -47
- {celestialflow-3.2.1 → celestialflow-3.2.2}/README.md +20 -46
- {celestialflow-3.2.1 → celestialflow-3.2.2}/pyproject.toml +1 -1
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/graph/core_graph.py +42 -26
- celestialflow-3.2.2/src/celestialflow/graph/util_serialize.py +153 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/observability/core_report.py +6 -20
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/core_fail.py +3 -3
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/core_dispatch.py +10 -17
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/core_envelope.py +10 -1
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/util_estimators.py +3 -3
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/stage/core_executor.py +18 -2
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/stage/core_stage.py +19 -3
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/stage/core_stages.py +11 -7
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/config.json +3 -1
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/core_server.py +83 -11
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/routes/pull_routes.py +16 -25
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/routes/push_routes.py +167 -186
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/base.css +54 -5
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/dashboard_history.js +11 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/dashboard_structure.js +55 -34
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/dashboard_summary.js +2 -23
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/errors.js +22 -3
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/i18n.js +21 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/injection.js +1 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/layout_editor.js +6 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/main.js +70 -14
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/web_config.js +9 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/dashboard_history.ts +12 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/dashboard_statuses.ts +1 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/dashboard_structure.ts +71 -41
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/dashboard_summary.ts +2 -25
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/errors.ts +37 -3
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/i18n.ts +21 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/injection.ts +1 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/layout_editor.ts +6 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/main.ts +79 -17
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/web_config.ts +12 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/templates/index.html +102 -29
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/util_error.py +23 -8
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/util_models.py +3 -7
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow.egg-info/PKG-INFO +21 -47
- celestialflow-3.2.1/src/celestialflow/graph/util_serialize.py +0 -151
- {celestialflow-3.2.1 → celestialflow-3.2.2}/setup.cfg +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/funnel/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/funnel/core_inlet.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/funnel/core_spout.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/graph/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/graph/core_structure.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/graph/util_analysis.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/observability/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/observability/core_observer.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/observability/core_progress.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/core_log.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/core_success.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/util_constant.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/persistence/util_jsonl.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/core_metrics.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/core_queue.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/util_errors.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/util_hash.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/runtime/util_types.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/stage/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/utils/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/utils/util_benchmark.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/utils/util_clone.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/utils/util_collections.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/utils/util_format.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/routes/__init__.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/_colors.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard_analysis.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard_history.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard_statuses.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard_structure.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/dashboard_summary.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/errors.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/css/injection.css +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/favicon.ico +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/dashboard_analysis.js +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/dashboard_statuses.js +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/js/utils.js +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/dashboard_analysis.ts +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/globals.d.ts +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/static/ts/utils.ts +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/util_cal.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow/web/util_config.py +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow.egg-info/SOURCES.txt +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow.egg-info/dependency_links.txt +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow.egg-info/entry_points.txt +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/src/celestialflow.egg-info/requires.txt +0 -0
- {celestialflow-3.2.1 → celestialflow-3.2.2}/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.2
|
|
4
4
|
Summary: A flexible GRAPH-based task orchestration framework.
|
|
5
5
|
Author-email: Mr-xiaotian <mingxiaomingtian@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -212,7 +212,7 @@ flowchart TD
|
|
|
212
212
|
|
|
213
213
|
以下三篇可以作为补充阅读:
|
|
214
214
|
|
|
215
|
-
- [runtime/
|
|
215
|
+
- [runtime/util_hash.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_hash.md)
|
|
216
216
|
- [runtime/util_types.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_types.md)
|
|
217
217
|
- [runtime/util_errors.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_errors.md)
|
|
218
218
|
- [persistence/core_fail.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_fail.md)
|
|
@@ -228,15 +228,15 @@ flowchart TD
|
|
|
228
228
|
|
|
229
229
|
你可以继续运行更多的演示代码,这里记录了各个演示文件与其中的演示函数说明:
|
|
230
230
|
|
|
231
|
-
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
231
|
+
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/demo)
|
|
232
232
|
|
|
233
233
|
如果你想运行测试代码, 可以先查看如下文档内容:
|
|
234
234
|
|
|
235
|
-
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
235
|
+
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/tests)
|
|
236
236
|
|
|
237
237
|
如果你想查看bench内容, 这里的数据成为框架中部分设计的决策依据:
|
|
238
238
|
|
|
239
|
-
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
239
|
+
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/bench)
|
|
240
240
|
|
|
241
241
|
## 环境要求(Requirements)
|
|
242
242
|
|
|
@@ -260,57 +260,31 @@ flowchart TD
|
|
|
260
260
|
<p align="center">
|
|
261
261
|
<img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
|
|
262
262
|
<br/>
|
|
263
|
-
<em>celestial-flow 3.2.
|
|
263
|
+
<em>celestial-flow 3.2.2</em>
|
|
264
264
|
</p>
|
|
265
265
|
|
|
266
266
|
(该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
|
|
267
267
|
|
|
268
268
|
## 版本日志(Version Log)
|
|
269
|
-
- 3.2.
|
|
269
|
+
- 3.2.2
|
|
270
270
|
- feat:
|
|
271
|
-
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
- 可以配置结构图中是否显示增量,不过现在样式上有点丑
|
|
275
|
-
- 以及最重要的,可以直接编辑仪表盘页的卡片布局
|
|
276
|
-
- 另外,所有设置保存成功后会有提示
|
|
277
|
-
- 折线图中可以选择数据类型
|
|
278
|
-
- 现在包括"数据累计"、"等待队列"和"数据变化率"
|
|
279
|
-
- 对 structure 的一些调整
|
|
280
|
-
- 所有 structure 的参数中添加 `stage_mode`,用于统一控制节点模式
|
|
281
|
-
- 对 struct 中节点不再重新命名
|
|
282
|
-
- 在部分 Spout 中增加缓冲机制
|
|
271
|
+
- `core_server` 中添加数据锁, 避免并发访问导致的错误状态
|
|
272
|
+
- 优化前端设置面板的显示, 现在只显示全局设置与当前页相关设置
|
|
273
|
+
- 在设置面板中添加全局设置中的 "是否自动更新" 选项与错误日志页面中的 "排序方式" 两项
|
|
283
274
|
- refactor:
|
|
284
|
-
-
|
|
285
|
-
|
|
286
|
-
- **[Important]** 将 executor 中 `task_queue` 与 `result_queue` 的定义提前到 `__init__` 中
|
|
287
|
-
- 对于 executor 来说区别不大,但对于 stage 而言这是更理想且优雅的形式,只是由于原先 `stage_mode="process"` 时不允许执行函数内带有 `MPQueue`,所以才使用 graph 中统一定义,然后通过 process 的 args 注入的形式
|
|
288
|
-
- **[Important]** 重构 `core_server`,将其分解出 `routes/` 与 `util_models`,实现结构优化
|
|
289
|
-
- 进一步地,将 `log_queue` 和 `fail_queue` 的注入也提前到 `graph.set_stages` 中,实现 `stage.start_stage` 完全无输入参数
|
|
290
|
-
- 同时在 executor 中添加 `put_task` 与 `put_signal`,并在 graph 中进行复用
|
|
291
|
-
- 之前不能这样做是因为 stage 中此时还没有定义 queue
|
|
292
|
-
- 移除 `core_graph` 中的 `StageRuntime`
|
|
293
|
-
- 将类型标注中的部分 `Any` 改为更明确的类型
|
|
294
|
-
- 删除 HTML 中的仪表盘部分的 card,现在交给 `web-config` 来定义
|
|
295
|
-
- 删除部分没必要的前后端通信,优化通信负载
|
|
296
|
-
- 移除后端传递的节点历史信息,由前端进行维护
|
|
297
|
-
- 移除总体统计中除"总剩余时间"的后端数据,由前端进行计算
|
|
298
|
-
- 优化错误存储的 JSONL 数据结构,现在保存更细致的错误信息
|
|
299
|
-
- 调整 pyright 规则,并实现 pyright 0 error / 0 warning
|
|
300
|
-
- 给 `web/` 下几乎所有 `.ts` 与 `.css` 文件重命名,并整理文件内容边界
|
|
301
|
-
- `util_error` 中添加更多错误类型,保证项目中所有主动 raise 的错误都在当前的错误体系下
|
|
302
|
-
- 删除前端代码中所有的 `onclick`,改用 `data-*` 属性
|
|
303
|
-
- 清简 `config.json` 中的部分字段
|
|
304
|
-
- 删除部分不必要的代码
|
|
275
|
+
- 删除前后端通讯中的 `summary` , 节点的总体预期结束时间由各个节点的 `status` 分别传递, 并由前端计算整体的预期结束时间
|
|
276
|
+
- 修改 `structure_graph`(原 `structure_json`) 字段的内容, 现在更为简洁, 避免信息冗余, 同时方便后续拓展
|
|
305
277
|
- fix:
|
|
306
|
-
-
|
|
278
|
+
- 修复指标折线图中指标选择失效的问题
|
|
279
|
+
- 修改 `report.stop` 中_refresh_all的执行顺序, 避免与thread中的刷新冲突
|
|
280
|
+
- 在 `graph._finalize_nodes` 中添加对thread未终止的防御性检查
|
|
281
|
+
- 修复 `stage` 中 `start_time` 在未定义前被 `report` 调用的问题
|
|
282
|
+
- 修复 `TaskRedisTransport._transport` 中使用 `id()` 来计算task_id导致的问题
|
|
283
|
+
- 修复部分任务无法被hash导致的panic问题
|
|
307
284
|
- chore:
|
|
308
|
-
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
- 添加 `.github/workflows`,实现 CI/CD
|
|
312
|
-
- 更新支持的 Python 版本为 3.11,以与部分库要求相符
|
|
313
|
-
- 添加两个 skill,分别用于更新文档与审查项目
|
|
285
|
+
- 删除所有的 `type: ignore`
|
|
286
|
+
- 好看不少
|
|
287
|
+
- 在 `start_*` 函数的doc-string中标注该函数为一次性调用函数
|
|
314
288
|
|
|
315
289
|
更多过往日志可看:
|
|
316
290
|
|
|
@@ -187,7 +187,7 @@ flowchart TD
|
|
|
187
187
|
|
|
188
188
|
以下三篇可以作为补充阅读:
|
|
189
189
|
|
|
190
|
-
- [runtime/
|
|
190
|
+
- [runtime/util_hash.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_hash.md)
|
|
191
191
|
- [runtime/util_types.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_types.md)
|
|
192
192
|
- [runtime/util_errors.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/util_errors.md)
|
|
193
193
|
- [persistence/core_fail.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/persistence/core_fail.md)
|
|
@@ -203,15 +203,15 @@ flowchart TD
|
|
|
203
203
|
|
|
204
204
|
你可以继续运行更多的演示代码,这里记录了各个演示文件与其中的演示函数说明:
|
|
205
205
|
|
|
206
|
-
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
206
|
+
[🎮demo/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/demo)
|
|
207
207
|
|
|
208
208
|
如果你想运行测试代码, 可以先查看如下文档内容:
|
|
209
209
|
|
|
210
|
-
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
210
|
+
[🧪tests/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/tests)
|
|
211
211
|
|
|
212
212
|
如果你想查看bench内容, 这里的数据成为框架中部分设计的决策依据:
|
|
213
213
|
|
|
214
|
-
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/
|
|
214
|
+
[⚡bench/](https://github.com/Mr-xiaotian/CelestialFlow/tree/main/docs/zh-CN/bench)
|
|
215
215
|
|
|
216
216
|
## 环境要求(Requirements)
|
|
217
217
|
|
|
@@ -235,57 +235,31 @@ flowchart TD
|
|
|
235
235
|
<p align="center">
|
|
236
236
|
<img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
|
|
237
237
|
<br/>
|
|
238
|
-
<em>celestial-flow 3.2.
|
|
238
|
+
<em>celestial-flow 3.2.2</em>
|
|
239
239
|
</p>
|
|
240
240
|
|
|
241
241
|
(该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
|
|
242
242
|
|
|
243
243
|
## 版本日志(Version Log)
|
|
244
|
-
- 3.2.
|
|
244
|
+
- 3.2.2
|
|
245
245
|
- feat:
|
|
246
|
-
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
- 可以配置结构图中是否显示增量,不过现在样式上有点丑
|
|
250
|
-
- 以及最重要的,可以直接编辑仪表盘页的卡片布局
|
|
251
|
-
- 另外,所有设置保存成功后会有提示
|
|
252
|
-
- 折线图中可以选择数据类型
|
|
253
|
-
- 现在包括"数据累计"、"等待队列"和"数据变化率"
|
|
254
|
-
- 对 structure 的一些调整
|
|
255
|
-
- 所有 structure 的参数中添加 `stage_mode`,用于统一控制节点模式
|
|
256
|
-
- 对 struct 中节点不再重新命名
|
|
257
|
-
- 在部分 Spout 中增加缓冲机制
|
|
246
|
+
- `core_server` 中添加数据锁, 避免并发访问导致的错误状态
|
|
247
|
+
- 优化前端设置面板的显示, 现在只显示全局设置与当前页相关设置
|
|
248
|
+
- 在设置面板中添加全局设置中的 "是否自动更新" 选项与错误日志页面中的 "排序方式" 两项
|
|
258
249
|
- refactor:
|
|
259
|
-
-
|
|
260
|
-
|
|
261
|
-
- **[Important]** 将 executor 中 `task_queue` 与 `result_queue` 的定义提前到 `__init__` 中
|
|
262
|
-
- 对于 executor 来说区别不大,但对于 stage 而言这是更理想且优雅的形式,只是由于原先 `stage_mode="process"` 时不允许执行函数内带有 `MPQueue`,所以才使用 graph 中统一定义,然后通过 process 的 args 注入的形式
|
|
263
|
-
- **[Important]** 重构 `core_server`,将其分解出 `routes/` 与 `util_models`,实现结构优化
|
|
264
|
-
- 进一步地,将 `log_queue` 和 `fail_queue` 的注入也提前到 `graph.set_stages` 中,实现 `stage.start_stage` 完全无输入参数
|
|
265
|
-
- 同时在 executor 中添加 `put_task` 与 `put_signal`,并在 graph 中进行复用
|
|
266
|
-
- 之前不能这样做是因为 stage 中此时还没有定义 queue
|
|
267
|
-
- 移除 `core_graph` 中的 `StageRuntime`
|
|
268
|
-
- 将类型标注中的部分 `Any` 改为更明确的类型
|
|
269
|
-
- 删除 HTML 中的仪表盘部分的 card,现在交给 `web-config` 来定义
|
|
270
|
-
- 删除部分没必要的前后端通信,优化通信负载
|
|
271
|
-
- 移除后端传递的节点历史信息,由前端进行维护
|
|
272
|
-
- 移除总体统计中除"总剩余时间"的后端数据,由前端进行计算
|
|
273
|
-
- 优化错误存储的 JSONL 数据结构,现在保存更细致的错误信息
|
|
274
|
-
- 调整 pyright 规则,并实现 pyright 0 error / 0 warning
|
|
275
|
-
- 给 `web/` 下几乎所有 `.ts` 与 `.css` 文件重命名,并整理文件内容边界
|
|
276
|
-
- `util_error` 中添加更多错误类型,保证项目中所有主动 raise 的错误都在当前的错误体系下
|
|
277
|
-
- 删除前端代码中所有的 `onclick`,改用 `data-*` 属性
|
|
278
|
-
- 清简 `config.json` 中的部分字段
|
|
279
|
-
- 删除部分不必要的代码
|
|
250
|
+
- 删除前后端通讯中的 `summary` , 节点的总体预期结束时间由各个节点的 `status` 分别传递, 并由前端计算整体的预期结束时间
|
|
251
|
+
- 修改 `structure_graph`(原 `structure_json`) 字段的内容, 现在更为简洁, 避免信息冗余, 同时方便后续拓展
|
|
280
252
|
- fix:
|
|
281
|
-
-
|
|
253
|
+
- 修复指标折线图中指标选择失效的问题
|
|
254
|
+
- 修改 `report.stop` 中_refresh_all的执行顺序, 避免与thread中的刷新冲突
|
|
255
|
+
- 在 `graph._finalize_nodes` 中添加对thread未终止的防御性检查
|
|
256
|
+
- 修复 `stage` 中 `start_time` 在未定义前被 `report` 调用的问题
|
|
257
|
+
- 修复 `TaskRedisTransport._transport` 中使用 `id()` 来计算task_id导致的问题
|
|
258
|
+
- 修复部分任务无法被hash导致的panic问题
|
|
282
259
|
- chore:
|
|
283
|
-
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
- 添加 `.github/workflows`,实现 CI/CD
|
|
287
|
-
- 更新支持的 Python 版本为 3.11,以与部分库要求相符
|
|
288
|
-
- 添加两个 skill,分别用于更新文档与审查项目
|
|
260
|
+
- 删除所有的 `type: ignore`
|
|
261
|
+
- 好看不少
|
|
262
|
+
- 在 `start_*` 函数的doc-string中标注该函数为一次性调用函数
|
|
289
263
|
|
|
290
264
|
更多过往日志可看:
|
|
291
265
|
|
|
@@ -23,6 +23,7 @@ from ..runtime import TaskInQueue, TaskOutQueue
|
|
|
23
23
|
from ..runtime.util_errors import (
|
|
24
24
|
CelestialTreeConnectionError,
|
|
25
25
|
DuplicateNodeError,
|
|
26
|
+
RuntimeStateError,
|
|
26
27
|
ScheduleModeError,
|
|
27
28
|
UnconsumedError,
|
|
28
29
|
)
|
|
@@ -48,7 +49,14 @@ from .util_serialize import build_structure_graph, format_structure_list_from_gr
|
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
class TaskGraph:
|
|
51
|
-
"""任务图核心类,负责构建、连接和调度一组 TaskStage 节点。
|
|
52
|
+
"""任务图核心类,负责构建、连接和调度一组 TaskStage 节点。
|
|
53
|
+
|
|
54
|
+
注意:
|
|
55
|
+
- TaskGraph 是一次性对象,设计上只应启动一次。
|
|
56
|
+
- start_graph() 执行后,内部会建立并持有运行期资源、队列绑定和线程状态,
|
|
57
|
+
不保证可被安全重置或重复启动。
|
|
58
|
+
- 如需再次运行相同流程,请重新创建 TaskGraph 实例及其关联的 TaskStage。
|
|
59
|
+
"""
|
|
52
60
|
|
|
53
61
|
# ==== 初始化 ====
|
|
54
62
|
|
|
@@ -64,6 +72,11 @@ class TaskGraph:
|
|
|
64
72
|
分层等多种形式的任务执行流程。通过分析图结构和调度布局策略,实现灵活的
|
|
65
73
|
DAG 任务调度控制。
|
|
66
74
|
|
|
75
|
+
生命周期说明:
|
|
76
|
+
- 当前 TaskGraph 实例为一次性对象。
|
|
77
|
+
- 完成一次 start_graph() 后,不应复用同一实例再次启动。
|
|
78
|
+
- 如需重复执行,请重新构建新的 TaskGraph 与节点对象。
|
|
79
|
+
|
|
67
80
|
:param schedule_mode: str, optional, default = 'eager'
|
|
68
81
|
控制任务图的调度布局模式,支持以下两种策略:
|
|
69
82
|
- 'eager':
|
|
@@ -111,8 +124,6 @@ class TaskGraph:
|
|
|
111
124
|
self.status_dict: dict[str, dict[str, Any]] = defaultdict(dict)
|
|
112
125
|
# 用于保存最近一次状态快照对应的统一时间戳
|
|
113
126
|
self.status_timestamp: float = 0.0
|
|
114
|
-
# 用于保存任务图的摘要信息
|
|
115
|
-
self.graph_summary: dict[str, int | float] = {}
|
|
116
127
|
# 用于保存每个节点的输入任务ID集合
|
|
117
128
|
self.input_ids: dict[str, set[int]] = defaultdict(set)
|
|
118
129
|
# 用于保存源节点列表(由 _build_analysis 自动计算)
|
|
@@ -294,8 +305,8 @@ class TaskGraph:
|
|
|
294
305
|
source_names = find_source_nodes(self.networkx_graph)
|
|
295
306
|
self.source_stages = [self.stage_dict[name] for name in source_names]
|
|
296
307
|
|
|
297
|
-
self.
|
|
298
|
-
self.
|
|
308
|
+
self.structure_graph = build_structure_graph(
|
|
309
|
+
self.stage_dict, self.out_edges, self.source_stages
|
|
299
310
|
)
|
|
300
311
|
|
|
301
312
|
self.is_dag = is_directed_acyclic_graph(self.networkx_graph)
|
|
@@ -343,6 +354,9 @@ class TaskGraph:
|
|
|
343
354
|
|
|
344
355
|
:param init_tasks_dict: 任务列表
|
|
345
356
|
:param put_termination_signal: 是否注入终止信号,默认 True
|
|
357
|
+
:note:
|
|
358
|
+
TaskGraph 为一次性对象;当前实例启动并运行完成后,不保证可安全再次调用
|
|
359
|
+
start_graph()。如需重复执行,请创建新的 TaskGraph 实例。
|
|
346
360
|
"""
|
|
347
361
|
self._build_resources()
|
|
348
362
|
self._build_analysis()
|
|
@@ -366,7 +380,7 @@ class TaskGraph:
|
|
|
366
380
|
self.fail_spout.start()
|
|
367
381
|
self.log_spout.start()
|
|
368
382
|
self.log_inlet.start_graph(self.get_structure_list())
|
|
369
|
-
self.fail_inlet.start_graph(self.
|
|
383
|
+
self.fail_inlet.start_graph(self.get_structure_graph())
|
|
370
384
|
self.reporter.start()
|
|
371
385
|
|
|
372
386
|
self.put_stage_queue(init_tasks_dict, put_termination_signal)
|
|
@@ -442,8 +456,18 @@ class TaskGraph:
|
|
|
442
456
|
确保所有线程安全结束,更新节点状态,并导出每个节点队列剩余任务。
|
|
443
457
|
"""
|
|
444
458
|
# 确保所有线程安全结束(线程不可 terminate,仅做 cooperative join)
|
|
459
|
+
alive_thread_names: list[str] = []
|
|
445
460
|
for t in self.threads:
|
|
446
461
|
t.join(timeout=10)
|
|
462
|
+
if t.is_alive():
|
|
463
|
+
alive_thread_names.append(t.name)
|
|
464
|
+
|
|
465
|
+
if alive_thread_names:
|
|
466
|
+
stage_names = ", ".join(sorted(alive_thread_names))
|
|
467
|
+
raise RuntimeStateError(
|
|
468
|
+
"TaskGraph shutdown incomplete; alive stage threads remain after finalize: "
|
|
469
|
+
f"{stage_names}"
|
|
470
|
+
)
|
|
447
471
|
|
|
448
472
|
# 更新所有节点状态为"已停止"
|
|
449
473
|
for stage in self.stage_dict.values():
|
|
@@ -534,7 +558,7 @@ class TaskGraph:
|
|
|
534
558
|
running_pending_map: dict[str, int],
|
|
535
559
|
running_elapsed_map: dict[str, float],
|
|
536
560
|
running_remaining_map: dict[str, float],
|
|
537
|
-
) -> float:
|
|
561
|
+
) -> dict[str, float]:
|
|
538
562
|
"""
|
|
539
563
|
根据 DAG/非 DAG 策略计算全局预计剩余时间
|
|
540
564
|
|
|
@@ -545,15 +569,15 @@ class TaskGraph:
|
|
|
545
569
|
:return: 全局预计剩余时间(秒)
|
|
546
570
|
"""
|
|
547
571
|
if not self.is_dag:
|
|
548
|
-
return
|
|
572
|
+
return running_remaining_map
|
|
549
573
|
|
|
550
|
-
|
|
574
|
+
total_remaining_map = calc_global_remain_equal_pred(
|
|
551
575
|
self.networkx_graph,
|
|
552
576
|
running_processed_map,
|
|
553
577
|
running_pending_map,
|
|
554
578
|
running_elapsed_map,
|
|
555
579
|
)
|
|
556
|
-
return
|
|
580
|
+
return total_remaining_map
|
|
557
581
|
|
|
558
582
|
def collect_runtime_snapshot(self) -> None:
|
|
559
583
|
"""
|
|
@@ -563,8 +587,6 @@ class TaskGraph:
|
|
|
563
587
|
now = time.time()
|
|
564
588
|
interval = self.reporter.interval
|
|
565
589
|
|
|
566
|
-
totals = {"total_remain": 0.0}
|
|
567
|
-
|
|
568
590
|
# 为全局预计 remaining 收集
|
|
569
591
|
running_elapsed_map: dict[str, float] = {}
|
|
570
592
|
running_processed_map: dict[str, int] = {}
|
|
@@ -589,16 +611,18 @@ class TaskGraph:
|
|
|
589
611
|
running_elapsed_map[stage_name] = elapsed
|
|
590
612
|
running_remaining_map[stage_name] = remaining
|
|
591
613
|
|
|
592
|
-
|
|
614
|
+
total_remaining_map = self._calc_graph_remain(
|
|
593
615
|
running_processed_map,
|
|
594
616
|
running_pending_map,
|
|
595
617
|
running_elapsed_map,
|
|
596
618
|
running_remaining_map,
|
|
597
619
|
)
|
|
598
620
|
|
|
621
|
+
for stage_name, stage_status in status_dict.items():
|
|
622
|
+
stage_status["total_remaining_time"] = total_remaining_map[stage_name]
|
|
623
|
+
|
|
599
624
|
self.status_dict = status_dict
|
|
600
625
|
self.status_timestamp = now
|
|
601
|
-
self.graph_summary = dict(totals)
|
|
602
626
|
|
|
603
627
|
# ==== 查询接口 ====
|
|
604
628
|
|
|
@@ -641,14 +665,6 @@ class TaskGraph:
|
|
|
641
665
|
"status": self.status_dict,
|
|
642
666
|
}
|
|
643
667
|
|
|
644
|
-
def get_graph_summary(self) -> dict[str, int | float]:
|
|
645
|
-
"""
|
|
646
|
-
获取任务链的摘要信息字典
|
|
647
|
-
|
|
648
|
-
:return: 当前仅包含 total_remain 的字典
|
|
649
|
-
"""
|
|
650
|
-
return self.graph_summary
|
|
651
|
-
|
|
652
668
|
def get_graph_analysis(self) -> dict[str, Any]:
|
|
653
669
|
"""
|
|
654
670
|
获取任务图的分析信息
|
|
@@ -662,13 +678,13 @@ class TaskGraph:
|
|
|
662
678
|
"layersDict": self.layers_dict,
|
|
663
679
|
}
|
|
664
680
|
|
|
665
|
-
def
|
|
681
|
+
def get_structure_graph(self) -> dict[str, Any]:
|
|
666
682
|
"""
|
|
667
683
|
获取任务图的 JSON 结构
|
|
668
684
|
|
|
669
|
-
:return: JSON
|
|
685
|
+
:return: JSON 格式的任务图结构字典
|
|
670
686
|
"""
|
|
671
|
-
return self.
|
|
687
|
+
return self.structure_graph
|
|
672
688
|
|
|
673
689
|
def get_structure_list(self) -> list[str]:
|
|
674
690
|
"""
|
|
@@ -676,7 +692,7 @@ class TaskGraph:
|
|
|
676
692
|
|
|
677
693
|
:return: 带边框的格式化字符串列表
|
|
678
694
|
"""
|
|
679
|
-
return format_structure_list_from_graph(self.
|
|
695
|
+
return format_structure_list_from_graph(self.structure_graph)
|
|
680
696
|
|
|
681
697
|
def get_networkx_graph(self) -> DiGraph[Any]:
|
|
682
698
|
"""
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# graph/util_serialize.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from ..stage import TaskStage
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ======== 处理图结构 ========
|
|
11
|
+
def build_structure_graph(
|
|
12
|
+
stage_dict: dict[str, TaskStage],
|
|
13
|
+
out_edges: dict[str, list[str]],
|
|
14
|
+
source_stages: list[TaskStage],
|
|
15
|
+
) -> dict[str, Any]:
|
|
16
|
+
"""
|
|
17
|
+
从源节点、邻接表和节点字典构建标准化图结构。
|
|
18
|
+
|
|
19
|
+
返回的结构采用 ``nodes + edges + source_nodes`` 形式:
|
|
20
|
+
- ``nodes``: 以节点名为 key 的节点元信息字典
|
|
21
|
+
- ``edges``: 邻接表 {stage_name: [next_stage_name, ...]}
|
|
22
|
+
- ``source_nodes``: 图入口节点名称列表
|
|
23
|
+
|
|
24
|
+
:param stage_dict: {stage_name: TaskStage}
|
|
25
|
+
:param out_edges: 邻接表 {stage_name: [next_stage_name, ...]}
|
|
26
|
+
:param source_stages: 源节点列表
|
|
27
|
+
:return: 标准化图结构字典
|
|
28
|
+
"""
|
|
29
|
+
nodes: dict[str, dict[str, Any]] = {}
|
|
30
|
+
edges: dict[str, list[str]] = {}
|
|
31
|
+
|
|
32
|
+
for stage_name, stage in stage_dict.items():
|
|
33
|
+
node_summary = dict(stage.get_summary())
|
|
34
|
+
node_summary.pop("name", None)
|
|
35
|
+
nodes[stage_name] = node_summary
|
|
36
|
+
edges[stage_name] = list(out_edges.get(stage_name, []))
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
"nodes": nodes,
|
|
40
|
+
"edges": edges,
|
|
41
|
+
"source_nodes": [stage.get_name() for stage in source_stages],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def format_structure_list_from_graph(
|
|
46
|
+
structure: dict[str, Any] | None = None,
|
|
47
|
+
) -> list[str]:
|
|
48
|
+
"""
|
|
49
|
+
从标准化图结构生成格式化任务结构文本列表(带边框)。
|
|
50
|
+
|
|
51
|
+
:param structure: ``nodes + edges + source_nodes`` 形式的图结构
|
|
52
|
+
:return: 带边框的格式化字符串列表
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
nodes: dict[str, dict[str, Any]] = dict((structure or {}).get("nodes", {}) or {})
|
|
56
|
+
edges: dict[str, list[str]] = dict((structure or {}).get("edges", {}) or {})
|
|
57
|
+
source_nodes: list[str] = list((structure or {}).get("source_nodes", []) or [])
|
|
58
|
+
|
|
59
|
+
if not nodes:
|
|
60
|
+
return ["+ No stages defined +"]
|
|
61
|
+
|
|
62
|
+
if not source_nodes:
|
|
63
|
+
child_names = {child for child_list in edges.values() for child in child_list}
|
|
64
|
+
source_nodes = [name for name in nodes if name not in child_names]
|
|
65
|
+
if not source_nodes:
|
|
66
|
+
source_nodes = [next(iter(nodes))]
|
|
67
|
+
|
|
68
|
+
expanded_nodes: set[str] = set()
|
|
69
|
+
|
|
70
|
+
def node_label(node_name: str, *, is_ref: bool = False) -> str:
|
|
71
|
+
"""
|
|
72
|
+
生成节点的显示标签字符串。
|
|
73
|
+
|
|
74
|
+
:param node_name: 节点名称
|
|
75
|
+
:param is_ref: 是否按引用节点展示
|
|
76
|
+
:return: 格式化的标签字符串
|
|
77
|
+
"""
|
|
78
|
+
node = nodes.get(node_name, {})
|
|
79
|
+
visited_note = " [Ref]" if is_ref else ""
|
|
80
|
+
F = node.get("func_name", "?") # F
|
|
81
|
+
S = node.get("stage_mode", "?") # S
|
|
82
|
+
E = node.get("execution_mode", "?") # E
|
|
83
|
+
W = node.get("max_workers", "?") # W
|
|
84
|
+
|
|
85
|
+
return f"{node_name}::{F} (S:{S}, E:{E}, W:{W}){visited_note}"
|
|
86
|
+
|
|
87
|
+
# 只渲染"子节点"(有父节点)——保证一定画连接符
|
|
88
|
+
def build_child_lines(
|
|
89
|
+
node_name: str, prefix: str, is_last: bool
|
|
90
|
+
) -> list[str]:
|
|
91
|
+
"""
|
|
92
|
+
递归构建子节点的树形显示行。
|
|
93
|
+
|
|
94
|
+
:param node_name: 子节点名称
|
|
95
|
+
:param prefix: 当前行的缩进前缀
|
|
96
|
+
:param is_last: 是否为同级最后一个节点
|
|
97
|
+
:return: 格式化的行列表
|
|
98
|
+
"""
|
|
99
|
+
connector = "╘-->" if is_last else "╞-->"
|
|
100
|
+
is_ref = node_name in expanded_nodes
|
|
101
|
+
lines = [f"{prefix}{connector}{node_label(node_name, is_ref=is_ref)}"]
|
|
102
|
+
if is_ref:
|
|
103
|
+
return lines
|
|
104
|
+
|
|
105
|
+
expanded_nodes.add(node_name)
|
|
106
|
+
|
|
107
|
+
# 子节点的 prefix 取决于当前节点是不是 last:last -> 空白,否则竖线延续
|
|
108
|
+
child_prefix = prefix + (" " if is_last else "│ ")
|
|
109
|
+
next_stages = edges.get(node_name, []) or []
|
|
110
|
+
for i, child_name in enumerate(next_stages):
|
|
111
|
+
lines.extend(
|
|
112
|
+
build_child_lines(child_name, child_prefix, i == len(next_stages) - 1)
|
|
113
|
+
)
|
|
114
|
+
return lines
|
|
115
|
+
|
|
116
|
+
# 专门处理 root:不画连接符,不产生祖先竖线
|
|
117
|
+
def build_root_lines(root_name: str) -> list[str]:
|
|
118
|
+
"""
|
|
119
|
+
构建根节点及其子树的树形显示行。
|
|
120
|
+
|
|
121
|
+
:param root_name: 根节点名称
|
|
122
|
+
:return: 格式化的行列表
|
|
123
|
+
"""
|
|
124
|
+
is_ref = root_name in expanded_nodes
|
|
125
|
+
lines = [node_label(root_name, is_ref=is_ref)]
|
|
126
|
+
if is_ref:
|
|
127
|
+
return lines
|
|
128
|
+
|
|
129
|
+
expanded_nodes.add(root_name)
|
|
130
|
+
next_stages = edges.get(root_name, []) or []
|
|
131
|
+
for i, child_name in enumerate(next_stages):
|
|
132
|
+
lines.extend(build_child_lines(child_name, "", i == len(next_stages) - 1))
|
|
133
|
+
return lines
|
|
134
|
+
|
|
135
|
+
all_lines: list[str] = []
|
|
136
|
+
rendered_roots: list[str] = []
|
|
137
|
+
for root_name in source_nodes:
|
|
138
|
+
if all_lines:
|
|
139
|
+
all_lines.append("") # 根之间留空行
|
|
140
|
+
all_lines.extend(build_root_lines(root_name))
|
|
141
|
+
rendered_roots.append(root_name)
|
|
142
|
+
|
|
143
|
+
for node_name in nodes:
|
|
144
|
+
if node_name in rendered_roots or node_name in expanded_nodes:
|
|
145
|
+
continue
|
|
146
|
+
if all_lines:
|
|
147
|
+
all_lines.append("")
|
|
148
|
+
all_lines.extend(build_root_lines(node_name))
|
|
149
|
+
|
|
150
|
+
max_length = max(len(line) for line in all_lines)
|
|
151
|
+
content_lines = [f"| {line.ljust(max_length)} |" for line in all_lines]
|
|
152
|
+
border = "+" + "-" * (max_length + 2) + "+"
|
|
153
|
+
return [border, *content_lines, border]
|
|
@@ -60,11 +60,11 @@ class TaskReporter:
|
|
|
60
60
|
|
|
61
61
|
def stop(self) -> None:
|
|
62
62
|
"""停止上报器线程"""
|
|
63
|
-
self._refresh_all() # 最后一次
|
|
64
63
|
self._stop_flag.set()
|
|
65
64
|
if self._thread is not None:
|
|
66
65
|
self._thread.join(timeout=2)
|
|
67
66
|
self._thread = None
|
|
67
|
+
self._refresh_all() # 最后一次
|
|
68
68
|
self._session.close()
|
|
69
69
|
self.log_inlet.stop_reporter()
|
|
70
70
|
|
|
@@ -100,7 +100,6 @@ class TaskReporter:
|
|
|
100
100
|
self._push_status()
|
|
101
101
|
self._push_structure()
|
|
102
102
|
self._push_analysis()
|
|
103
|
-
self._push_summary()
|
|
104
103
|
|
|
105
104
|
# ==== 拉取 ====
|
|
106
105
|
def _pull_interval(self) -> None:
|
|
@@ -139,7 +138,7 @@ class TaskReporter:
|
|
|
139
138
|
for task in task_datas
|
|
140
139
|
]
|
|
141
140
|
try:
|
|
142
|
-
self.task_graph.put_stage_queue(
|
|
141
|
+
self.task_graph.put_stage_queue(
|
|
143
142
|
{target_stage: task_datas}, put_termination_signal=False
|
|
144
143
|
)
|
|
145
144
|
self.log_inlet.inject_tasks_success(target_stage, task_datas)
|
|
@@ -231,7 +230,7 @@ class TaskReporter:
|
|
|
231
230
|
def _push_status(self) -> None:
|
|
232
231
|
"""推送状态信息"""
|
|
233
232
|
try:
|
|
234
|
-
payload: dict[str, Any] = self.task_graph.get_status_snapshot()
|
|
233
|
+
payload: dict[str, Any] = self.task_graph.get_status_snapshot()
|
|
235
234
|
_ = self._session.post(
|
|
236
235
|
f"{self.base_url}/api/push_status",
|
|
237
236
|
json=payload,
|
|
@@ -243,8 +242,8 @@ class TaskReporter:
|
|
|
243
242
|
def _push_structure(self) -> None:
|
|
244
243
|
"""推送结构信息"""
|
|
245
244
|
try:
|
|
246
|
-
structure:
|
|
247
|
-
payload: dict[str, Any] = {"
|
|
245
|
+
structure: dict[str, Any] = self.task_graph.get_structure_graph()
|
|
246
|
+
payload: dict[str, Any] = {"structure": structure}
|
|
248
247
|
_ = self._session.post(
|
|
249
248
|
f"{self.base_url}/api/push_structure",
|
|
250
249
|
json=payload,
|
|
@@ -256,7 +255,7 @@ class TaskReporter:
|
|
|
256
255
|
def _push_analysis(self) -> None:
|
|
257
256
|
"""推送分析信息"""
|
|
258
257
|
try:
|
|
259
|
-
analysis: dict[str, Any] = self.task_graph.get_graph_analysis()
|
|
258
|
+
analysis: dict[str, Any] = self.task_graph.get_graph_analysis()
|
|
260
259
|
payload: dict[str, Any] = {"analysis": analysis}
|
|
261
260
|
_ = self._session.post(
|
|
262
261
|
f"{self.base_url}/api/push_analysis",
|
|
@@ -266,19 +265,6 @@ class TaskReporter:
|
|
|
266
265
|
except Exception as e:
|
|
267
266
|
self.log_inlet.push_analysis_failed(e)
|
|
268
267
|
|
|
269
|
-
def _push_summary(self) -> None:
|
|
270
|
-
"""推送摘要信息"""
|
|
271
|
-
try:
|
|
272
|
-
summary: dict[str, Any] = self.task_graph.get_graph_summary() # type: ignore[reportUnknownMemberType]
|
|
273
|
-
payload: dict[str, Any] = {"summary": summary}
|
|
274
|
-
_ = self._session.post(
|
|
275
|
-
f"{self.base_url}/api/push_summary",
|
|
276
|
-
json=payload,
|
|
277
|
-
timeout=self._push_timeout(),
|
|
278
|
-
)
|
|
279
|
-
except Exception as e:
|
|
280
|
-
self.log_inlet.push_summary_failed(e)
|
|
281
|
-
|
|
282
268
|
|
|
283
269
|
class NullTaskReporter:
|
|
284
270
|
"""空实现的任务上报器,用于关闭上报功能时的占位对象。"""
|
|
@@ -103,15 +103,15 @@ class FailInlet(BaseInlet):
|
|
|
103
103
|
"""
|
|
104
104
|
super().__init__(fail_queue)
|
|
105
105
|
|
|
106
|
-
def start_graph(self,
|
|
106
|
+
def start_graph(self, structure_graph: dict[str, Any]) -> None:
|
|
107
107
|
"""
|
|
108
108
|
在运行开始时写入任务结构元信息到 jsonl 文件
|
|
109
109
|
|
|
110
|
-
:param
|
|
110
|
+
:param structure_graph: 任务图结构 JSON
|
|
111
111
|
"""
|
|
112
112
|
meta_item = {
|
|
113
113
|
"timestamp": datetime.now().isoformat(),
|
|
114
|
-
"structure":
|
|
114
|
+
"structure": structure_graph,
|
|
115
115
|
}
|
|
116
116
|
self._funnel(meta_item)
|
|
117
117
|
|