celestialflow 3.2.6__tar.gz → 3.2.8__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.
Files changed (58) hide show
  1. {celestialflow-3.2.6/src/celestialflow.egg-info → celestialflow-3.2.8}/PKG-INFO +131 -21
  2. {celestialflow-3.2.6 → celestialflow-3.2.8}/README.md +130 -19
  3. {celestialflow-3.2.6 → celestialflow-3.2.8}/pyproject.toml +9 -2
  4. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/__init__.py +4 -4
  5. celestialflow-3.2.8/src/celestialflow/benchmark/__init__.py +6 -0
  6. {celestialflow-3.2.6/src/celestialflow/utils → celestialflow-3.2.8/src/celestialflow/benchmark}/util_benchmark.py +20 -17
  7. {celestialflow-3.2.6/src/celestialflow/utils → celestialflow-3.2.8/src/celestialflow/benchmark}/util_clone.py +34 -12
  8. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/funnel/core_spout.py +4 -1
  9. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/graph/core_graph.py +306 -287
  10. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/graph/core_structure.py +40 -21
  11. {celestialflow-3.2.6/src/celestialflow/runtime → celestialflow-3.2.8/src/celestialflow/graph}/util_estimators.py +15 -65
  12. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/graph/util_graph.py +2 -3
  13. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/graph/util_serialize.py +7 -7
  14. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/observability/__init__.py +2 -3
  15. celestialflow-3.2.8/src/celestialflow/observability/core_observer.py +112 -0
  16. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/observability/core_report.py +42 -34
  17. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/observability/util_types.py +14 -7
  18. celestialflow-3.2.8/src/celestialflow/persistence/__init__.py +31 -0
  19. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/persistence/core_fallback.py +23 -10
  20. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/persistence/core_log.py +82 -57
  21. celestialflow-3.2.8/src/celestialflow/persistence/core_scope.py +41 -0
  22. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/persistence/util_payload.py +2 -1
  23. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/persistence/util_sqlite.py +10 -8
  24. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/__init__.py +1 -4
  25. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/core_envelope.py +11 -11
  26. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/core_metrics.py +77 -14
  27. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/core_queue.py +26 -44
  28. celestialflow-3.2.8/src/celestialflow/runtime/util_config.py +40 -0
  29. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/util_errors.py +207 -285
  30. celestialflow-3.2.8/src/celestialflow/runtime/util_estimators.py +68 -0
  31. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/util_event.py +63 -63
  32. {celestialflow-3.2.6/src/celestialflow/utils → celestialflow-3.2.8/src/celestialflow/runtime}/util_format.py +10 -18
  33. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/util_hash.py +3 -3
  34. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/util_types.py +2 -6
  35. {celestialflow-3.2.6/src/celestialflow/runtime → celestialflow-3.2.8/src/celestialflow/stage}/core_dispatch.py +68 -55
  36. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/core_executor.py +692 -698
  37. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/core_stage.py +172 -236
  38. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/core_stages.py +23 -15
  39. {celestialflow-3.2.6 → celestialflow-3.2.8/src/celestialflow.egg-info}/PKG-INFO +131 -21
  40. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow.egg-info/SOURCES.txt +9 -8
  41. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow.egg-info/requires.txt +0 -1
  42. celestialflow-3.2.6/src/celestialflow/observability/core_observer.py +0 -51
  43. celestialflow-3.2.6/src/celestialflow/observability/core_progress.py +0 -61
  44. celestialflow-3.2.6/src/celestialflow/persistence/__init__.py +0 -15
  45. celestialflow-3.2.6/src/celestialflow/utils/__init__.py +0 -5
  46. celestialflow-3.2.6/src/celestialflow/utils/util_collections.py +0 -16
  47. {celestialflow-3.2.6 → celestialflow-3.2.8}/LICENSE +0 -0
  48. {celestialflow-3.2.6 → celestialflow-3.2.8}/setup.cfg +0 -0
  49. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/funnel/__init__.py +0 -0
  50. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/funnel/core_inlet.py +0 -0
  51. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/funnel/util_count.py +0 -0
  52. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/graph/__init__.py +0 -0
  53. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/runtime/util_constant.py +0 -0
  54. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/__init__.py +0 -0
  55. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/util_callable.py +0 -0
  56. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow/stage/util_types.py +0 -0
  57. {celestialflow-3.2.6 → celestialflow-3.2.8}/src/celestialflow.egg-info/dependency_links.txt +0 -0
  58. {celestialflow-3.2.6 → celestialflow-3.2.8}/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.6
3
+ Version: 3.2.8
4
4
  Summary: A flexible GRAPH-based task orchestration framework.
5
5
  Author-email: Mr-xiaotian <mingxiaomingtian@gmail.com>
6
6
  License: MIT
@@ -14,7 +14,6 @@ Classifier: Topic :: Software Development :: Libraries
14
14
  Requires-Python: >=3.12
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: tqdm
18
17
  Requires-Dist: requests
19
18
  Dynamic: license-file
20
19
 
