fluty 0.1.1__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.
- fluty-0.1.1/LICENSE +20 -0
- fluty-0.1.1/PKG-INFO +91 -0
- fluty-0.1.1/README.md +67 -0
- fluty-0.1.1/pyproject.toml +43 -0
- fluty-0.1.1/setup.cfg +4 -0
- fluty-0.1.1/src/flownet/__init__.py +56 -0
- fluty-0.1.1/src/flownet/api/__init__.py +226 -0
- fluty-0.1.1/src/flownet/api/actor_method_ref.py +20 -0
- fluty-0.1.1/src/flownet/api/actor_ref.py +30 -0
- fluty-0.1.1/src/flownet/api/connected_streams.py +153 -0
- fluty-0.1.1/src/flownet/api/dataset.py +784 -0
- fluty-0.1.1/src/flownet/api/datastream.py +561 -0
- fluty-0.1.1/src/flownet/api/flow_exception_handlers.py +66 -0
- fluty-0.1.1/src/flownet/api/node.py +76 -0
- fluty-0.1.1/src/flownet/api/node_control.py +210 -0
- fluty-0.1.1/src/flownet/api/runtime.py +805 -0
- fluty-0.1.1/src/flownet/api/scheduler.py +147 -0
- fluty-0.1.1/src/flownet/api/services.py +77 -0
- fluty-0.1.1/src/flownet/api/stateless_op.py +75 -0
- fluty-0.1.1/src/flownet/api/tasks.py +311 -0
- fluty-0.1.1/src/flownet/api/topic_stream.py +208 -0
- fluty-0.1.1/src/flownet/cli.py +987 -0
- fluty-0.1.1/src/flownet/compiler/__init__.py +0 -0
- fluty-0.1.1/src/flownet/compiler/exception_scope.py +17 -0
- fluty-0.1.1/src/flownet/compiler/flow_context.py +18 -0
- fluty-0.1.1/src/flownet/compiler/flow_def.py +513 -0
- fluty-0.1.1/src/flownet/compiler/flowtask.py +161 -0
- fluty-0.1.1/src/flownet/compiler/transformation.py +75 -0
- fluty-0.1.1/src/flownet/compiler/v1_compile_facade.py +328 -0
- fluty-0.1.1/src/flownet/config.py +141 -0
- fluty-0.1.1/src/flownet/core/__init__.py +0 -0
- fluty-0.1.1/src/flownet/core/actor.py +60 -0
- fluty-0.1.1/src/flownet/core/exceptions.py +74 -0
- fluty-0.1.1/src/flownet/core/flow_program.py +80 -0
- fluty-0.1.1/src/flownet/core/lockfree.py +6 -0
- fluty-0.1.1/src/flownet/core/request.py +307 -0
- fluty-0.1.1/src/flownet/core/request_id.py +14 -0
- fluty-0.1.1/src/flownet/core/service_event.py +18 -0
- fluty-0.1.1/src/flownet/core/stateless.py +32 -0
- fluty-0.1.1/src/flownet/core/stream_event.py +56 -0
- fluty-0.1.1/src/flownet/core/types.py +14 -0
- fluty-0.1.1/src/flownet/diagnostics/__init__.py +4 -0
- fluty-0.1.1/src/flownet/diagnostics/loop_watcher.py +54 -0
- fluty-0.1.1/src/flownet/engine/__init__.py +36 -0
- fluty-0.1.1/src/flownet/engine/adapters/__init__.py +7 -0
- fluty-0.1.1/src/flownet/engine/adapters/runtime_adapter.py +296 -0
- fluty-0.1.1/src/flownet/engine/advancer.py +309 -0
- fluty-0.1.1/src/flownet/engine/context.py +48 -0
- fluty-0.1.1/src/flownet/engine/exception_resolver.py +156 -0
- fluty-0.1.1/src/flownet/engine/flow_engine.py +345 -0
- fluty-0.1.1/src/flownet/engine/meta_validation.py +118 -0
- fluty-0.1.1/src/flownet/engine/operator_handlers.py +19 -0
- fluty-0.1.1/src/flownet/engine/operator_registry.py +60 -0
- fluty-0.1.1/src/flownet/engine/operators/__init__.py +13 -0
- fluty-0.1.1/src/flownet/engine/operators/base.py +78 -0
- fluty-0.1.1/src/flownet/engine/operators/defaults.py +37 -0
- fluty-0.1.1/src/flownet/engine/operators/reducers/__init__.py +9 -0
- fluty-0.1.1/src/flownet/engine/operators/reducers/common.py +314 -0
- fluty-0.1.1/src/flownet/engine/operators/reducers/join_reducer.py +293 -0
- fluty-0.1.1/src/flownet/engine/operators/reducers/merge_reducer.py +258 -0
- fluty-0.1.1/src/flownet/engine/operators/reducers/reducer.py +424 -0
- fluty-0.1.1/src/flownet/engine/operators/router.py +114 -0
- fluty-0.1.1/src/flownet/engine/operators/shuffle.py +320 -0
- fluty-0.1.1/src/flownet/engine/operators/stateful_process.py +187 -0
- fluty-0.1.1/src/flownet/engine/operators/stateless.py +257 -0
- fluty-0.1.1/src/flownet/engine/port.py +57 -0
- fluty-0.1.1/src/flownet/engine/result_normalizer.py +39 -0
- fluty-0.1.1/src/flownet/engine/utils/__init__.py +16 -0
- fluty-0.1.1/src/flownet/engine/utils/flow_stack.py +72 -0
- fluty-0.1.1/src/flownet/lib/__init__.py +3 -0
- fluty-0.1.1/src/flownet/lib/data/__init__.py +66 -0
- fluty-0.1.1/src/flownet/lib/data/adapters/__init__.py +15 -0
- fluty-0.1.1/src/flownet/lib/data/adapters/sage_data_mapper.py +155 -0
- fluty-0.1.1/src/flownet/lib/data/connectors/__init__.py +27 -0
- fluty-0.1.1/src/flownet/lib/data/connectors/core.py +574 -0
- fluty-0.1.1/src/flownet/lib/data/contract_injection.py +49 -0
- fluty-0.1.1/src/flownet/lib/data/contracts.py +259 -0
- fluty-0.1.1/src/flownet/lib/data/manifest.py +56 -0
- fluty-0.1.1/src/flownet/lib/data/pipeline.py +1141 -0
- fluty-0.1.1/src/flownet/platform/__init__.py +9 -0
- fluty-0.1.1/src/flownet/platform/container_manager_actor.py +370 -0
- fluty-0.1.1/src/flownet/platform/node_runtime.py +36 -0
- fluty-0.1.1/src/flownet/platform/services/__init__.py +3 -0
- fluty-0.1.1/src/flownet/platform/services/container_event_stream.py +10 -0
- fluty-0.1.1/src/flownet/platform/start_container.py +128 -0
- fluty-0.1.1/src/flownet/platform/start_node_runtime.py +73 -0
- fluty-0.1.1/src/flownet/platform/user/__init__.py +17 -0
- fluty-0.1.1/src/flownet/platform/user/platform_client_actor.py +83 -0
- fluty-0.1.1/src/flownet/platform/user/startup.py +238 -0
- fluty-0.1.1/src/flownet/proactive/__init__.py +27 -0
- fluty-0.1.1/src/flownet/proactive/manager_actor.py +74 -0
- fluty-0.1.1/src/flownet/proactive/registry.py +458 -0
- fluty-0.1.1/src/flownet/runtime/__init__.py +17 -0
- fluty-0.1.1/src/flownet/runtime/actors/__init__.py +33 -0
- fluty-0.1.1/src/flownet/runtime/actors/dispatcher.py +75 -0
- fluty-0.1.1/src/flownet/runtime/actors/execution.py +68 -0
- fluty-0.1.1/src/flownet/runtime/actors/mailbox.py +123 -0
- fluty-0.1.1/src/flownet/runtime/actors/policy.py +85 -0
- fluty-0.1.1/src/flownet/runtime/actors/registry.py +75 -0
- fluty-0.1.1/src/flownet/runtime/cluster_gossip_protocol.py +238 -0
- fluty-0.1.1/src/flownet/runtime/cluster_gossip_service.py +416 -0
- fluty-0.1.1/src/flownet/runtime/cluster_view.py +744 -0
- fluty-0.1.1/src/flownet/runtime/contexts/__init__.py +59 -0
- fluty-0.1.1/src/flownet/runtime/contexts/actor.py +109 -0
- fluty-0.1.1/src/flownet/runtime/contexts/flow.py +101 -0
- fluty-0.1.1/src/flownet/runtime/contexts/source.py +120 -0
- fluty-0.1.1/src/flownet/runtime/contexts/system.py +531 -0
- fluty-0.1.1/src/flownet/runtime/flows/__init__.py +75 -0
- fluty-0.1.1/src/flownet/runtime/flows/connectors.py +118 -0
- fluty-0.1.1/src/flownet/runtime/flows/control_output.py +114 -0
- fluty-0.1.1/src/flownet/runtime/flows/ordered_event_channel.py +431 -0
- fluty-0.1.1/src/flownet/runtime/flows/output_channel.py +604 -0
- fluty-0.1.1/src/flownet/runtime/flows/program_catalog.py +194 -0
- fluty-0.1.1/src/flownet/runtime/flows/replay_checkpoint.py +135 -0
- fluty-0.1.1/src/flownet/runtime/flows/request_registry.py +55 -0
- fluty-0.1.1/src/flownet/runtime/flows/request_tracker.py +162 -0
- fluty-0.1.1/src/flownet/runtime/flows/run.py +431 -0
- fluty-0.1.1/src/flownet/runtime/flows/service.py +1003 -0
- fluty-0.1.1/src/flownet/runtime/flows/stream_run_tracker.py +159 -0
- fluty-0.1.1/src/flownet/runtime/flows/topic_output.py +358 -0
- fluty-0.1.1/src/flownet/runtime/kernel.py +669 -0
- fluty-0.1.1/src/flownet/runtime/loops.py +108 -0
- fluty-0.1.1/src/flownet/runtime/node_control.py +780 -0
- fluty-0.1.1/src/flownet/runtime/runner_lifecycle.py +104 -0
- fluty-0.1.1/src/flownet/runtime/runtime.py +1235 -0
- fluty-0.1.1/src/flownet/runtime/scheduler_hook.py +945 -0
- fluty-0.1.1/src/flownet/runtime/sources/__init__.py +17 -0
- fluty-0.1.1/src/flownet/runtime/sources/stream_sources.py +291 -0
- fluty-0.1.1/src/flownet/runtime/state/__init__.py +25 -0
- fluty-0.1.1/src/flownet/runtime/state/backend.py +47 -0
- fluty-0.1.1/src/flownet/runtime/state/codec.py +54 -0
- fluty-0.1.1/src/flownet/runtime/state/memory_backend.py +112 -0
- fluty-0.1.1/src/flownet/runtime/state/sqlite_backend.py +172 -0
- fluty-0.1.1/src/flownet/runtime/stateless_ops.py +187 -0
- fluty-0.1.1/src/flownet/runtime/topics/__init__.py +27 -0
- fluty-0.1.1/src/flownet/runtime/topics/flow_program_service.py +276 -0
- fluty-0.1.1/src/flownet/runtime/topics/topic_identity.py +66 -0
- fluty-0.1.1/src/flownet/runtime/topics/topic_registry.py +1438 -0
- fluty-0.1.1/src/flownet/runtime/topics/topic_router.py +46 -0
- fluty-0.1.1/src/flownet/runtime/transport/__init__.py +38 -0
- fluty-0.1.1/src/flownet/runtime/transport/call_manager.py +293 -0
- fluty-0.1.1/src/flownet/runtime/transport/network_interface.py +10 -0
- fluty-0.1.1/src/flownet/runtime/transport/packet_transport.py +32 -0
- fluty-0.1.1/src/flownet/runtime/transport/runtime_protocol.py +436 -0
- fluty-0.1.1/src/flownet/runtime/transport/shm_transport.py +182 -0
- fluty-0.1.1/src/flownet/runtime/transport/tcp_transport.py +132 -0
- fluty-0.1.1/src/flownet/runtime/transport/transport_hub.py +457 -0
- fluty-0.1.1/src/flownet/runtime/transport/transport_selector.py +227 -0
- fluty-0.1.1/src/flownet/runtime/transport/uds_transport.py +145 -0
- fluty-0.1.1/src/flownet/testing/__init__.py +3 -0
- fluty-0.1.1/src/flownet/testing/chaos_harness.py +57 -0
- fluty-0.1.1/src/flownet/utils/__init__.py +0 -0
- fluty-0.1.1/src/flownet/utils/async_tools.py +98 -0
- fluty-0.1.1/src/flownet/utils/context_vars.py +51 -0
- fluty-0.1.1/src/flownet/utils/custom_formatter.py +55 -0
- fluty-0.1.1/src/flownet/utils/custom_logger.py +174 -0
- fluty-0.1.1/src/flownet/v1/__init__.py +44 -0
- fluty-0.1.1/src/flownet/v1/api/__init__.py +29 -0
- fluty-0.1.1/src/flownet/v1/api/declarations.py +83 -0
- fluty-0.1.1/src/flownet/v1/api/decorators.py +423 -0
- fluty-0.1.1/src/flownet/v1/api/flow_exception_handlers.py +8 -0
- fluty-0.1.1/src/flownet/v1/client/__init__.py +10 -0
- fluty-0.1.1/src/flownet/v1/client/handles.py +56 -0
- fluty-0.1.1/src/flownet/v1/client/registries.py +163 -0
- fluty-0.1.1/src/flownet/v1/client/runtime_client.py +159 -0
- fluty-0.1.1/src/flownet/v1/compiler/__init__.py +8 -0
- fluty-0.1.1/src/flownet/v1/compiler/errors.py +15 -0
- fluty-0.1.1/src/flownet/v1/compiler/exception_scope.py +77 -0
- fluty-0.1.1/src/flownet/v1/compiler/flow_compiler.py +53 -0
- fluty-0.1.1/src/flownet/v1/compiler/streams.py +633 -0
- fluty-0.1.1/src/flownet/v1/compiler/targets.py +98 -0
- fluty-0.1.1/src/flownet/v1/compiler/transformation.py +76 -0
- fluty-0.1.1/src/flownet/v1/core/__init__.py +5 -0
- fluty-0.1.1/src/flownet/v1/core/flow_program.py +180 -0
- fluty-0.1.1/src/flownet/v1/runtime/__init__.py +227 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/__init__.py +108 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/actor_api.py +237 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/callback_handle.py +73 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/callback_registry.py +437 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/comm_bridge.py +87 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/error_codes.py +30 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/event_emitter.py +216 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/executor_lanes.py +210 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/invoker.py +213 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/registry.py +155 -0
- fluty-0.1.1/src/flownet/v1/runtime/actors/task_runtime.py +231 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/__init__.py +75 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/hub.py +197 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/loopback.py +108 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/protocol.py +406 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/reply_tracker.py +74 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/router.py +95 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/transport.py +29 -0
- fluty-0.1.1/src/flownet/v1/runtime/comm/v0_transport_hub_adapter.py +189 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/__init__.py +131 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/cursor_codec.py +263 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/cursor_guards.py +80 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/cursor_models.py +49 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/engine.py +141 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/exception_decision.py +84 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/exception_runner.py +131 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/flow_process_execution.py +454 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/operator_executor.py +405 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/operator_runtime.py +1788 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/program_cache.py +74 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/program_comm_bridge.py +198 -0
- fluty-0.1.1/src/flownet/v1/runtime/flowengine/scope_resolver.py +179 -0
- fluty-0.1.1/src/flownet/v1/runtime/loops.py +78 -0
- fluty-0.1.1/src/flownet/v1/runtime/runtime.py +438 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/__init__.py +55 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/comm_bridge.py +142 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/control_dispatch.py +140 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/coordinator_registry.py +137 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/event_dispatch.py +84 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/event_group_ledger.py +192 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/exception_invoker.py +107 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/flow_process_catalog.py +71 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/normalization.py +79 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/routing_directory.py +177 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/subscriber_progress.py +160 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/subscriber_registry.py +102 -0
- fluty-0.1.1/src/flownet/v1/runtime/topics/topic_api.py +957 -0
- fluty-0.1.1/src/fluty.egg-info/PKG-INFO +91 -0
- fluty-0.1.1/src/fluty.egg-info/SOURCES.txt +226 -0
- fluty-0.1.1/src/fluty.egg-info/dependency_links.txt +1 -0
- fluty-0.1.1/src/fluty.egg-info/entry_points.txt +2 -0
- fluty-0.1.1/src/fluty.egg-info/requires.txt +14 -0
- fluty-0.1.1/src/fluty.egg-info/top_level.txt +1 -0
fluty-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2024-2026 Jingyuan Tian. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Except for the excluded lab-owned directories listed below, this repository
|
|
4
|
+
is an individually authored work by Jingyuan Tian and is proprietary and
|
|
5
|
+
confidential.
|
|
6
|
+
|
|
7
|
+
This notice does not apply to lab-owned projects copied into this repository,
|
|
8
|
+
including:
|
|
9
|
+
- `applications/SAGE`
|
|
10
|
+
- `applications/sage-studio`
|
|
11
|
+
- `applications/sageData`
|
|
12
|
+
|
|
13
|
+
No permission is granted to use, copy, modify, merge, publish, distribute,
|
|
14
|
+
sublicense, or sell this Software, in whole or in part, in source or binary
|
|
15
|
+
form, except with prior written permission from the copyright holder.
|
|
16
|
+
|
|
17
|
+
Unauthorized use, disclosure, reproduction, or distribution is strictly
|
|
18
|
+
prohibited.
|
|
19
|
+
|
|
20
|
+
For licensing requests, contact: jingyuantian@hust.edu.cn
|
fluty-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fluty
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Flownet: A distributed dataflow orchestration system.
|
|
5
|
+
Author-email: Flecther Tian <jingyuan_tian@hust.edu.cn>, SAGE Team <shuhao_zhang@hust.edu.cn>
|
|
6
|
+
License: Proprietary - All Rights Reserved
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: cloudpickle>=2.2
|
|
11
|
+
Requires-Dist: aiohttp
|
|
12
|
+
Requires-Dist: pyyaml
|
|
13
|
+
Requires-Dist: grpcio
|
|
14
|
+
Requires-Dist: rich
|
|
15
|
+
Requires-Dist: fastapi
|
|
16
|
+
Requires-Dist: uvicorn[standard]
|
|
17
|
+
Requires-Dist: pydantic
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest; extra == "dev"
|
|
20
|
+
Requires-Dist: black; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy; extra == "dev"
|
|
22
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# SAGE-Flownet
|
|
29
|
+
|
|
30
|
+
**SAGE-Flownet** 是一个轻量、原生 Python 的动态数据流执行引擎。它以“嵌套动态图”为核心模型,把用户写下的普通 Python 函数编译为可执行的 FlowTask DAG,并由运行时按需调度执行,让复杂的工作流像调用函数一样自然。
|
|
31
|
+
|
|
32
|
+
它不是另一个固定模板的流水线框架。Flownet 将远程调用、闭包、回调以及子图嵌套视为**一等公民**,在不牺牲 Python 语义的前提下,支持灵活组合和横向扩展。
|
|
33
|
+
|
|
34
|
+
## 安装与使用
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install isage-flownet
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
> **⚠️ PyPI 包名 vs. import 名**
|
|
41
|
+
>
|
|
42
|
+
> SAGE 生态约定:PyPI 包名使用 `isage-` 前缀(因为 `sage` 在 PyPI 已被占用),
|
|
43
|
+
> 但 Python **import 名**使用 `sage.*` 命名空间。
|
|
44
|
+
>
|
|
45
|
+
> | 操作 | 命令 |
|
|
46
|
+
> |------|------|
|
|
47
|
+
> | 安装 | `pip install isage-flownet` |
|
|
48
|
+
> | import | `from flownet import flow, init` |
|
|
49
|
+
>
|
|
50
|
+
> `import isage_flownet` **不存在**,请始终使用 `flownet`。
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from flownet import flow, init, create_actor
|
|
54
|
+
|
|
55
|
+
@flow
|
|
56
|
+
def my_pipeline(init_stream):
|
|
57
|
+
return init_stream.map(lambda x: x * 2)
|
|
58
|
+
|
|
59
|
+
init() # 启动运行时
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## ✧ 项目如何工作(概述)
|
|
63
|
+
|
|
64
|
+
* **Flow 定义与编译**:通过 `@flow` 装饰器将函数包装为 Flow 定义(`FlowDef`),编译为包含 Transformation 的 FlowTask 图。
|
|
65
|
+
* **数据流建模**:`DataStream.map/flatmap` 等算子创建上下游关系,形成可追踪的依赖图和执行边。
|
|
66
|
+
* **运行时执行**:`FlownetRuntime` 负责处理请求栈(TransformationFrame),并由 operator handler 决定目标调用与转发策略。
|
|
67
|
+
* **Actor 调用统一化**:`ActorRef` / `ActorMethodRef` 将本地与远程调用统一抽象,运行时根据目标地址完成派发。
|
|
68
|
+
* **FlowRun 输出通道**:运行时通过 `FlowRunRef` 的输出通道暴露“写入输入—等待输出”的调用方式,负责 fork/join 逻辑与结果收集。
|
|
69
|
+
|
|
70
|
+
## ✧ 预期目标与效果
|
|
71
|
+
|
|
72
|
+
* **保持原生 Python 开发体验**:无需额外 DSL,工作流像写函数一样简单。
|
|
73
|
+
* **支持动态与嵌套的复杂流程**:运行时编译、依赖跟踪与延迟执行适配不确定结构。
|
|
74
|
+
* **可扩展的分布式执行**:为本地/远程统一执行提供清晰路径,便于水平扩展。
|
|
75
|
+
* **更可靠的并发与结果聚合**:由运行时完成 fork/join、收集与异常处理,降低业务代码复杂度。
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## Intellectual Property
|
|
79
|
+
|
|
80
|
+
`All Rights Reserved` applies to repository contents authored by Jingyuan Tian,
|
|
81
|
+
including code, documentation, benchmarks, and related assets.
|
|
82
|
+
|
|
83
|
+
The following copied lab projects are excluded from this claim and retain their
|
|
84
|
+
original ownership/license context: `applications/SAGE`, `applications/sage-studio`,
|
|
85
|
+
`applications/sageData`.
|
|
86
|
+
|
|
87
|
+
1. License terms: `LICENSE`
|
|
88
|
+
2. Ownership details: `COPYRIGHT.md`
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
---
|
fluty-0.1.1/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
---
|
|
3
|
+
|
|
4
|
+
# SAGE-Flownet
|
|
5
|
+
|
|
6
|
+
**SAGE-Flownet** 是一个轻量、原生 Python 的动态数据流执行引擎。它以“嵌套动态图”为核心模型,把用户写下的普通 Python 函数编译为可执行的 FlowTask DAG,并由运行时按需调度执行,让复杂的工作流像调用函数一样自然。
|
|
7
|
+
|
|
8
|
+
它不是另一个固定模板的流水线框架。Flownet 将远程调用、闭包、回调以及子图嵌套视为**一等公民**,在不牺牲 Python 语义的前提下,支持灵活组合和横向扩展。
|
|
9
|
+
|
|
10
|
+
## 安装与使用
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install isage-flownet
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
> **⚠️ PyPI 包名 vs. import 名**
|
|
17
|
+
>
|
|
18
|
+
> SAGE 生态约定:PyPI 包名使用 `isage-` 前缀(因为 `sage` 在 PyPI 已被占用),
|
|
19
|
+
> 但 Python **import 名**使用 `sage.*` 命名空间。
|
|
20
|
+
>
|
|
21
|
+
> | 操作 | 命令 |
|
|
22
|
+
> |------|------|
|
|
23
|
+
> | 安装 | `pip install isage-flownet` |
|
|
24
|
+
> | import | `from flownet import flow, init` |
|
|
25
|
+
>
|
|
26
|
+
> `import isage_flownet` **不存在**,请始终使用 `flownet`。
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from flownet import flow, init, create_actor
|
|
30
|
+
|
|
31
|
+
@flow
|
|
32
|
+
def my_pipeline(init_stream):
|
|
33
|
+
return init_stream.map(lambda x: x * 2)
|
|
34
|
+
|
|
35
|
+
init() # 启动运行时
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## ✧ 项目如何工作(概述)
|
|
39
|
+
|
|
40
|
+
* **Flow 定义与编译**:通过 `@flow` 装饰器将函数包装为 Flow 定义(`FlowDef`),编译为包含 Transformation 的 FlowTask 图。
|
|
41
|
+
* **数据流建模**:`DataStream.map/flatmap` 等算子创建上下游关系,形成可追踪的依赖图和执行边。
|
|
42
|
+
* **运行时执行**:`FlownetRuntime` 负责处理请求栈(TransformationFrame),并由 operator handler 决定目标调用与转发策略。
|
|
43
|
+
* **Actor 调用统一化**:`ActorRef` / `ActorMethodRef` 将本地与远程调用统一抽象,运行时根据目标地址完成派发。
|
|
44
|
+
* **FlowRun 输出通道**:运行时通过 `FlowRunRef` 的输出通道暴露“写入输入—等待输出”的调用方式,负责 fork/join 逻辑与结果收集。
|
|
45
|
+
|
|
46
|
+
## ✧ 预期目标与效果
|
|
47
|
+
|
|
48
|
+
* **保持原生 Python 开发体验**:无需额外 DSL,工作流像写函数一样简单。
|
|
49
|
+
* **支持动态与嵌套的复杂流程**:运行时编译、依赖跟踪与延迟执行适配不确定结构。
|
|
50
|
+
* **可扩展的分布式执行**:为本地/远程统一执行提供清晰路径,便于水平扩展。
|
|
51
|
+
* **更可靠的并发与结果聚合**:由运行时完成 fork/join、收集与异常处理,降低业务代码复杂度。
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Intellectual Property
|
|
55
|
+
|
|
56
|
+
`All Rights Reserved` applies to repository contents authored by Jingyuan Tian,
|
|
57
|
+
including code, documentation, benchmarks, and related assets.
|
|
58
|
+
|
|
59
|
+
The following copied lab projects are excluded from this claim and retain their
|
|
60
|
+
original ownership/license context: `applications/SAGE`, `applications/sage-studio`,
|
|
61
|
+
`applications/sageData`.
|
|
62
|
+
|
|
63
|
+
1. License terms: `LICENSE`
|
|
64
|
+
2. Ownership details: `COPYRIGHT.md`
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
---
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fluty"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Flownet: A distributed dataflow orchestration system."
|
|
9
|
+
authors = [{ name = "Flecther Tian", email = "jingyuan_tian@hust.edu.cn" }, { name = "SAGE Team", email = "shuhao_zhang@hust.edu.cn" }]
|
|
10
|
+
license = { text = "Proprietary - All Rights Reserved" }
|
|
11
|
+
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"cloudpickle>=2.2",
|
|
16
|
+
"aiohttp",
|
|
17
|
+
"pyyaml",
|
|
18
|
+
"grpcio",
|
|
19
|
+
"rich",
|
|
20
|
+
# 还有你分布式 actor 或 pipeline 用到的依赖
|
|
21
|
+
"fastapi",
|
|
22
|
+
"uvicorn[standard]",
|
|
23
|
+
"pydantic"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
dev = [
|
|
28
|
+
"pytest",
|
|
29
|
+
"black",
|
|
30
|
+
"mypy",
|
|
31
|
+
"pre-commit"
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
flownet = "flownet.cli:main"
|
|
36
|
+
|
|
37
|
+
# Package discovery (PEP 420 namespace)
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
where = ["src"]
|
|
40
|
+
namespaces = true
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
fluty-0.1.1/setup.cfg
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from flownet.api import (
|
|
2
|
+
flow,
|
|
3
|
+
init,
|
|
4
|
+
init_user,
|
|
5
|
+
create_actor,
|
|
6
|
+
create_local_actor,
|
|
7
|
+
flow_program_ref,
|
|
8
|
+
register_flow_program,
|
|
9
|
+
list_flow_programs,
|
|
10
|
+
get_flow_program,
|
|
11
|
+
delete_flow_program,
|
|
12
|
+
submit_flow_program,
|
|
13
|
+
stateless,
|
|
14
|
+
stateless_op,
|
|
15
|
+
exception_handler,
|
|
16
|
+
flow_exception_handler,
|
|
17
|
+
Dataset,
|
|
18
|
+
DatasetExecutionMetrics,
|
|
19
|
+
DatasetWriteResult,
|
|
20
|
+
SINK_IDEMPOTENCY_META_FIELD,
|
|
21
|
+
read_rows,
|
|
22
|
+
read_parquet,
|
|
23
|
+
read_images,
|
|
24
|
+
read_tfrecords,
|
|
25
|
+
)
|
|
26
|
+
from flownet.runtime.runtime import configure_runtime
|
|
27
|
+
__all__ = [
|
|
28
|
+
"flow",
|
|
29
|
+
"init",
|
|
30
|
+
"init_user",
|
|
31
|
+
"create_actor",
|
|
32
|
+
"create_local_actor",
|
|
33
|
+
"flow_program_ref",
|
|
34
|
+
"register_flow_program",
|
|
35
|
+
"list_flow_programs",
|
|
36
|
+
"get_flow_program",
|
|
37
|
+
"delete_flow_program",
|
|
38
|
+
"submit_flow_program",
|
|
39
|
+
"stateless",
|
|
40
|
+
"stateless_op",
|
|
41
|
+
"exception_handler",
|
|
42
|
+
"flow_exception_handler",
|
|
43
|
+
"configure_runtime",
|
|
44
|
+
"Dataset",
|
|
45
|
+
"DatasetExecutionMetrics",
|
|
46
|
+
"DatasetWriteResult",
|
|
47
|
+
"SINK_IDEMPOTENCY_META_FIELD",
|
|
48
|
+
"read_rows",
|
|
49
|
+
"read_parquet",
|
|
50
|
+
"read_images",
|
|
51
|
+
"read_tfrecords",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# 名字待定,叫做flownet,或者soda(stack-objective distributed architecture)
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# DOCS_REF:
|
|
2
|
+
# - docs/user/03-programming-model.md
|
|
3
|
+
# - docs/user/reference/api-surface.md
|
|
4
|
+
# - docs/user/cookbook/flow-pipeline-patterns.md
|
|
5
|
+
# DOCS_SYNC:
|
|
6
|
+
# - If exported API names or flow decorator behavior changes, update the
|
|
7
|
+
# referenced docs and examples/docs/ snippets that import from flownet.api.
|
|
8
|
+
|
|
9
|
+
from dataclasses import replace
|
|
10
|
+
|
|
11
|
+
from flownet.api.flow_exception_handlers import (
|
|
12
|
+
flow_exception_handler,
|
|
13
|
+
exception_handler,
|
|
14
|
+
)
|
|
15
|
+
from flownet.core.lockfree import lockfree
|
|
16
|
+
from flownet.api.topic_stream import topic_stream, TopicStream, from_topic, from_service
|
|
17
|
+
from flownet.api.stateless_op import stateless, stateless_op, StatelessOpRef, StatelessOpConfig, StatelessScope
|
|
18
|
+
from flownet.api.services import (
|
|
19
|
+
get_services,
|
|
20
|
+
try_get_services,
|
|
21
|
+
start_service,
|
|
22
|
+
publish_service,
|
|
23
|
+
stop_service,
|
|
24
|
+
list_services,
|
|
25
|
+
start_source,
|
|
26
|
+
publish_topic,
|
|
27
|
+
stop_source,
|
|
28
|
+
list_sources,
|
|
29
|
+
)
|
|
30
|
+
from flownet.api import services as services
|
|
31
|
+
from flownet.api import tasks as tasks
|
|
32
|
+
from flownet.api import node as node
|
|
33
|
+
from flownet.api import node_control as node_control
|
|
34
|
+
from flownet.api import scheduler as scheduler
|
|
35
|
+
|
|
36
|
+
from flownet.api.runtime import (
|
|
37
|
+
create_actor,
|
|
38
|
+
create_local_actor,
|
|
39
|
+
list_runtime_topics,
|
|
40
|
+
list_runtime_actors,
|
|
41
|
+
list_runtime_nodes,
|
|
42
|
+
flow_program_ref,
|
|
43
|
+
register_flow_program,
|
|
44
|
+
list_flow_programs,
|
|
45
|
+
get_flow_program,
|
|
46
|
+
delete_flow_program,
|
|
47
|
+
submit_flow_program,
|
|
48
|
+
)
|
|
49
|
+
from flownet.api import runtime as runtime
|
|
50
|
+
from flownet.runtime.runtime import configure_runtime
|
|
51
|
+
from flownet.config import FlownetConfig, RuntimeConfigInput, coerce_flownet_config
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# TODO: 里边加一个decorator,然后把func参数放到decorator里边去
|
|
55
|
+
# flow decorator
|
|
56
|
+
def flow(func):
|
|
57
|
+
from flownet.compiler.flow_def import FlowDef
|
|
58
|
+
return FlowDef(func, static = True)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
from flownet.api.dataset import (
|
|
62
|
+
Dataset,
|
|
63
|
+
DatasetExecutionMetrics,
|
|
64
|
+
DatasetWriteResult,
|
|
65
|
+
SINK_IDEMPOTENCY_META_FIELD,
|
|
66
|
+
read_rows,
|
|
67
|
+
read_parquet,
|
|
68
|
+
read_images,
|
|
69
|
+
read_tfrecords,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# api里边要能给concurrency hints
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _init_with_boot_policy(
|
|
76
|
+
config: RuntimeConfigInput | None = None,
|
|
77
|
+
*,
|
|
78
|
+
node_mode: str | None = None,
|
|
79
|
+
node_address: str | None = None,
|
|
80
|
+
node_id: str | None = None,
|
|
81
|
+
node_threads: int | None = None,
|
|
82
|
+
connect_timeout: float | None = None,
|
|
83
|
+
):
|
|
84
|
+
if config is not None:
|
|
85
|
+
configure_runtime(config)
|
|
86
|
+
|
|
87
|
+
from flownet.platform.user.startup import boot_user_runtime
|
|
88
|
+
|
|
89
|
+
return boot_user_runtime(
|
|
90
|
+
node_mode=node_mode,
|
|
91
|
+
node_address=node_address,
|
|
92
|
+
node_id=node_id,
|
|
93
|
+
node_threads=node_threads,
|
|
94
|
+
connect_timeout=connect_timeout,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
_DEFAULT_NODE_PORT = 8787
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _normalize_node_address(node: str | None) -> str | None:
|
|
102
|
+
if node is None:
|
|
103
|
+
return None
|
|
104
|
+
normalized = node.strip()
|
|
105
|
+
if not normalized:
|
|
106
|
+
raise ValueError("node address must not be empty.")
|
|
107
|
+
if ":" in normalized:
|
|
108
|
+
return normalized
|
|
109
|
+
return f"{normalized}:{_DEFAULT_NODE_PORT}"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _coerce_user_runtime_config(config: RuntimeConfigInput | None) -> FlownetConfig:
|
|
113
|
+
if config is None:
|
|
114
|
+
from flownet.runtime import runtime as runtime_module
|
|
115
|
+
resolved = coerce_flownet_config(runtime_module._runtime_config)
|
|
116
|
+
else:
|
|
117
|
+
resolved = coerce_flownet_config(config)
|
|
118
|
+
if resolved.schedulable is False:
|
|
119
|
+
return resolved
|
|
120
|
+
return replace(resolved, schedulable=False)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def init(
|
|
124
|
+
config: RuntimeConfigInput | None = None,
|
|
125
|
+
*,
|
|
126
|
+
node_mode: str | None = None,
|
|
127
|
+
node_address: str | None = None,
|
|
128
|
+
node_id: str | None = None,
|
|
129
|
+
node_threads: int | None = None,
|
|
130
|
+
connect_timeout: float | None = None,
|
|
131
|
+
):
|
|
132
|
+
# Compatibility entrypoint:
|
|
133
|
+
# - preserves legacy behavior where startup mode defaults to env/default.
|
|
134
|
+
# - for cluster/user decoupled attach flow, prefer init_user(...).
|
|
135
|
+
return _init_with_boot_policy(
|
|
136
|
+
config,
|
|
137
|
+
node_mode=node_mode,
|
|
138
|
+
node_address=node_address,
|
|
139
|
+
node_id=node_id,
|
|
140
|
+
node_threads=node_threads,
|
|
141
|
+
connect_timeout=connect_timeout,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def init_user(
|
|
146
|
+
config: RuntimeConfigInput | None = None,
|
|
147
|
+
*,
|
|
148
|
+
node: str | None = None,
|
|
149
|
+
node_address: str | None = None,
|
|
150
|
+
node_id: str | None = None,
|
|
151
|
+
node_threads: int | None = None,
|
|
152
|
+
connect_timeout: float | None = None,
|
|
153
|
+
node_mode: str = "connect_only",
|
|
154
|
+
):
|
|
155
|
+
if node is not None and node_address is not None:
|
|
156
|
+
raise ValueError("Pass either `node` or `node_address`, not both.")
|
|
157
|
+
normalized_node_address = _normalize_node_address(
|
|
158
|
+
node if node is not None else node_address
|
|
159
|
+
)
|
|
160
|
+
user_runtime_config = _coerce_user_runtime_config(config)
|
|
161
|
+
# Decoupled user-runtime entrypoint:
|
|
162
|
+
# - defaults to connect_only so cluster/node lifecycle is managed externally.
|
|
163
|
+
# - user runtime is never a schedulable compute member in placement plans.
|
|
164
|
+
# - supports explicit mode override for migration/debug.
|
|
165
|
+
return _init_with_boot_policy(
|
|
166
|
+
user_runtime_config,
|
|
167
|
+
node_mode=node_mode,
|
|
168
|
+
node_address=normalized_node_address,
|
|
169
|
+
node_id=node_id,
|
|
170
|
+
node_threads=node_threads,
|
|
171
|
+
connect_timeout=connect_timeout,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
__all__ = [
|
|
175
|
+
"flow",
|
|
176
|
+
"init",
|
|
177
|
+
"init_user",
|
|
178
|
+
"create_actor",
|
|
179
|
+
"create_local_actor",
|
|
180
|
+
"list_runtime_topics",
|
|
181
|
+
"list_runtime_actors",
|
|
182
|
+
"list_runtime_nodes",
|
|
183
|
+
"flow_program_ref",
|
|
184
|
+
"register_flow_program",
|
|
185
|
+
"list_flow_programs",
|
|
186
|
+
"get_flow_program",
|
|
187
|
+
"delete_flow_program",
|
|
188
|
+
"submit_flow_program",
|
|
189
|
+
"exception_handler",
|
|
190
|
+
"flow_exception_handler",
|
|
191
|
+
"configure_runtime",
|
|
192
|
+
"lockfree",
|
|
193
|
+
"topic_stream",
|
|
194
|
+
"from_topic",
|
|
195
|
+
"from_service",
|
|
196
|
+
"TopicStream",
|
|
197
|
+
"services",
|
|
198
|
+
"tasks",
|
|
199
|
+
"node",
|
|
200
|
+
"node_control",
|
|
201
|
+
"scheduler",
|
|
202
|
+
"runtime",
|
|
203
|
+
"get_services",
|
|
204
|
+
"try_get_services",
|
|
205
|
+
"start_service",
|
|
206
|
+
"publish_service",
|
|
207
|
+
"stop_service",
|
|
208
|
+
"list_services",
|
|
209
|
+
"start_source",
|
|
210
|
+
"publish_topic",
|
|
211
|
+
"stop_source",
|
|
212
|
+
"list_sources",
|
|
213
|
+
"stateless",
|
|
214
|
+
"stateless_op",
|
|
215
|
+
"StatelessOpRef",
|
|
216
|
+
"StatelessOpConfig",
|
|
217
|
+
"StatelessScope",
|
|
218
|
+
"Dataset",
|
|
219
|
+
"DatasetExecutionMetrics",
|
|
220
|
+
"DatasetWriteResult",
|
|
221
|
+
"SINK_IDEMPOTENCY_META_FIELD",
|
|
222
|
+
"read_rows",
|
|
223
|
+
"read_parquet",
|
|
224
|
+
"read_images",
|
|
225
|
+
"read_tfrecords",
|
|
226
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# ARCH_NOTE:
|
|
4
|
+
# - ActorMethodRef is a concrete execution target (address + actor_id + method),
|
|
5
|
+
# not a logical alias.
|
|
6
|
+
# - This means flow topology currently captures materialized runtime bindings.
|
|
7
|
+
# - If we later add URI/logical-flow indirection, that resolution should happen
|
|
8
|
+
# before dispatch and still produce ActorMethodRef for execution.
|
|
9
|
+
class ActorMethodRef:
|
|
10
|
+
def __init__(self, address: str, actor_id: str, method: str):
|
|
11
|
+
self.address = address
|
|
12
|
+
self.actor_id = actor_id
|
|
13
|
+
self.method = method
|
|
14
|
+
|
|
15
|
+
def __call__(self, *args, **kwargs):
|
|
16
|
+
from flownet.api.runtime import handle_actor_call
|
|
17
|
+
return handle_actor_call(self, *args, **kwargs)
|
|
18
|
+
|
|
19
|
+
def __reduce__(self):
|
|
20
|
+
return (self.__class__, (self.address, self.actor_id, self.method))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Any, TYPE_CHECKING
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from flownet.api.actor_method_ref import ActorMethodRef
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ActorRef:
|
|
9
|
+
def __init__(self, address: str, actor_id: str):
|
|
10
|
+
self.address = address
|
|
11
|
+
self.actor_id = actor_id
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# TODO: 这里需要区分一下本地actor,并且对于本地actor,直接通过队列调用actor方法并返回结果
|
|
15
|
+
def __getattr__(self, name: str) -> 'ActorMethodRef':
|
|
16
|
+
from flownet.api.actor_method_ref import ActorMethodRef
|
|
17
|
+
return ActorMethodRef(address=self.address, actor_id=self.actor_id, method=name)
|
|
18
|
+
|
|
19
|
+
def __reduce__(self):
|
|
20
|
+
return (self.__class__, (self.address, self.actor_id))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ContainerRef(ActorRef):
|
|
24
|
+
def __init__(self, address: str):
|
|
25
|
+
super().__init__(address=address, actor_id="__container__")
|
|
26
|
+
|
|
27
|
+
def __getattr__(self, name):
|
|
28
|
+
from flownet.api.actor_method_ref import ActorMethodRef
|
|
29
|
+
print(f"[ContainerRef] Getting method {name} from container at {self.address}")
|
|
30
|
+
return ActorMethodRef(address=self.address, actor_id="__container__", method=name)
|