celestialflow 3.2.6__tar.gz → 3.2.7__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 (52) hide show
  1. {celestialflow-3.2.6/src/celestialflow.egg-info → celestialflow-3.2.7}/PKG-INFO +104 -21
  2. {celestialflow-3.2.6 → celestialflow-3.2.7}/README.md +103 -19
  3. {celestialflow-3.2.6 → celestialflow-3.2.7}/pyproject.toml +3 -2
  4. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/__init__.py +1 -2
  5. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/graph/core_graph.py +11 -3
  6. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/observability/__init__.py +0 -2
  7. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/core_dispatch.py +7 -2
  8. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/core_metrics.py +41 -1
  9. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/core_queue.py +10 -23
  10. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/core_executor.py +14 -42
  11. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/core_stage.py +237 -236
  12. {celestialflow-3.2.6 → celestialflow-3.2.7/src/celestialflow.egg-info}/PKG-INFO +104 -21
  13. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow.egg-info/SOURCES.txt +0 -1
  14. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow.egg-info/requires.txt +0 -1
  15. celestialflow-3.2.6/src/celestialflow/observability/core_progress.py +0 -61
  16. {celestialflow-3.2.6 → celestialflow-3.2.7}/LICENSE +0 -0
  17. {celestialflow-3.2.6 → celestialflow-3.2.7}/setup.cfg +0 -0
  18. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/funnel/__init__.py +0 -0
  19. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/funnel/core_inlet.py +0 -0
  20. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/funnel/core_spout.py +0 -0
  21. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/funnel/util_count.py +0 -0
  22. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/graph/__init__.py +0 -0
  23. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/graph/core_structure.py +0 -0
  24. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/graph/util_graph.py +0 -0
  25. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/graph/util_serialize.py +0 -0
  26. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/observability/core_observer.py +0 -0
  27. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/observability/core_report.py +0 -0
  28. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/observability/util_types.py +0 -0
  29. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/persistence/__init__.py +0 -0
  30. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/persistence/core_fallback.py +0 -0
  31. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/persistence/core_log.py +0 -0
  32. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/persistence/util_payload.py +0 -0
  33. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/persistence/util_sqlite.py +0 -0
  34. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/__init__.py +0 -0
  35. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/core_envelope.py +0 -0
  36. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_constant.py +0 -0
  37. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_errors.py +0 -0
  38. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_estimators.py +0 -0
  39. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_event.py +0 -0
  40. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_hash.py +0 -0
  41. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/runtime/util_types.py +0 -0
  42. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/__init__.py +0 -0
  43. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/core_stages.py +0 -0
  44. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/util_callable.py +0 -0
  45. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/stage/util_types.py +0 -0
  46. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/utils/__init__.py +0 -0
  47. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/utils/util_benchmark.py +0 -0
  48. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/utils/util_clone.py +0 -0
  49. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/utils/util_collections.py +0 -0
  50. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow/utils/util_format.py +0 -0
  51. {celestialflow-3.2.6 → celestialflow-3.2.7}/src/celestialflow.egg-info/dependency_links.txt +0 -0
  52. {celestialflow-3.2.6 → celestialflow-3.2.7}/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.7
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,99 @@ flowchart TD
247
257
 
248
258
  ## 文件结构(File Structure)
249
259
 
