flwr 1.19.0__py3-none-any.whl → 1.21.0__py3-none-any.whl
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.
- flwr/__init__.py +4 -1
- flwr/app/__init__.py +28 -0
- flwr/app/exception.py +31 -0
- flwr/cli/auth_plugin/oidc_cli_plugin.py +4 -4
- flwr/cli/build.py +15 -5
- flwr/cli/cli_user_auth_interceptor.py +1 -1
- flwr/cli/config_utils.py +3 -3
- flwr/cli/constant.py +25 -8
- flwr/cli/log.py +9 -9
- flwr/cli/login/login.py +3 -3
- flwr/cli/ls.py +5 -5
- flwr/cli/new/new.py +23 -4
- flwr/cli/new/templates/app/README.flowertune.md.tpl +2 -0
- flwr/cli/new/templates/app/README.md.tpl +5 -0
- flwr/cli/new/templates/app/code/__init__.pytorch_msg_api.py.tpl +1 -0
- flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +80 -0
- flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +41 -0
- flwr/cli/new/templates/app/code/task.pytorch_msg_api.py.tpl +98 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +14 -3
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +13 -1
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +21 -2
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +18 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +19 -2
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +18 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +20 -3
- flwr/cli/new/templates/app/pyproject.pytorch_msg_api.toml.tpl +53 -0
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +18 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +18 -1
- flwr/cli/run/run.py +53 -50
- flwr/cli/stop.py +7 -4
- flwr/cli/utils.py +29 -11
- flwr/client/grpc_adapter_client/connection.py +11 -4
- flwr/client/grpc_rere_client/connection.py +93 -129
- flwr/client/rest_client/connection.py +134 -164
- flwr/clientapp/__init__.py +10 -0
- flwr/clientapp/mod/__init__.py +26 -0
- flwr/clientapp/mod/centraldp_mods.py +132 -0
- flwr/common/args.py +20 -6
- flwr/common/auth_plugin/__init__.py +4 -4
- flwr/common/auth_plugin/auth_plugin.py +7 -7
- flwr/common/constant.py +26 -5
- flwr/common/event_log_plugin/event_log_plugin.py +1 -1
- flwr/common/exit/__init__.py +4 -0
- flwr/common/exit/exit.py +8 -1
- flwr/common/exit/exit_code.py +42 -8
- flwr/common/exit/exit_handler.py +62 -0
- flwr/common/{exit_handlers.py → exit/signal_handler.py} +20 -37
- flwr/common/grpc.py +1 -1
- flwr/common/{inflatable_grpc_utils.py → inflatable_protobuf_utils.py} +52 -10
- flwr/common/inflatable_utils.py +191 -24
- flwr/common/logger.py +1 -1
- flwr/common/record/array.py +101 -22
- flwr/common/record/arraychunk.py +59 -0
- flwr/common/retry_invoker.py +30 -11
- flwr/common/serde.py +0 -28
- flwr/common/telemetry.py +4 -0
- flwr/compat/client/app.py +14 -31
- flwr/compat/server/app.py +2 -2
- flwr/proto/appio_pb2.py +51 -0
- flwr/proto/appio_pb2.pyi +195 -0
- flwr/proto/appio_pb2_grpc.py +4 -0
- flwr/proto/appio_pb2_grpc.pyi +4 -0
- flwr/proto/clientappio_pb2.py +4 -19
- flwr/proto/clientappio_pb2.pyi +0 -125
- flwr/proto/clientappio_pb2_grpc.py +269 -29
- flwr/proto/clientappio_pb2_grpc.pyi +114 -21
- flwr/proto/control_pb2.py +62 -0
- flwr/proto/{exec_pb2_grpc.py → control_pb2_grpc.py} +54 -54
- flwr/proto/{exec_pb2_grpc.pyi → control_pb2_grpc.pyi} +28 -28
- flwr/proto/fleet_pb2.py +12 -20
- flwr/proto/fleet_pb2.pyi +6 -36
- flwr/proto/serverappio_pb2.py +8 -31
- flwr/proto/serverappio_pb2.pyi +0 -152
- flwr/proto/serverappio_pb2_grpc.py +107 -38
- flwr/proto/serverappio_pb2_grpc.pyi +47 -20
- flwr/proto/simulationio_pb2.py +4 -11
- flwr/proto/simulationio_pb2.pyi +0 -58
- flwr/proto/simulationio_pb2_grpc.py +129 -27
- flwr/proto/simulationio_pb2_grpc.pyi +52 -13
- flwr/server/app.py +130 -153
- flwr/server/fleet_event_log_interceptor.py +4 -0
- flwr/server/grid/grpc_grid.py +94 -54
- flwr/server/grid/inmemory_grid.py +1 -0
- flwr/server/serverapp/app.py +165 -144
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +8 -0
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -1
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -5
- flwr/server/superlink/fleet/message_handler/message_handler.py +10 -16
- flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -2
- flwr/server/superlink/fleet/vce/backend/raybackend.py +3 -1
- flwr/server/superlink/fleet/vce/vce_api.py +6 -6
- flwr/server/superlink/linkstate/in_memory_linkstate.py +34 -0
- flwr/server/superlink/linkstate/linkstate.py +2 -1
- flwr/server/superlink/linkstate/sqlite_linkstate.py +45 -0
- flwr/server/superlink/serverappio/serverappio_grpc.py +2 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +95 -48
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
- flwr/server/superlink/simulation/simulationio_servicer.py +98 -22
- flwr/server/superlink/utils.py +0 -35
- flwr/serverapp/__init__.py +12 -0
- flwr/serverapp/dp_fixed_clipping.py +352 -0
- flwr/serverapp/exception.py +38 -0
- flwr/serverapp/strategy/__init__.py +38 -0
- flwr/serverapp/strategy/dp_fixed_clipping.py +352 -0
- flwr/serverapp/strategy/fedadagrad.py +162 -0
- flwr/serverapp/strategy/fedadam.py +181 -0
- flwr/serverapp/strategy/fedavg.py +295 -0
- flwr/serverapp/strategy/fedopt.py +218 -0
- flwr/serverapp/strategy/fedyogi.py +173 -0
- flwr/serverapp/strategy/result.py +105 -0
- flwr/serverapp/strategy/strategy.py +285 -0
- flwr/serverapp/strategy/strategy_utils.py +251 -0
- flwr/serverapp/strategy/strategy_utils_tests.py +304 -0
- flwr/simulation/app.py +159 -154
- flwr/simulation/run_simulation.py +17 -0
- flwr/supercore/app_utils.py +58 -0
- flwr/supercore/cli/__init__.py +22 -0
- flwr/supercore/cli/flower_superexec.py +141 -0
- flwr/supercore/corestate/__init__.py +22 -0
- flwr/supercore/corestate/corestate.py +81 -0
- flwr/{server/superlink → supercore}/ffs/disk_ffs.py +1 -1
- flwr/supercore/grpc_health/__init__.py +25 -0
- flwr/supercore/grpc_health/health_server.py +53 -0
- flwr/supercore/grpc_health/simple_health_servicer.py +38 -0
- flwr/supercore/license_plugin/__init__.py +22 -0
- flwr/supercore/license_plugin/license_plugin.py +26 -0
- flwr/supercore/object_store/in_memory_object_store.py +31 -31
- flwr/supercore/object_store/object_store.py +20 -42
- flwr/supercore/object_store/utils.py +43 -0
- flwr/{superexec → supercore/superexec}/__init__.py +1 -1
- flwr/supercore/superexec/plugin/__init__.py +28 -0
- flwr/supercore/superexec/plugin/base_exec_plugin.py +53 -0
- flwr/supercore/superexec/plugin/clientapp_exec_plugin.py +28 -0
- flwr/supercore/superexec/plugin/exec_plugin.py +71 -0
- flwr/supercore/superexec/plugin/serverapp_exec_plugin.py +28 -0
- flwr/supercore/superexec/plugin/simulation_exec_plugin.py +28 -0
- flwr/supercore/superexec/run_superexec.py +185 -0
- flwr/supercore/utils.py +32 -0
- flwr/superlink/servicer/__init__.py +15 -0
- flwr/superlink/servicer/control/__init__.py +22 -0
- flwr/{superexec/exec_event_log_interceptor.py → superlink/servicer/control/control_event_log_interceptor.py} +9 -5
- flwr/{superexec/exec_grpc.py → superlink/servicer/control/control_grpc.py} +39 -28
- flwr/superlink/servicer/control/control_license_interceptor.py +82 -0
- flwr/{superexec/exec_servicer.py → superlink/servicer/control/control_servicer.py} +79 -31
- flwr/{superexec/exec_user_auth_interceptor.py → superlink/servicer/control/control_user_auth_interceptor.py} +18 -10
- flwr/supernode/cli/flower_supernode.py +3 -7
- flwr/supernode/cli/flwr_clientapp.py +20 -16
- flwr/supernode/nodestate/in_memory_nodestate.py +13 -4
- flwr/supernode/nodestate/nodestate.py +3 -44
- flwr/supernode/runtime/run_clientapp.py +129 -115
- flwr/supernode/servicer/clientappio/__init__.py +1 -3
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +217 -165
- flwr/supernode/start_client_internal.py +205 -148
- {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/METADATA +5 -3
- {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/RECORD +161 -117
- {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/entry_points.txt +1 -0
- flwr/common/inflatable_rest_utils.py +0 -99
- flwr/proto/exec_pb2.py +0 -62
- flwr/superexec/app.py +0 -45
- flwr/superexec/deployment.py +0 -192
- flwr/superexec/executor.py +0 -100
- flwr/superexec/simulation.py +0 -130
- /flwr/proto/{exec_pb2.pyi → control_pb2.pyi} +0 -0
- /flwr/{server/superlink → supercore}/ffs/__init__.py +0 -0
- /flwr/{server/superlink → supercore}/ffs/ffs.py +0 -0
- /flwr/{server/superlink → supercore}/ffs/ffs_factory.py +0 -0
- {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/WHEEL +0 -0
|
@@ -16,9 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import gc
|
|
19
|
-
import os
|
|
20
|
-
import threading
|
|
21
|
-
import time
|
|
22
19
|
from logging import DEBUG, ERROR, INFO
|
|
23
20
|
from typing import Optional
|
|
24
21
|
|
|
@@ -32,34 +29,46 @@ from flwr.common import Context, Message
|
|
|
32
29
|
from flwr.common.config import get_flwr_dir
|
|
33
30
|
from flwr.common.constant import ErrorCode
|
|
34
31
|
from flwr.common.grpc import create_channel, on_channel_state_change
|
|
32
|
+
from flwr.common.inflatable import (
|
|
33
|
+
get_all_nested_objects,
|
|
34
|
+
get_object_tree,
|
|
35
|
+
no_object_id_recompute,
|
|
36
|
+
)
|
|
37
|
+
from flwr.common.inflatable_protobuf_utils import (
|
|
38
|
+
make_confirm_message_received_fn_protobuf,
|
|
39
|
+
make_pull_object_fn_protobuf,
|
|
40
|
+
make_push_object_fn_protobuf,
|
|
41
|
+
)
|
|
42
|
+
from flwr.common.inflatable_utils import pull_and_inflate_object_from_tree, push_objects
|
|
35
43
|
from flwr.common.logger import log
|
|
44
|
+
from flwr.common.message import remove_content_from_message
|
|
36
45
|
from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
|
|
37
46
|
from flwr.common.serde import (
|
|
38
47
|
context_from_proto,
|
|
39
48
|
context_to_proto,
|
|
40
49
|
fab_from_proto,
|
|
41
|
-
message_from_proto,
|
|
42
50
|
message_to_proto,
|
|
43
51
|
run_from_proto,
|
|
44
52
|
)
|
|
45
53
|
from flwr.common.typing import Fab, Run
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
PushClientAppOutputsResponse,
|
|
54
|
+
from flwr.proto.appio_pb2 import ( # pylint: disable=E0611
|
|
55
|
+
PullAppInputsRequest,
|
|
56
|
+
PullAppInputsResponse,
|
|
57
|
+
PullAppMessagesRequest,
|
|
58
|
+
PullAppMessagesResponse,
|
|
59
|
+
PushAppMessagesRequest,
|
|
60
|
+
PushAppOutputsRequest,
|
|
61
|
+
PushAppOutputsResponse,
|
|
55
62
|
)
|
|
56
63
|
from flwr.proto.clientappio_pb2_grpc import ClientAppIoStub
|
|
64
|
+
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
65
|
+
from flwr.supercore.app_utils import start_parent_process_monitor
|
|
66
|
+
from flwr.supercore.utils import mask_string
|
|
57
67
|
|
|
58
68
|
|
|
59
69
|
def run_clientapp( # pylint: disable=R0913, R0914, R0917
|
|
60
70
|
clientappio_api_address: str,
|
|
61
|
-
|
|
62
|
-
token: Optional[int] = None,
|
|
71
|
+
token: str,
|
|
63
72
|
flwr_dir: Optional[str] = None,
|
|
64
73
|
certificates: Optional[bytes] = None,
|
|
65
74
|
parent_pid: Optional[int] = None,
|
|
@@ -82,124 +91,95 @@ def run_clientapp( # pylint: disable=R0913, R0914, R0917
|
|
|
82
91
|
stub = ClientAppIoStub(channel)
|
|
83
92
|
_wrap_stub(stub, _make_simple_grpc_retry_invoker())
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
while token is None:
|
|
88
|
-
token = get_token(stub)
|
|
89
|
-
time.sleep(1)
|
|
90
|
-
|
|
91
|
-
# Pull Message, Context, Run and (optional) FAB from SuperNode
|
|
92
|
-
message, context, run, fab = pull_clientappinputs(stub=stub, token=token)
|
|
93
|
-
|
|
94
|
-
# Install FAB, if provided
|
|
95
|
-
if fab:
|
|
96
|
-
log(DEBUG, "[flwr-clientapp] Start FAB installation.")
|
|
97
|
-
install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
|
|
98
|
-
|
|
99
|
-
load_client_app_fn = get_load_client_app_fn(
|
|
100
|
-
default_app_ref="",
|
|
101
|
-
app_path=None,
|
|
102
|
-
multi_app=True,
|
|
103
|
-
flwr_dir=str(flwr_dir_),
|
|
104
|
-
)
|
|
94
|
+
# Pull Message, Context, Run and (optional) FAB from SuperNode
|
|
95
|
+
message, context, run, fab = pull_clientappinputs(stub=stub, token=token)
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
run.fab_id, run.fab_version, fab.hash_str if fab else ""
|
|
111
|
-
)
|
|
97
|
+
# Install FAB, if provided
|
|
98
|
+
if fab:
|
|
99
|
+
log(DEBUG, "[flwr-clientapp] Start FAB installation.")
|
|
100
|
+
install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
|
|
112
101
|
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
load_client_app_fn = get_load_client_app_fn(
|
|
103
|
+
default_app_ref="",
|
|
104
|
+
app_path=None,
|
|
105
|
+
multi_app=True,
|
|
106
|
+
flwr_dir=str(flwr_dir_),
|
|
107
|
+
)
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
try:
|
|
110
|
+
# Load ClientApp
|
|
111
|
+
log(DEBUG, "[flwr-clientapp] Start `ClientApp` Loading.")
|
|
112
|
+
client_app: ClientApp = load_client_app_fn(
|
|
113
|
+
run.fab_id, run.fab_version, fab.hash_str if fab else ""
|
|
114
|
+
)
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
122
|
-
exc_entity = "ClientApp"
|
|
123
|
-
if isinstance(ex, LoadClientAppError):
|
|
124
|
-
reason = (
|
|
125
|
-
"An exception was raised when attempting to load `ClientApp`"
|
|
126
|
-
)
|
|
127
|
-
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
116
|
+
# Execute ClientApp
|
|
117
|
+
reply_message = client_app(message=message, context=context)
|
|
128
118
|
|
|
129
|
-
|
|
119
|
+
except Exception as ex: # pylint: disable=broad-exception-caught
|
|
120
|
+
# Don't update/change NodeState
|
|
130
121
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
122
|
+
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
123
|
+
# Ex fmt: "<class 'ZeroDivisionError'>:<'division by zero'>"
|
|
124
|
+
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
125
|
+
exc_entity = "ClientApp"
|
|
126
|
+
if isinstance(ex, LoadClientAppError):
|
|
127
|
+
reason = "An exception was raised when attempting to load `ClientApp`"
|
|
128
|
+
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
135
129
|
|
|
136
|
-
|
|
137
|
-
_ = push_clientappoutputs(
|
|
138
|
-
stub=stub, token=token, message=reply_message, context=context
|
|
139
|
-
)
|
|
130
|
+
log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
|
|
140
131
|
|
|
141
|
-
|
|
142
|
-
|
|
132
|
+
# Create error message
|
|
133
|
+
reply_message = Message(Error(code=e_code, reason=reason), reply_to=message)
|
|
143
134
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
token =
|
|
135
|
+
# Push Message and Context to SuperNode
|
|
136
|
+
_ = push_clientappoutputs(
|
|
137
|
+
stub=stub, token=token, message=reply_message, context=context
|
|
138
|
+
)
|
|
147
139
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if run_once:
|
|
151
|
-
break
|
|
140
|
+
del client_app, message, context, run, fab, reply_message
|
|
141
|
+
gc.collect()
|
|
152
142
|
|
|
153
|
-
except KeyboardInterrupt:
|
|
154
|
-
log(INFO, "Closing connection")
|
|
155
143
|
except grpc.RpcError as e:
|
|
156
144
|
log(ERROR, "GRPC error occurred: %s", str(e))
|
|
157
145
|
finally:
|
|
158
146
|
channel.close()
|
|
159
147
|
|
|
160
148
|
|
|
161
|
-
def start_parent_process_monitor(
|
|
162
|
-
parent_pid: int,
|
|
163
|
-
) -> None:
|
|
164
|
-
"""Monitor the parent process and exit if it terminates."""
|
|
165
|
-
|
|
166
|
-
def monitor() -> None:
|
|
167
|
-
while True:
|
|
168
|
-
time.sleep(0.2)
|
|
169
|
-
if os.getppid() != parent_pid:
|
|
170
|
-
os.kill(os.getpid(), 9)
|
|
171
|
-
|
|
172
|
-
threading.Thread(target=monitor, daemon=True).start()
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def get_token(stub: grpc.Channel) -> Optional[int]:
|
|
176
|
-
"""Get a token from SuperNode."""
|
|
177
|
-
log(DEBUG, "[flwr-clientapp] Request token")
|
|
178
|
-
try:
|
|
179
|
-
res: GetTokenResponse = stub.GetToken(GetTokenRequest())
|
|
180
|
-
log(DEBUG, "[GetToken] Received token: %s", res.token)
|
|
181
|
-
return res.token
|
|
182
|
-
except grpc.RpcError as e:
|
|
183
|
-
if e.code() == grpc.StatusCode.FAILED_PRECONDITION: # pylint: disable=no-member
|
|
184
|
-
log(DEBUG, "[GetToken] No token available yet")
|
|
185
|
-
else:
|
|
186
|
-
log(ERROR, "[GetToken] gRPC error occurred: %s", str(e))
|
|
187
|
-
return None
|
|
188
|
-
|
|
189
|
-
|
|
190
149
|
def pull_clientappinputs(
|
|
191
|
-
stub:
|
|
150
|
+
stub: ClientAppIoStub, token: str
|
|
192
151
|
) -> tuple[Message, Context, Run, Optional[Fab]]:
|
|
193
152
|
"""Pull ClientAppInputs from SuperNode."""
|
|
194
|
-
|
|
153
|
+
masked_token = mask_string(token)
|
|
154
|
+
log(INFO, "[flwr-clientapp] Pull `ClientAppInputs` for token %s", masked_token)
|
|
195
155
|
try:
|
|
196
|
-
|
|
197
|
-
|
|
156
|
+
# Pull Context, Run and (optional) FAB
|
|
157
|
+
res: PullAppInputsResponse = stub.PullClientAppInputs(
|
|
158
|
+
PullAppInputsRequest(token=token)
|
|
198
159
|
)
|
|
199
|
-
message = message_from_proto(res.message)
|
|
200
160
|
context = context_from_proto(res.context)
|
|
201
161
|
run = run_from_proto(res.run)
|
|
202
162
|
fab = fab_from_proto(res.fab) if res.fab else None
|
|
163
|
+
|
|
164
|
+
# Pull and inflate the message
|
|
165
|
+
pull_msg_res: PullAppMessagesResponse = stub.PullMessage(
|
|
166
|
+
PullAppMessagesRequest(token=token)
|
|
167
|
+
)
|
|
168
|
+
run_id = context.run_id
|
|
169
|
+
node = Node(node_id=context.node_id)
|
|
170
|
+
object_tree = pull_msg_res.message_object_trees[0]
|
|
171
|
+
message = pull_and_inflate_object_from_tree(
|
|
172
|
+
object_tree,
|
|
173
|
+
make_pull_object_fn_protobuf(stub.PullObject, node, run_id),
|
|
174
|
+
make_confirm_message_received_fn_protobuf(
|
|
175
|
+
stub.ConfirmMessageReceived, node, run_id
|
|
176
|
+
),
|
|
177
|
+
return_type=Message,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Set the message ID
|
|
181
|
+
# The deflated message doesn't contain the message_id (its own object_id)
|
|
182
|
+
message.metadata.__dict__["_message_id"] = object_tree.object_id
|
|
203
183
|
return message, context, run, fab
|
|
204
184
|
except grpc.RpcError as e:
|
|
205
185
|
log(ERROR, "[PullClientAppInputs] gRPC error occurred: %s", str(e))
|
|
@@ -207,18 +187,52 @@ def pull_clientappinputs(
|
|
|
207
187
|
|
|
208
188
|
|
|
209
189
|
def push_clientappoutputs(
|
|
210
|
-
stub:
|
|
211
|
-
) ->
|
|
190
|
+
stub: ClientAppIoStub, token: str, message: Message, context: Context
|
|
191
|
+
) -> PushAppOutputsResponse:
|
|
212
192
|
"""Push ClientAppOutputs to SuperNode."""
|
|
213
|
-
|
|
214
|
-
|
|
193
|
+
masked_token = mask_string(token)
|
|
194
|
+
log(INFO, "[flwr-clientapp] Push `ClientAppOutputs` for token %s", masked_token)
|
|
195
|
+
# Set message ID
|
|
196
|
+
message.metadata.__dict__["_message_id"] = message.object_id
|
|
197
|
+
proto_message = message_to_proto(remove_content_from_message(message))
|
|
215
198
|
proto_context = context_to_proto(context)
|
|
216
199
|
|
|
217
200
|
try:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
201
|
+
|
|
202
|
+
with no_object_id_recompute():
|
|
203
|
+
# Get object tree and all objects to push
|
|
204
|
+
object_tree = get_object_tree(message)
|
|
205
|
+
|
|
206
|
+
# Push Message
|
|
207
|
+
# This is temporary. The message should not contain its content
|
|
208
|
+
push_msg_res = stub.PushMessage(
|
|
209
|
+
PushAppMessagesRequest(
|
|
210
|
+
token=token,
|
|
211
|
+
messages_list=[proto_message],
|
|
212
|
+
message_object_trees=[object_tree],
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
del proto_message
|
|
216
|
+
|
|
217
|
+
# Retrieve the object IDs to push
|
|
218
|
+
object_ids_to_push = set(push_msg_res.objects_to_push)
|
|
219
|
+
|
|
220
|
+
# Push all objects
|
|
221
|
+
all_objects = get_all_nested_objects(message)
|
|
222
|
+
del message
|
|
223
|
+
push_objects(
|
|
224
|
+
all_objects,
|
|
225
|
+
make_push_object_fn_protobuf(
|
|
226
|
+
stub.PushObject,
|
|
227
|
+
Node(node_id=context.node_id),
|
|
228
|
+
run_id=context.run_id,
|
|
229
|
+
),
|
|
230
|
+
object_ids_to_push=object_ids_to_push,
|
|
221
231
|
)
|
|
232
|
+
|
|
233
|
+
# Push Context
|
|
234
|
+
res: PushAppOutputsResponse = stub.PushClientAppOutputs(
|
|
235
|
+
PushAppOutputsRequest(token=token, context=proto_context)
|
|
222
236
|
)
|
|
223
237
|
return res
|
|
224
238
|
except grpc.RpcError as e:
|
|
@@ -15,10 +15,8 @@
|
|
|
15
15
|
"""ClientAppIo API Servicer."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from .clientappio_servicer import
|
|
18
|
+
from .clientappio_servicer import ClientAppIoServicer
|
|
19
19
|
|
|
20
20
|
__all__ = [
|
|
21
|
-
"ClientAppInputs",
|
|
22
21
|
"ClientAppIoServicer",
|
|
23
|
-
"ClientAppOutputs",
|
|
24
22
|
]
|