@@ -134,16 +133,27 @@ uv sync --group dev
134
133
  ```python
135
134
  from celestialflow import TaskStage, TaskGraph
136
135
 
137
- def add(x, y):
136
+
137
+ def add(x, y):
138
138
  return x + y
139
139
 
140
- def square(x):
141
- return x ** 2
140
+
141
+ def square(x):
142
+ return x**2
143
+
142
144
 
143
145
  if __name__ == "__main__":
144
146
  # 定义两个任务节点
145
- stage1 = TaskStage(name="Adder", func=add, stage_mode="thread", execution_mode="thread", unpack_task_args=True)
146
- stage2 = TaskStage(name="Squarer", func=square, stage_mode="thread", execution_mode="thread")
147
+ stage1 = TaskStage(
148
+ name="Adder",
149
+ func=add,
150
+ stage_mode="thread",
151
+ execution_mode="thread",
152
+ unpack_task_args=True,
153
+ )
154
+ stage2 = TaskStage(
155
+ name="Squarer", func=square, stage_mode="thread", execution_mode="thread"
156
+ )
147
157
 
148
158
  # 构建任务图结构
149
159
  graph = TaskGraph(name="DemoGraph")
@@ -165,12 +175,12 @@ if __name__ == "__main__":
165
175
  - [TaskExecutor.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_executor.md)
166
176
  - [TaskStage.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_stage.md)
167
177
  - [TaskGraph.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/graph/core_graph.md)
168
- - [TaskProgress.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_progress.md)
169
178
  - [TaskMetrics.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/core_metrics.md)
170
179
  - [TaskQueue.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/core_queue.md)
171
180
  - [TaskStages.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_stages.md)
172
181
  - [TaskReport.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_report.md)
173
182
  - [TaskStructure.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/graph/core_structure.md)
183
+ - [BaseObserver.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_observer.md)
174
184
  - [Go Worker.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/other/go_worker.md)
175
185
 
176
186
  推荐阅读顺序:
@@ -183,7 +193,7 @@ flowchart TD
183
193
  classDef execution fill:#f3e8ff,stroke:#a855f7,color:#581c87;
184
194
 
185
195
  TM[TaskExecutor.md] --> TS[TaskStage.md] --> TG[TaskGraph.md]
186
- TM --> TP[TaskProgress.md]
196
+ TM --> OB[BaseObserver.md]
187
197
  TM --> TME[TaskMetrics.md]
188
198
 
189
199
  TG --> TQ[TaskQueue.md]
@@ -247,26 +257,126 @@ flowchart TD
247
257
 
248
258
  ## 文件结构(File Structure)
249
259
 
260
+ ```
261
+ 📁 CelestialFlow (587MB 684KB 313B)
262
+ 📁 bench (296KB 842B)
263
+ 📁 [1项排除的目录] (194KB 222B)
264
+ 🐍 bench_datastructures.py (6KB 690B)
265
+ 🐍 bench_execution_mode.py (2KB 831B)
266
+ 🐍 bench_futures_memory.py (2KB 269B)
267
+ 🐍 bench_gil_vs_nogil.py (10KB 7B)
268
+ 🐍 bench_graph_mode.py (7KB 450B)
269
+ 🐍 bench_hash.py (7KB 67B)
270
+ 🐍 bench_hash_container.py (3KB 1009B)
271
+ 🐍 bench_hash_memory.py (3KB 642B)
272
+ 🐍 bench_http_grpc.py (2KB 608B)
273
+ 🐍 bench_ipc_queue.py (7KB 104B)
274
+ 🐍 bench_lock_overhead.py (9KB 421B)
275
+ 🐍 bench_mpqueue_vs_shared_memory.py (13KB 127B)
276
+ 🐍 bench_observer.py (7KB 860B)
277
+ 🐍 bench_persistence_spout.py (4KB 279B)
278
+ 🐍 bench_queue.py (5KB 857B)
279
+ 🐍 bench_requests.py (6KB 813B)
280
+ 🐍 bench_tqdm.py (1KB 235B)
281
+ 🐍 bench_utils.py (543B)
282
+ 📁 demo (147KB 87B)
283
+ 📁 [1项排除的目录] (100KB 9B)
284
+ 🐍 demo_executor.py (1KB 495B)
285
+ 🐍 demo_funnel.py (2KB 289B)
286
+ 🐍 demo_graph.py (3KB 565B)
287
+ 🐍 demo_network.py (3KB 879B)
288
+ 🐍 demo_observer.py (4KB 270B)
289
+ 🐍 demo_redis.py (9KB 144B)
290
+ 🐍 demo_stages.py (4KB 336B)
291
+ 🐍 demo_structure.py (12KB 24B)
292
+ 🐍 demo_utils.py (6KB 148B)
293
+ 📁 dist (147KB 48B)
294
+ ❓ .gitignore (1B)
295
+ ❓ celestialflow-3.2.7-py3-none-any.whl (79KB 235B)
296
+ 📦 celestialflow-3.2.7.tar.gz (67KB 836B)
297
+ 📁 docs (1MB 722KB 21B)
298
+ 📁 en[已折叠] (568KB 991B)
299
+ 📁 ja[已折叠] (642KB 383B)
300
+ 📁 zh-CN[已折叠] (534KB 695B)
301
+ 📁 experiments (2KB 1015B)
302
+ 🐍 experiment_networkx.py (1KB 878B)
303
+ 🐍 experiment_tqdm.py (1KB 137B)
304
+ 📁 img (5MB 871KB 242B)
305
+ 📷 file_structure.svg (4MB 918KB 1000B)
306
+ 📷 logo(old).png (836KB 542B)
307
+ 📷 logo.png (122KB 747B)
308
+ 📷 scc_condensation.svg (17KB 1B)
309
+ 📁 src (1MB 858KB 89B)
310
+ 📁 celestialflow[已折叠] (1MB 839KB 629B)
311
+ 📁 celestialflow.egg-info[已折叠] (18KB 484B)
312
+ 📁 tests (4MB 167KB 552B)
313
+ 📁 benchmark[已折叠] (38KB 197B)
314
+ 📁 funnel[已折叠] (96KB 363B)
315
+ 📁 graph[已折叠] (721KB 564B)
316
+ 📁 observability[已折叠] (189KB 236B)
317
+ 📁 persistence[已折叠] (388KB 426B)
318
+ 📁 runtime[已折叠] (1MB 295KB 529B)
319
+ 📁 stage[已折叠] (382KB 155B)
320
+ 📁 utils[已折叠] (639KB 527B)
321
+ 📁 [1项排除的目录] (487KB 589B)
322
+ 🐍 conftest.py (1KB 38B)
323
+ 🐍 __init__.py (0B)
324
+ 📁 [12项排除的目录] (573MB 420KB 160B)
325
+ ❓ .env (468B)
326
+ ❓ .gitignore (1KB 314B)
327
+ 📝 AGENTS.md (1KB 173B)
328
+ ❓ LICENSE (1KB 65B)
329
+ ❓ Makefile (155B)
330
+ ⚙️ pyproject.toml (2KB 668B)
331
+ 📝 README.md (19KB 24B)
332
+ 🔒 uv.lock (97KB 510B)
333
+ ```
250
334
  <p align="center">
251
- <img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
252
- <br/>
253
- <em>celestial-flow 3.2.6</em>
335
+ <em>celestial-flow 3.2.8</em>
254
336
  </p>
255
337
 
256
338
  (该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
257
339
 
258
340
  ## 版本日志(Version Log)
259
- - 3.2.6
341
+ - 3.2.8
260
342
  - feat:
261
- - `graph` `stage` 中添加直接读取db文件并重试/继续任务的方法
262
- - 分别为 `start_graph_db` `start_db`
343
+ - [IMPORTANT] 添加 `TaskGraph.run_async`, 现在可以直接进行图级别的异步
344
+ - 根据 `bench_graph_mode.py` 最新测试, 在I/O密集型任务中, `serial`+`async`(6.05s),比 `serial`+`serial`(69.04s)快 **11.4x**
345
+ - 在 `core_structure` 中添加报错校验
346
+ - 不再允许设置 `execution_mode=async` 时调用 `TashExecutor.start`(如今的`TashExecutor.run`), 只能调用 `TashExecutor.run_async`
347
+ - 另外调用 `TashExecutor.run_async` 时也会进行模式检查, 不是 `execution_mode=async` 就会抛出异常
348
+ - 在 `BaseObserver` 中添加 `observer_error`, 用于处理 `BaseObserver.on_*` 函数的报错
349
+ - 在 `TaskGraph._finish_start_graph` `TaskExecutor._finish_start` 中对所有执行步骤进行 `try-except`, 以使收尾步骤尽量全部完成
350
+ - 添加 `core_scope`, 用于独立控制 `funnel` 的生命周期, 并用于 `TaskGraph.run/run_async` `TaskExecutor.run/run_async`
263
351
  - refactor:
264
- - **[IMPORTANT]** 将web部分移至单独项目 [celestialflow-web](https://github.com/Mr-xiaotian/celestialflow-web)
265
- - 考虑许久的决定, 当前的web端代码与项目整体风格差异极大, 已经不再适合继续合并一处
266
- - 当然这意味着 `celestialflow-web` 命令在当前项目下失效, 需要单独安装 `pip install celestialflow-web`
267
- - chore:
268
- - 全量更新文档, 并翻译为en/ja双语言
269
- - 移除 docs/zh-CN 下的 `README.md`, 现在中文readme只保留根目录下的这一份
352
+ - [IMPORTANT] `TaskGraph.start_graph/start_graph_async` `TaskExecutor.start/start_async` 已被重命名为 `TaskGraph.run/run_async` `TaskExecutor.run/run_async`
353
+ - 破坏性更新
354
+ - 其底层缘由是为了合并 `TaskStage.start_stage/start_stage_async` `TaskExecutor.start/start_async` 而做出的一系列重构之一
355
+ - 现在的 `TaskGraph.start/start_async` `TaskExecutor.start/start_async` 不再接受任务, 而是专注于处理现有任务列表中的任务
356
+ - [IMPORTANT] 将funnel从 `TaskGraph` `TaskExecutor` 中的显性调用与显性传递, 改为所有使用端均从独立文件中import
357
+ - 一来是因为原先的传递链太丑了, 二来是为了简化 `TaskExecutor.start/start_async` 逻辑, 为其与 `TaskStage.start_stage/start_stage_async` 的合并做准备
358
+ - 移动部分文件以解决部分模块级的循环引用问题
359
+ - 原先并非文件级循环引用, 在使用上并无问题
360
+ - 修改 `TaskDispatch.dispatch_thread` 中处理已完成future的逻辑, 避免cpu浪费
361
+ - 删除 `util_errors` 中一些不必要的错误类
362
+ - 将 `TaskGraph._finalize_stages` 进行拆分, 删除不必要的机制, 将剩余机制移至其他方法
363
+ - 修改 `TaskGraph.set_reporter` 的逻辑, 使其与 `set_ctree` 保持一致
364
+ - 将 `TaskOutQueue` 中的 `queue_list|target_name|_name_to_idx` 改为 `_queues`, 并删除 `put_channel`
365
+ - 我有些困惑为什么最初我没有这么做
366
+ - 在 `TaskExecutor` 中合并 `_get_task_repr` and `_get_result_repr`
367
+ - 这两个方法原先差异巨大, 但后来经过多次其他部分的重构, 现在逻辑已经一致
368
+ - 将 `TaskStage` 中的 `_status` 交给 `TaskMetrics` 维护
369
+ - 依旧是为了合并 `TaskExecutor.start/start_async` 与 `TaskStage.start_stage/start_stage_async`
370
+ - 移除 `TaskGraph` 中的 `put_stage_queue`
371
+ - 任务输入完全使用 `TaskExecutor` 中的 `put_task` `put_signal` 方法
372
+ - fix:
373
+ - 在 `TaskDispatch.worker/worker_async` 中添加错误捕捉, 捕捉为 `CRITICAL` 级错误
374
+ - 避免 `worker` 级出错导致计数错误, 永远无法退出
375
+ - 在 `spout` 与 `reporter` 的 `stop` 操作中添加对于线程没有成功 `join` 的报错
376
+ - 修复 `TaskGraph.restore_db` 与 `TaskExecutor.restore_db` 中开启 `filter_by_error_type=Ture` 时跳过 `status=pending` 任务记录的问题
377
+ - 修复 `TaskGraph` 中部分 `get_*` 方法依赖 `_build_analysis` 的产物, 但 `_build_analysis` 未执行导致的问题
378
+ - 修复 `TaskMetrics` 中 `get_counts` 与 `is_tasks_finished` 中可能导致死锁的问题
379
+ - 修复 `TaskReporter` 中 `stop` 里进行的最后一次 `_refresh_all` 没有错误捕捉, 导致后续收尾未完成的问题
270
380
 
271
381
  更多过往日志可看:
272
382
 
@@ -114,16 +114,27 @@ uv sync --group dev
114
114
  ```python