260
+ ```
261
+ 📁 CelestialFlow (471MB 982KB 22B)
262
+ 📁 .agents (55KB 152B)
263
+ 📁 skills[已折叠] (55KB 152B)
264
+ 📁 .claude (99B)
265
+ 🗄️ settings.local.json (99B)
266
+ 📁 .github (601B)
267
+ 📁 workflows[已折叠] (601B)
268
+ 📁 bench (150KB 552B)
269
+ 📁 [1项排除的目录] (47KB 905B)
270
+ 🐍 bench_datastructures.py (6KB 690B)
271
+ 🐍 bench_execution_mode.py (2KB 889B)
272
+ 🐍 bench_futures_memory.py (2KB 267B)
273
+ 🐍 bench_gil_vs_nogil.py (10KB 159B)
274
+ 🐍 bench_graph_mode.py (7KB 173B)
275
+ 🐍 bench_hash.py (7KB 39B)
276
+ 🐍 bench_hash_container.py (3KB 1009B)
277
+ 🐍 bench_hash_memory.py (3KB 613B)
278
+ 🐍 bench_http_grpc.py (2KB 883B)
279
+ 🐍 bench_ipc_queue.py (7KB 74B)
280
+ 🐍 bench_lock_overhead.py (9KB 421B)
281
+ 🐍 bench_mpqueue_vs_shared_memory.py (13KB 106B)
282
+ 🐍 bench_observer.py (7KB 899B)
283
+ 🐍 bench_persistence_spout.py (4KB 193B)
284
+ 🐍 bench_queue.py (5KB 857B)
285
+ 🐍 bench_requests.py (6KB 813B)
286
+ 🐍 bench_tqdm.py (1KB 235B)
287
+ 🐍 bench_utils.py (543B)
288
+ 📁 demo (105KB 440B)
289
+ 📁 [1项排除的目录] (61KB 883B)
290
+ 🐍 demo_executor.py (1KB 504B)
291
+ 🐍 demo_funnel.py (2KB 289B)
292
+ 🐍 demo_graph.py (3KB 615B)
293
+ 🐍 demo_observer.py (4KB 293B)
294
+ 🐍 demo_redis.py (9KB 201B)
295
+ 🐍 demo_stages.py (4KB 519B)
296
+ 🐍 demo_structure.py (12KB 8B)
297
+ 🐍 demo_utils.py (6KB 200B)
298
+ 📁 dist (145KB 290B)
299
+ ❓ .gitignore (1B)
300
+ ❓ celestialflow-3.2.6-py3-none-any.whl (78KB 975B)
301
+ 📦 celestialflow-3.2.6.tar.gz (66KB 338B)
302
+ 📁 docs (1MB 712KB 884B)
303
+ 📁 en[已折叠] (569KB 485B)
304
+ 📁 ja[已折叠] (642KB 959B)
305
+ 📁 zh-CN[已折叠] (524KB 464B)
306
+ 📁 experiments (2KB 1015B)
307
+ 🐍 experiment_networkx.py (1KB 878B)
308
+ 🐍 experiment_tqdm.py (1KB 137B)
309
+ 📁 img (5MB 871KB 242B)
310
+ 📷 file_structure.svg (4MB 918KB 1000B)
311
+ 📷 logo(old).png (836KB 542B)
312
+ 📷 logo.png (122KB 747B)
313
+ 📷 scc_condensation.svg (17KB 1B)
314
+ 📁 src (1MB 767KB 296B)
315
+ 📁 celestialflow[已折叠] (1MB 752KB 195B)
316
+ 📁 celestialflow.egg-info[已折叠] (15KB 101B)
317
+ 📁 tests (3MB 902KB 217B)
318
+ 📁 funnel[已折叠] (96KB 481B)
319
+ 📁 graph[已折叠] (631KB 532B)
320
+ 📁 observability[已折叠] (157KB 435B)
321
+ 📁 persistence[已折叠] (359KB 68B)
322
+ 📁 runtime[已折叠] (1MB 286KB 487B)
323
+ 📁 stage[已折叠] (281KB 752B)
324
+ 📁 utils[已折叠] (648KB 931B)
325
+ 📁 [1项排除的目录] (487KB 589B)
326
+ 🐍 conftest.py (1KB 38B)
327
+ 🐍 __init__.py (0B)
328
+ 📁 [9项排除的目录] (458MB 223KB 525B)
329
+ ❓ .env (468B)
330
+ ❓ .gitignore (1KB 313B)
331
+ 📝 AGENTS.md (971B)
332
+ ❓ LICENSE (1KB 65B)
333
+ ⚙️ pyproject.toml (2KB 555B)
334
+ 📝 README.md (12KB 272B)
335
+ 🔒 uv.lock (98KB 257B)
336
+ ```
250
337
  <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>
338
+ <em>celestial-flow 3.2.7</em>
254
339
  </p>
255
340
 
256
341
  (该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
257
342
 
258
343
  ## 版本日志(Version Log)
259
- - 3.2.6
344
+ - 3.2.7
260
345
  - feat:
261
- - `graph` `stage` 中添加直接读取db文件并重试/继续任务的方法
262
- - 分别为 `start_graph_db` `start_db`
346
+ - `TaskInQueue` 中添加 `maxsize` 参数, 用于限制队列最大长度
347
+ - `graph.connect` 中添加对两个stage输入输出参数类型的检验, 如果不通过, 会有pyright报错
263
348
  - 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只保留根目录下的这一份
349
+ - 移除对 `tqdm` 的依赖
350
+ - 根据 `bench\bench_observer.py`, tqdm对轻量级任务影响有限
351
+ - 这次移除主要是为了完成尽量零第三方库依赖的目标
352
+ - 将 `observer` 的管理从 `executor` 转到 `metric`
270
353
 
271
354
  更多过往日志可看:
272
355
 
@@ -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,99 @@ flowchart TD
227
238
 
228
239
  ## 文件结构(File Structure)
229
240
 
241
+ ```
242
+ 📁 CelestialFlow (471MB 982KB 22B)
243
+ 📁 .agents (55KB 152B)
244
+ 📁 skills[已折叠] (55KB 152B)
245
+ 📁 .claude (99B)
246
+ 🗄️ settings.local.json (99B)
247
+ 📁 .github (601B)
248
+ 📁 workflows[已折叠] (601B)
249
+ 📁 bench (150KB 552B)
250
+ 📁 [1项排除的目录] (47KB 905B)
251
+ 🐍 bench_datastructures.py (6KB 690B)
252
+ 🐍 bench_execution_mode.py (2KB 889B)
253
+ 🐍 bench_futures_memory.py (2KB 267B)
254
+ 🐍 bench_gil_vs_nogil.py (10KB 159B)
255
+ 🐍 bench_graph_mode.py (7KB 173B)
256
+ 🐍 bench_hash.py (7KB 39B)
257
+ 🐍 bench_hash_container.py (3KB 1009B)
258
+ 🐍 bench_hash_memory.py (3KB 613B)
259
+ 🐍 bench_http_grpc.py (2KB 883B)
260
+ 🐍 bench_ipc_queue.py (7KB 74B)
261
+ 🐍 bench_lock_overhead.py (9KB 421B)
262
+ 🐍 bench_mpqueue_vs_shared_memory.py (13KB 106B)
263
+ 🐍 bench_observer.py (7KB 899B)
264
+ 🐍 bench_persistence_spout.py (4KB 193B)
265
+ 🐍 bench_queue.py (5KB 857B)
266
+ 🐍 bench_requests.py (6KB 813B)
267
+ 🐍 bench_tqdm.py (1KB 235B)
268
+ 🐍 bench_utils.py (543B)
269
+ 📁 demo (105KB 440B)
270
+ 📁 [1项排除的目录] (61KB 883B)
271
+ 🐍 demo_executor.py (1KB 504B)
272
+ 🐍 demo_funnel.py (2KB 289B)
273
+ 🐍 demo_graph.py (3KB 615B)
274
+ 🐍 demo_observer.py (4KB 293B)
275
+ 🐍 demo_redis.py (9KB 201B)
276
+ 🐍 demo_stages.py (4KB 519B)
277
+ 🐍 demo_structure.py (12KB 8B)
278
+ 🐍 demo_utils.py (6KB 200B)
279
+ 📁 dist (145KB 290B)
280
+ ❓ .gitignore (1B)
281
+ ❓ celestialflow-3.2.6-py3-none-any.whl (78KB 975B)
282
+ 📦 celestialflow-3.2.6.tar.gz (66KB 338B)
283
+ 📁 docs (1MB 712KB 884B)
284
+ 📁 en[已折叠] (569KB 485B)
285
+ 📁 ja[已折叠] (642KB 959B)
286
+ 📁 zh-CN[已折叠] (524KB 464B)
287
+ 📁 experiments (2KB 1015B)
288
+ 🐍 experiment_networkx.py (1KB 878B)
289
+ 🐍 experiment_tqdm.py (1KB 137B)
290
+ 📁 img (5MB 871KB 242B)
291
+ 📷 file_structure.svg (4MB 918KB 1000B)
292
+ 📷 logo(old).png (836KB 542B)
293
+ 📷 logo.png (122KB 747B)
294
+ 📷 scc_condensation.svg (17KB 1B)
295
+ 📁 src (1MB 767KB 296B)
296
+ 📁 celestialflow[已折叠] (1MB 752KB 195B)
297
+ 📁 celestialflow.egg-info[已折叠] (15KB 101B)
298
+ 📁 tests (3MB 902KB 217B)
299
+ 📁 funnel[已折叠] (96KB 481B)
300
+ 📁 graph[已折叠] (631KB 532B)
301
+ 📁 observability[已折叠] (157KB 435B)
302
+ 📁 persistence[已折叠] (359KB 68B)
303
+ 📁 runtime[已折叠] (1MB 286KB 487B)
304
+ 📁 stage[已折叠] (281KB 752B)
305
+ 📁 utils[已折叠] (648KB 931B)
306
+ 📁 [1项排除的目录] (487KB 589B)
307
+ 🐍 conftest.py (1KB 38B)
308
+ 🐍 __init__.py (0B)
309
+ 📁 [9项排除的目录] (458MB 223KB 525B)
310
+ ❓ .env (468B)
311
+ ❓ .gitignore (1KB 313B)
312
+ 📝 AGENTS.md (971B)
313
+ ❓ LICENSE (1KB 65B)
314
+ ⚙️ pyproject.toml (2KB 555B)
315
+ 📝 README.md (12KB 272B)
316
+ 🔒 uv.lock (98KB 257B)
317
+ ```
230
318
  <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>
319
+ <em>celestial-flow 3.2.7</em>
234
320
  </p>
235
321
 
236
322
  (该视图由我的另一个项目[CelestialVault](https://github.com/Mr-xiaotian/CelestialVault)中inst_file.FileTree.print_tree()生成。转换为图片则借助[Carbon](https://carbon.now.sh)。)
237
323
 
238
324
  ## 版本日志(Version Log)
239
- - 3.2.6
325
+ - 3.2.7
240
326
  - feat:
241
- - `graph` `stage` 中添加直接读取db文件并重试/继续任务的方法
242
- - 分别为 `start_graph_db` `start_db`
327
+ - `TaskInQueue` 中添加 `maxsize` 参数, 用于限制队列最大长度
328
+ - `graph.connect` 中添加对两个stage输入输出参数类型的检验, 如果不通过, 会有pyright报错
243
329
  - 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只保留根目录下的这一份
330
+ - 移除对 `tqdm` 的依赖
331
+ - 根据 `bench\bench_observer.py`, tqdm对轻量级任务影响有限
332
+ - 这次移除主要是为了完成尽量零第三方库依赖的目标
333
+ - 将 `observer` 的管理从 `executor` 转到 `metric`
250
334
 
251
335
  更多过往日志可看:
252
336
 
@@ -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.7"
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
 
@@ -54,12 +53,14 @@ dev = [
54
53
  "pyright>=1.1.409",
55
54
  "redis",
56
55
  "celestialtree>=0.1.3",
56
+ "tqdm",
57
57
  ]
58
58
 
59
59
  [tool.pyright]
60
60
  include = ["src"]
61
61
  ignore = ["tests", "**/tests/**", "typings", "demo", "bench", "experiments", "examples", "temp"]
62
62
 
63
+ pythonVersion = "3.14"
63
64
  typeCheckingMode = "strict"
64
65
  reportUnusedFunction = "none"
65
66
  reportImplicitOverride = "none"
@@ -14,7 +14,7 @@ from .graph import (
14
14
  TaskLoop,
15
15
  TaskWheel,
16
16
  )
17
- from .observability import BaseObserver, TaskProgress
17
+ from .observability import BaseObserver
18
18
  from .persistence.util_sqlite import (
19
19
  load_records,
20
20
  load_tasks_grouped_by_stage,
@@ -41,7 +41,6 @@ __all__ = [
41
41
  "TaskGraph",
42
42
  "TaskGrid",
43
43
  "TaskLoop",
44
- "TaskProgress",
45
44
  "TaskRouter",
46
45
  "TaskSplitter",
47
46
  "TaskStage",
@@ -27,6 +27,7 @@ from ..runtime.util_estimators import (
27
27
  )
28
28
  from ..runtime.util_event import EventClient, LocalEventClient
29
29
  from ..runtime.util_types import TerminationSignal
30
+ from ..stage.core_stage import TaskStage
30
31
  from ..stage.util_types import AnyTaskStage
31
32
  from ..utils.util_collections import cluster_by_value_sorted
32
33
  from ..utils.util_format import format_avg_time
@@ -103,20 +104,27 @@ class TaskGraph:
103
104
  """
104
105
  # 用于保存所有子线程的引用
105
106
  self.threads: list[threading.Thread] = []
107
+
106
108
  # 用于保存每个节点的运行信息
107
109
  self.stage_dict: dict[str, AnyTaskStage] = {}
110
+
108
111
  # 用于保存每个节点的上一次collect_runtime_snapshot()的状态信息
109
112
  self.status_dict: dict[str, dict[str, Any]] = defaultdict(dict)
113
+
110
114
  # 用于保存最近一次状态快照对应的统一时间戳
111
115
  self.status_timestamp: float = 0.0
116
+
112
117
  # 用于保存每个节点的输入任务ID集合
113
118
  self.input_ids: dict[str, set[int]] = defaultdict(set)
119
+
114
120
  # 用于保存源节点列表(由 _build_analysis 自动计算)
115
121
  self.source_stages: list[AnyTaskStage] = []
122
+
116
123
  # 用于保存图结构的邻接表
117
124
  self.out_edges: dict[str, list[str]] = defaultdict(list)
118
125
  self.in_edges: dict[str, list[str]] = defaultdict(list)
119
126
  self.order_graph = OrderGraph()
127
+
120
128
  # 用于保存任务图启动时间
121
129
  self.start_time: float = 0.0
122
130
 
@@ -157,10 +165,10 @@ class TaskGraph:
157
165
  stage.set_ctree(self.ctree_client)
158
166
  stage.set_inlet(self.fallback_inlet, self.log_inlet)
159
167
 
160
- def connect(
168
+ def connect[R](
161
169
  self,
162
- from_stages: list[AnyTaskStage],
163
- to_stages: list[AnyTaskStage],
170
+ from_stages: list[TaskStage[Any, R]],
171
+ to_stages: list[TaskStage[R, Any]],
164
172
  ) -> None:
165
173
  """
166
174
  建立超边连接:from_stages 中的每个节点连接到 to_stages 中的每个节点。
@@ -5,12 +5,10 @@
5
5
  """
6
6
 
7
7
  from .core_observer import BaseObserver
8
- from .core_progress import TaskProgress
9
8
  from .core_report import NullTaskReporter, TaskReporter
10
9
 
11
10
  __all__ = [
12
11
  "BaseObserver",
13
12
  "NullTaskReporter",
14
- "TaskProgress",
15
13
  "TaskReporter",
16
14
  ]
@@ -210,9 +210,14 @@ class TaskDispatch[T, R]:
210
210
  if self._pool is None:
211
211
  raise InitializationError("execution pool has not been initialized")
212
212
 
213
- futures.append(self._pool.submit(self._worker, envelope))
214
- if len(futures) >= self.max_workers * 2:
213
+ # 等待在途任务数低于水位线
214
+ while True:
215
+ # 清理已完成的任务
215
216
  futures = [f for f in futures if not f.done()]
217
+ if len(futures) < self.max_workers:
218
+ break
219
+ time.sleep(0.001) # 简短让出
220
+ futures.append(self._pool.submit(self._worker, envelope))
216
221
 
217
222
  # 等待当前批次的所有任务完成
218
223
  for future in futures:
@@ -2,9 +2,13 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  from threading import Lock
5
+ from typing import TYPE_CHECKING
5
6
 
6
7
  from .util_types import SumCounter, ValueWrapper
7
8
 
9
+ if TYPE_CHECKING:
10
+ from ..observability import BaseObserver
11
+
8
12
 
9
13
  class TaskMetrics:
10
14
  """
@@ -35,6 +39,7 @@ class TaskMetrics:
35
39
  """
36
40
  self.enable_duplicate_check = enable_duplicate_check
37
41
  self.retry_exceptions = ()
42
+ self._observers: list[BaseObserver] = []
38
43
 
39
44
  self.lock = Lock()
40
45
  self._init_counter()
@@ -51,6 +56,7 @@ class TaskMetrics:
51
56
  self.error_counter = ValueWrapper(value=0, lock=self.lock)
52
57
  self.duplicate_counter = ValueWrapper(value=0, lock=self.lock)
53
58
 
59
+ # ==== 重置 ====
54
60
  def reset_counter(self) -> None:
55
61
  """
56
62
  重置计数器
@@ -69,6 +75,23 @@ class TaskMetrics:
69
75
  """
70
76
  self.processed_set = set() # task_hash
71
77
 
78
+ # ==== 观察者 ====
79
+ def add_observer(self, observer: BaseObserver) -> None:
80
+ """
81
+ 注册观察者。
82
+
83
+ :param observer: 要注册的观察者实例
84
+ """
85
+ self._observers.append(observer)
86
+
87
+ def remove_observer(self, observer: BaseObserver) -> None:
88
+ """
89
+ 移除观察者。
90
+
91
+ :param observer: 要移除的观察者实例
92
+ """
93
+ self._observers.remove(observer)
94
+
72
95
  # ==== 去重 ====
73
96
  def is_duplicate(self, task_hash: bytes) -> bool:
74
97
  """
@@ -125,6 +148,8 @@ class TaskMetrics:
125
148
  :param add_count: 增加的任务数
126
149
  """
127
150
  self.task_counter.add(add_count)
151
+ for observer in self._observers:
152
+ observer.on_tasks_added(add_count)
128
153
 
129
154
  def add_success_count(self, count: int = 1) -> None:
130
155
  """
@@ -135,8 +160,10 @@ class TaskMetrics:
135
160
  :param count: 增加的成功任务数量,默认值为 1。
136
161
  """
137
162
  self.success_counter.add(count)
163
+ for observer in self._observers:
164
+ observer.on_task_success(count)
138
165
 
139
- def add_error_count(self, count: int = 1) -> None:
166
+ def add_fail_count(self, count: int = 1) -> None:
140
167
  """
141
168
  更新失败任务计数器
142
169
 
@@ -145,6 +172,8 @@ class TaskMetrics:
145
172
  :param count: 增加的失败任务数量,默认值为 1。
146
173
  """
147
174
  self.error_counter.add(count)
175
+ for observer in self._observers:
176
+ observer.on_task_fail(count)
148
177
 
149
178
  def add_duplicate_count(self, count: int = 1) -> None:
150
179
  """
@@ -155,6 +184,17 @@ class TaskMetrics:
155
184
  :param count: 增加的重复任务数量,默认值为 1。
156
185
  """
157
186
  self.duplicate_counter.add(count)
187
+ for observer in self._observers:
188
+ observer.on_task_duplicate(count)
189
+
190
+ # ==== 启动与结束 ====
191
+ def on_start(self, _name: str, _total: int) -> None:
192
+ for observer in self._observers:
193
+ observer.on_start(_name, _total)
194
+
195
+ def on_finish(self) -> None:
196
+ for observer in self._observers:
197
+ observer.on_finish()
158
198
 
159
199
  # ==== 查询 ====
160
200
  def is_tasks_finished(self) -> bool:
@@ -1,12 +1,11 @@
1
1
  # runtime/core_queue.py
2
2
  from __future__ import annotations
3
3
 
4
- from queue import Empty
4
+ from queue import Empty, Queue
5
5
  from typing import Any
6
6
 
7
7
  from .core_envelope import TaskEnvelope
8
8
  from .util_errors import (
9
- ConfigurationError,
10
9
  DuplicateNodeError,
11
10
  TerminationMergeError,
12
11
  UnknownNodeError,
@@ -18,29 +17,27 @@ from .util_types import TerminationIdPool, TerminationSignal
18
17
  class TaskInQueue[T]:
19
18
  """任务输入队列,聚合多个上游来源的任务和终止信号。"""
20
19
 
20
+ out_name: str
21
21
  queue: Any
22
22
  source_names: list[str]
23
- out_name: str
24
23
  termination_dict: dict[str, int]
25
24
 
26
25
  # ==== 初始化 ====
27
26
  def __init__(
28
27
  self,
29
- queue: Any,
30
- source_names: list[str],
31
28
  out_name: str,
29
+ maxsize: int = 0,
32
30
  ) -> None:
33
31
  """
34
32
  初始化任务入队
35
33
 
36
- :param queue: 队列对象
37
- :param source_names: 上游节点名称列表
38
34
  :param out_name: 当前节点唯一名称
35
+ :param maxsize: 队列最大容量,默认为 0(无限制)
39
36
  """
40
- self.queue = queue
41
- self.source_names = source_names
42
37
  self.out_name = out_name
38
+ self.queue = Queue(maxsize=maxsize)
43
39
 
40
+ self.source_names = []
44
41
  self.termination_dict = {}
45
42
 
46
43
  # ==== 添加 ====
@@ -181,36 +178,26 @@ class TaskInQueue[T]:
181
178
  class TaskOutQueue[T]:
182
179
  """任务输出队列,将任务广播到一个或多个下游队列通道。"""
183
180
 
181
+ in_name: str
184
182
  queue_list: list[Any]
185
183
  target_names: list[str]
186
- in_name: str
187
184
  _name_to_idx: dict[str, int]
188
185
 
189
186
  # ==== 初始化 ====
190
187
  def __init__(
191
188
  self,
192
- queue_list: list[Any],
193
- target_names: list[str],
194
189
  in_name: str,
195
190
  ) -> None:
196
191
  """
197
192
  任务输出队列类,用于管理多个输出队列
198
193
 
199
- :param queue_list: 输出队列列表,每个元素为一个线程队列或异步队列
200
- :param target_names: 下游节点名称列表,用于标识每个队列
201
194
  :param in_name: 当前节点唯一名称,用于记录日志
202
- :raises ConfigurationError: 如果队列列表和目标名称列表长度不一致
203
195
  """
204
- if len(queue_list) != len(target_names):
205
- raise ConfigurationError(
206
- "queue_list and target_names must have the same length"
207
- )
208
-
209
- self.queue_list = queue_list
210
- self.target_names = target_names
211
196
  self.in_name = in_name
212
197
 
213
- self._name_to_idx = {name: i for i, name in enumerate(target_names)}
198
+ self.queue_list = []
199
+ self.target_names = []
200
+ self._name_to_idx = {}
214
201
 
215
202
  # ==== put ====
216
203