115
115
  from celestialflow import TaskStage, TaskGraph
116
116
 
117
- def add(x, y):
117
+
118
+ def add(x, y):
118
119
  return x + y
119
120
 
120
- def square(x):
121
- return x ** 2
121
+
122
+ def square(x):
123
+ return x**2
124
+
122
125
 
123
126
  if __name__ == "__main__":
124
127
  # 定义两个任务节点
125
- stage1 = TaskStage(name="Adder", func=add, stage_mode="thread", execution_mode="thread", unpack_task_args=True)
126
- stage2 = TaskStage(name="Squarer", func=square, stage_mode="thread", execution_mode="thread")
128
+ stage1 = TaskStage(
129
+ name="Adder",
130
+ func=add,
131
+ stage_mode="thread",
132
+ execution_mode="thread",
133
+ unpack_task_args=True,
134
+ )
135
+ stage2 = TaskStage(
136
+ name="Squarer", func=square, stage_mode="thread", execution_mode="thread"
137
+ )
127
138
 
128
139
  # 构建任务图结构
129
140
  graph = TaskGraph(name="DemoGraph")
@@ -145,12 +156,12 @@ if __name__ == "__main__":
145
156
  - [TaskExecutor.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_executor.md)
146
157
  - [TaskStage.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_stage.md)
147
158
  - [TaskGraph.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/graph/core_graph.md)
148
- - [TaskProgress.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_progress.md)
149
159
  - [TaskMetrics.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/core_metrics.md)
150
160
  - [TaskQueue.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/runtime/core_queue.md)
151
161
  - [TaskStages.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/stage/core_stages.md)
152
162
  - [TaskReport.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_report.md)
153
163
  - [TaskStructure.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/graph/core_structure.md)
164
+ - [BaseObserver.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/src/observability/core_observer.md)
154
165
  - [Go Worker.md](https://github.com/Mr-xiaotian/CelestialFlow/blob/main/docs/zh-CN/other/go_worker.md)
155
166
 
156
167
  推荐阅读顺序:
@@ -163,7 +174,7 @@ flowchart TD
163
174
  classDef execution fill:#f3e8ff,stroke:#a855f7,color:#581c87;
164
175
 
165
176
  TM[TaskExecutor.md] --> TS[TaskStage.md] --> TG[TaskGraph.md]
166
- TM --> TP[TaskProgress.md]
177
+ TM --> OB[BaseObserver.md]
167
178
  TM --> TME[TaskMetrics.md]
168
179
 
169
180
  TG --> TQ[TaskQueue.md]
@@ -227,26 +238,126 @@ flowchart TD
227
238
 
228
239
  ## 文件结构(File Structure)
229
240
 
241
+ ```
242
+ 📁 CelestialFlow (587MB 684KB 313B)
243
+ 📁 bench (296KB 842B)
244
+ 📁 [1项排除的目录] (194KB 222B)
245
+ 🐍 bench_datastructures.py (6KB 690B)
246
+ 🐍 bench_execution_mode.py (2KB 831B)
247
+ 🐍 bench_futures_memory.py (2KB 269B)
248
+ 🐍 bench_gil_vs_nogil.py (10KB 7B)
249
+ 🐍 bench_graph_mode.py (7KB 450B)
250
+ 🐍 bench_hash.py (7KB 67B)
251
+ 🐍 bench_hash_container.py (3KB 1009B)
252
+ 🐍 bench_hash_memory.py (3KB 642B)
253
+ 🐍 bench_http_grpc.py (2KB 608B)
254
+ 🐍 bench_ipc_queue.py (7KB 104B)
255
+ 🐍 bench_lock_overhead.py (9KB 421B)
256
+ 🐍 bench_mpqueue_vs_shared_memory.py (13KB 127B)
257
+ 🐍 bench_observer.py (7KB 860B)
258
+ 🐍 bench_persistence_spout.py (4KB 279B)
259
+ 🐍 bench_queue.py (5KB 857B)
260
+ 🐍 bench_requests.py (6KB 813B)
261
+ 🐍 bench_tqdm.py (1KB 235B)
262
+ 🐍 bench_utils.py (543B)
263
+ 📁 demo (147KB 87B)
264
+ 📁 [1项排除的目录] (100KB 9B)
265
+ 🐍 demo_executor.py (1KB 495B)
266
+ 🐍 demo_funnel.py (2KB 289B)
267
+ 🐍 demo_graph.py (3KB 565B)
268
+ 🐍 demo_network.py (3KB 879B)
269
+ 🐍 demo_observer.py (4KB 270B)
270
+ 🐍 demo_redis.py (9KB 144B)
271
+ 🐍 demo_stages.py (4KB 336B)
272
+ 🐍 demo_structure.py (12KB 24B)
273
+ 🐍 demo_utils.py (6KB 148B)
274
+ 📁 dist (147KB 48B)
275
+ ❓ .gitignore (1B)
276
+ ❓ celestialflow-3.2.7-py3-none-any.whl (79KB 235B)
277
+ 📦 celestialflow-3.2.7.tar.gz (67KB 836B)
278
+ 📁 docs (1MB 722KB 21B)
279
+ 📁 en[已折叠] (568KB 991B)
280
+ 📁 ja[已折叠] (642KB 383B)
281
+ 📁 zh-CN[已折叠] (534KB 695B)
282
+ 📁 experiments (2KB 1015B)
283
+ 🐍 experiment_networkx.py (1KB 878B)
284
+ 🐍 experiment_tqdm.py (1KB 137B)
285
+ 📁 img (5MB 871KB 242B)
286
+ 📷 file_structure.svg (4MB 918KB 1000B)
287
+ 📷 logo(old).png (836KB 542B)
288
+ 📷 logo.png (122KB 747B)
289
+ 📷 scc_condensation.svg (17KB 1B)
290
+ 📁 src (1MB 858KB 89B)
291
+ 📁 celestialflow[已折叠] (1MB 839KB 629B)
292
+ 📁 celestialflow.egg-info[已折叠] (18KB 484B)
293
+ 📁 tests (4MB 167KB 552B)
294
+ 📁 benchmark[已折叠] (38KB 197B)
295
+ 📁 funnel[已折叠] (96KB 363B)
296
+ 📁 graph[已折叠] (721KB 564B)
297
+ 📁 observability[已折叠] (189KB 236B)
298
+ 📁 persistence[已折叠] (388KB 426B)
299
+ 📁 runtime[已折叠] (1MB 295KB 529B)
300
+ 📁 stage[已折叠] (382KB 155B)
301
+ 📁 utils[已折叠] (639KB 527B)
302
+ 📁 [1项排除的目录] (487KB 589B)
303
+ 🐍 conftest.py (1KB 38B)
304
+ 🐍 __init__.py (0B)
305
+ 📁 [12项排除的目录] (573MB 420KB 160B)
306
+ ❓ .env (468B)
307
+ ❓ .gitignore (1KB 314B)
308
+ 📝 AGENTS.md (1KB 173B)
309
+ ❓ LICENSE (1KB 65B)
310
+ ❓ Makefile (155B)
311
+ ⚙️ pyproject.toml (2KB 668B)
312
+ 📝 README.md (19KB 24B)
313
+ 🔒 uv.lock (97KB 510B)
314
+ ```
230
315
  <p align="center">
231
- <img src="https://raw.githubusercontent.com/Mr-xiaotian/CelestialFlow/main/img/file_structure.svg" alt="FileStructure" />
232
- <br/>
233
- <em>celestial-flow 3.2.6</em>
316
+ <em>celestial-flow 3.2.8</em>
234
317
  </p>
235
318
 
236
319
  (该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
237
320
 
238
321
  ## 版本日志(Version Log)
239
- - 3.2.6
322
+ - 3.2.8
240
323
  - feat:
241
- - `graph` `stage` 中添加直接读取db文件并重试/继续任务的方法
242
- - 分别为 `start_graph_db` `start_db`
324
+ - [IMPORTANT] 添加 `TaskGraph.run_async`, 现在可以直接进行图级别的异步
325
+ - 根据 `bench_graph_mode.py` 最新测试, 在I/O密集型任务中, `serial`+`async`(6.05s),比 `serial`+`serial`(69.04s)快 **11.4x**
326
+ - 在 `core_structure` 中添加报错校验
327
+ - 不再允许设置 `execution_mode=async` 时调用 `TashExecutor.start`(如今的`TashExecutor.run`), 只能调用 `TashExecutor.run_async`
328
+ - 另外调用 `TashExecutor.run_async` 时也会进行模式检查, 不是 `execution_mode=async` 就会抛出异常
329
+ - 在 `BaseObserver` 中添加 `observer_error`, 用于处理 `BaseObserver.on_*` 函数的报错
330
+ - 在 `TaskGraph._finish_start_graph` `TaskExecutor._finish_start` 中对所有执行步骤进行 `try-except`, 以使收尾步骤尽量全部完成
331
+ - 添加 `core_scope`, 用于独立控制 `funnel` 的生命周期, 并用于 `TaskGraph.run/run_async` `TaskExecutor.run/run_async`
243
332
  - refactor:
244
- - **[IMPORTANT]** 将web部分移至单独项目 [celestialflow-web](https://github.com/Mr-xiaotian/celestialflow-web)
245
- - 考虑许久的决定, 当前的web端代码与项目整体风格差异极大, 已经不再适合继续合并一处
246
- - 当然这意味着 `celestialflow-web` 命令在当前项目下失效, 需要单独安装 `pip install celestialflow-web`
247
- - chore:
248
- - 全量更新文档, 并翻译为en/ja双语言
249
- - 移除 docs/zh-CN 下的 `README.md`, 现在中文readme只保留根目录下的这一份
333
+ - [IMPORTANT] `TaskGraph.start_graph/start_graph_async` `TaskExecutor.start/start_async` 已被重命名为 `TaskGraph.run/run_async` `TaskExecutor.run/run_async`
334
+ - 破坏性更新
335
+ - 其底层缘由是为了合并 `TaskStage.start_stage/start_stage_async` `TaskExecutor.start/start_async` 而做出的一系列重构之一
336
+ - 现在的 `TaskGraph.start/start_async` `TaskExecutor.start/start_async` 不再接受任务, 而是专注于处理现有任务列表中的任务
337
+ - [IMPORTANT] 将funnel从 `TaskGraph` `TaskExecutor` 中的显性调用与显性传递, 改为所有使用端均从独立文件中import
338
+ - 一来是因为原先的传递链太丑了, 二来是为了简化 `TaskExecutor.start/start_async` 逻辑, 为其与 `TaskStage.start_stage/start_stage_async` 的合并做准备
339
+ - 移动部分文件以解决部分模块级的循环引用问题
340
+ - 原先并非文件级循环引用, 在使用上并无问题
341
+ - 修改 `TaskDispatch.dispatch_thread` 中处理已完成future的逻辑, 避免cpu浪费
342
+ - 删除 `util_errors` 中一些不必要的错误类
343
+ - 将 `TaskGraph._finalize_stages` 进行拆分, 删除不必要的机制, 将剩余机制移至其他方法
344
+ - 修改 `TaskGraph.set_reporter` 的逻辑, 使其与 `set_ctree` 保持一致
345
+ - 将 `TaskOutQueue` 中的 `queue_list|target_name|_name_to_idx` 改为 `_queues`, 并删除 `put_channel`
346
+ - 我有些困惑为什么最初我没有这么做
347
+ - 在 `TaskExecutor` 中合并 `_get_task_repr` and `_get_result_repr`
348
+ - 这两个方法原先差异巨大, 但后来经过多次其他部分的重构, 现在逻辑已经一致
349
+ - 将 `TaskStage` 中的 `_status` 交给 `TaskMetrics` 维护
350
+ - 依旧是为了合并 `TaskExecutor.start/start_async` 与 `TaskStage.start_stage/start_stage_async`
351
+ - 移除 `TaskGraph` 中的 `put_stage_queue`
352
+ - 任务输入完全使用 `TaskExecutor` 中的 `put_task` `put_signal` 方法
353
+ - fix:
354
+ - 在 `TaskDispatch.worker/worker_async` 中添加错误捕捉, 捕捉为 `CRITICAL` 级错误
355
+ - 避免 `worker` 级出错导致计数错误, 永远无法退出
356
+ - 在 `spout` 与 `reporter` 的 `stop` 操作中添加对于线程没有成功 `join` 的报错
357
+ - 修复 `TaskGraph.restore_db` 与 `TaskExecutor.restore_db` 中开启 `filter_by_error_type=Ture` 时跳过 `status=pending` 任务记录的问题
358
+ - 修复 `TaskGraph` 中部分 `get_*` 方法依赖 `_build_analysis` 的产物, 但 `_build_analysis` 未执行导致的问题
359
+ - 修复 `TaskMetrics` 中 `get_counts` 与 `is_tasks_finished` 中可能导致死锁的问题
360
+ - 修复 `TaskReporter` 中 `stop` 里进行的最后一次 `_refresh_all` 没有错误捕捉, 导致后续收尾未完成的问题
250
361
 
251
362
  更多过往日志可看:
252
363
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "celestialflow"
7
- version = "3.2.6"
7
+ version = "3.2.8"
8
8
  description = "A flexible GRAPH-based task orchestration framework."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -13,7 +13,6 @@ keywords = ["workflow", "task", "graph", "async", "CelestialFlow"]
13
13
  requires-python = ">=3.12"
14
14
 
15
15
  dependencies = [
16
- "tqdm",
17
16
  "requests",
18
17
  ]
19
18
 
@@ -28,6 +27,9 @@ classifiers = [
28
27
  "Homepage" = "https://github.com/Mr-xiaotian/CelestialFlow"
29
28
  "Bug Tracker" = "https://github.com/Mr-xiaotian/CelestialFlow/issues"
30
29
 
30
+ [tool.uv]
31
+ index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"
32
+
31
33
  [tool.pytest.ini_options]
32
34
  addopts = "-s"
33
35
  log_cli = true
@@ -54,12 +56,17 @@ dev = [
54
56
  "pyright>=1.1.409",
55
57
  "redis",
56
58
  "celestialtree>=0.1.3",
59
+ "tqdm",
57
60
  ]
58
61
 
62
+ [tool.celestialflow]
63
+ log_level = "INFO"
64
+
59
65
  [tool.pyright]
60
66
  include = ["src"]
61
67
  ignore = ["tests", "**/tests/**", "typings", "demo", "bench", "experiments", "examples", "temp"]
62
68
 
69
+ pythonVersion = "3.14"
63
70
  typeCheckingMode = "strict"
64
71
  reportUnusedFunction = "none"
65
72
  reportImplicitOverride = "none"
@@ -4,6 +4,7 @@
4
4
  提供任务图构建、执行调度、实时监控与持久化等核心能力。
5
5
  """
6
6
 
7
+ from .benchmark.util_benchmark import benchmark_executor, benchmark_graph
7
8
  from .funnel import BaseInlet, BaseSpout
8
9
  from .graph import (
9
10
  TaskChain,
@@ -14,11 +15,12 @@ from .graph import (
14
15
  TaskLoop,
15
16
  TaskWheel,
16
17
  )
17
- from .observability import BaseObserver, TaskProgress
18
+ from .observability import BaseObserver, TaskReporter
18
19
  from .persistence.util_sqlite import (
19
20
  load_records,
20
21
  load_tasks_grouped_by_stage,
21
22
  )
23
+ from .runtime.util_format import format_table
22
24
  from .runtime.util_hash import make_hashable
23
25
  from .runtime.util_types import TerminationSignal
24
26
  from .stage import (
@@ -27,8 +29,6 @@ from .stage import (
27
29
  TaskSplitter,
28
30
  TaskStage,
29
31
  )
30
- from .utils.util_benchmark import benchmark_executor, benchmark_graph
31
- from .utils.util_format import format_table
32
32
 
33
33
  __all__ = [
34
34
  "BaseInlet",
@@ -41,7 +41,7 @@ __all__ = [
41
41
  "TaskGraph",
42
42
  "TaskGrid",
43
43
  "TaskLoop",
44
- "TaskProgress",
44
+ "TaskReporter",
45
45
  "TaskRouter",
46
46
  "TaskSplitter",
47
47
  "TaskStage",
@@ -0,0 +1,6 @@
1
+ # benchmark/__init__.py
2
+ """CelestialFlow 基准测试与克隆工具模块。
3
+
4
+ 提供执行器/任务图的克隆(clone)与基准测试(benchmark)能力。
5
+ 该模块位于依赖链顶层,可依赖其他模块,但不应被其他模块依赖。
6
+ """
@@ -1,4 +1,4 @@
1
- # utils/util_benchmark.py
1
+ # benchmark/util_benchmark.py
2
2
  from __future__ import annotations
3
3
 
4
4
  import time
@@ -6,9 +6,9 @@ from collections.abc import Iterable, Mapping
6
6
  from typing import Any
7
7
 
8
8
  from ..graph import TaskGraph
9
+ from ..runtime.util_format import format_table
9
10
  from ..stage import TaskExecutor
10
11
  from .util_clone import clone_executor, clone_graph
11
- from .util_format import format_table
12
12
 
13
13
  type AnyTaskExecutor = TaskExecutor[Any, Any]
14
14
 
@@ -41,7 +41,8 @@ async def benchmark_executor(
41
41
  cloned_executor.set_execution_mode(mode)
42
42
 
43
43
  start: float = time.perf_counter()
44
- cloned_executor.start(task_list)
44
+ cloned_executor.put_tasks(task_list)
45
+ cloned_executor.start()
45
46
  use_time.append([time.perf_counter() - start])
46
47
  results.append(cloned_executor.get_success_pairs())
47
48
 
@@ -50,7 +51,8 @@ async def benchmark_executor(
50
51
  cloned_executor.set_execution_mode(mode)
51
52
 
52
53
  start = time.perf_counter()
53
- await cloned_executor.start_async(task_list)
54
+ cloned_executor.put_tasks(task_list)
55
+ await cloned_executor.start_async()
54
56
  use_time.append([time.perf_counter() - start])
55
57
  results.append(cloned_executor.get_success_pairs())
56
58
 
@@ -68,7 +70,7 @@ async def benchmark_executor(
68
70
  }
69
71
 
70
72
 
71
- def benchmark_graph(
73
+ async def benchmark_graph(
72
74
  sync_graph: TaskGraph,
73
75
  async_graph: TaskGraph,
74
76
  init_tasks_dict: Mapping[str, Iterable[Any]],
@@ -88,38 +90,39 @@ def benchmark_graph(
88
90
  :return: 包含测试结果的字典
89
91
  """
90
92
  stage_modes = stage_modes or ["serial", "thread"]
91
- sync_modes = execution_sync_modes or ["serial", "thread"]
92
- async_modes = execution_async_modes or ["async"]
93
+ execution_sync_modes = execution_sync_modes or ["serial", "thread"]
94
+ execution_async_modes = execution_async_modes or ["async"]
93
95
 
94
96
  base_tasks: dict[str, list[Any]] = {
95
97
  stage_name: list(tasks) for stage_name, tasks in init_tasks_dict.items()
96
98
  }
97
- execution_modes: list[str] = sync_modes + async_modes
99
+ execution_modes: list[str] = execution_sync_modes + execution_async_modes
98
100
 
99
101
  test_table_list: list[list[float]] = []
100
102
 
101
103
  for stage_mode in stage_modes:
102
104
  time_list: list[float] = []
103
- for execution_mode in sync_modes:
105
+
106
+ for execution_mode in execution_sync_modes:
104
107
  cloned_graph: TaskGraph = clone_graph(sync_graph)
105
108
  cloned_graph.set_graph_mode(stage_mode, execution_mode)
106
109
 
107
- run_tasks: dict[str, list[Any]] = {
110
+ sync_run_tasks: dict[str, Iterable[Any]] = {
108
111
  stage_name: list(tasks) for stage_name, tasks in base_tasks.items()
109
112
  }
110
113
  start_time: float = time.perf_counter()
111
- cloned_graph.start_graph(run_tasks)
114
+ cloned_graph.run(sync_run_tasks)
112
115
  time_list.append(time.perf_counter() - start_time)
113
116
 
114
- for execution_mode in async_modes:
117
+ for execution_mode in execution_async_modes:
115
118
  cloned_graph = clone_graph(async_graph)
116
119
  cloned_graph.set_graph_mode(stage_mode, execution_mode)
117
120
 
118
- run_tasks = {
121
+ async_run_tasks: dict[str, Iterable[Any]] = {
119
122
  stage_name: list(tasks) for stage_name, tasks in base_tasks.items()
120
123
  }
121
124
  start_time = time.perf_counter()
122
- cloned_graph.start_graph(run_tasks)
125
+ await cloned_graph.run_async(async_run_tasks)
123
126
  time_list.append(time.perf_counter() - start_time)
124
127
 
125
128
  test_table_list.append(time_list)
@@ -128,12 +131,12 @@ def benchmark_graph(
128
131
  test_table_list,
129
132
  stage_modes,
130
133
  execution_modes,
131
- r"stage\execution",
134
+ "stage/execution",
132
135
  )
133
136
  print(f"Time table:\n{time_table}")
134
137
  return {
135
138
  "table": time_table,
136
139
  "stage_modes": stage_modes,
137
- "sync_modes": sync_modes,
138
- "async_modes": async_modes if async_graph else [],
140
+ "sync_modes": execution_sync_modes,
141
+ "async_modes": execution_async_modes if async_graph else [],
139
142
  }