flwr 1.22.0__py3-none-any.whl → 1.24.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 +16 -5
- flwr/app/error.py +2 -2
- flwr/app/exception.py +3 -3
- flwr/cli/app.py +34 -1
- flwr/cli/app_cmd/__init__.py +23 -0
- flwr/cli/app_cmd/publish.py +285 -0
- flwr/cli/app_cmd/review.py +252 -0
- flwr/cli/auth_plugin/__init__.py +15 -6
- flwr/cli/auth_plugin/auth_plugin.py +94 -0
- flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
- flwr/cli/auth_plugin/oidc_cli_plugin.py +46 -32
- flwr/cli/build.py +166 -53
- flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +29 -11
- flwr/cli/config_utils.py +101 -13
- flwr/cli/federation/__init__.py +24 -0
- flwr/cli/federation/ls.py +140 -0
- flwr/cli/federation/show.py +317 -0
- flwr/cli/install.py +91 -13
- flwr/cli/log.py +54 -11
- flwr/cli/login/login.py +41 -27
- flwr/cli/ls.py +177 -133
- flwr/cli/new/new.py +175 -40
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
- flwr/cli/pull.py +12 -7
- flwr/cli/run/run.py +82 -31
- flwr/cli/run_utils.py +130 -0
- flwr/cli/stop.py +27 -9
- flwr/cli/supernode/__init__.py +25 -0
- flwr/cli/supernode/ls.py +268 -0
- flwr/cli/supernode/register.py +190 -0
- flwr/cli/supernode/unregister.py +140 -0
- flwr/cli/utils.py +464 -81
- flwr/client/__init__.py +2 -1
- flwr/client/dpfedavg_numpy_client.py +4 -1
- flwr/client/grpc_adapter_client/connection.py +12 -15
- flwr/client/grpc_rere_client/connection.py +68 -41
- flwr/client/grpc_rere_client/grpc_adapter.py +34 -14
- flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
- flwr/client/message_handler/message_handler.py +2 -2
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +10 -8
- flwr/client/numpy_client.py +1 -1
- flwr/client/rest_client/connection.py +94 -51
- flwr/client/run_info_store.py +4 -5
- flwr/client/typing.py +1 -1
- flwr/clientapp/__init__.py +1 -2
- flwr/{client → clientapp}/client_app.py +9 -10
- flwr/clientapp/mod/centraldp_mods.py +16 -17
- flwr/clientapp/mod/localdp_mod.py +8 -9
- flwr/clientapp/typing.py +1 -1
- flwr/{client/clientapp → clientapp}/utils.py +4 -4
- flwr/common/address.py +1 -2
- flwr/common/args.py +3 -4
- flwr/common/config.py +13 -16
- flwr/common/constant.py +56 -13
- flwr/common/differential_privacy.py +3 -4
- flwr/common/event_log_plugin/event_log_plugin.py +3 -4
- flwr/common/exit/exit.py +15 -2
- flwr/common/exit/exit_code.py +39 -10
- flwr/common/exit/exit_handler.py +6 -2
- flwr/common/exit/signal_handler.py +5 -5
- flwr/common/grpc.py +6 -6
- flwr/common/inflatable_protobuf_utils.py +1 -1
- flwr/common/inflatable_utils.py +48 -31
- flwr/common/logger.py +19 -19
- flwr/common/message.py +4 -4
- flwr/common/object_ref.py +7 -7
- flwr/common/record/array.py +6 -6
- flwr/common/record/arrayrecord.py +18 -21
- flwr/common/record/configrecord.py +3 -3
- flwr/common/record/recorddict.py +5 -5
- flwr/common/record/typeddict.py +9 -2
- flwr/common/recorddict_compat.py +7 -10
- flwr/common/retry_invoker.py +20 -20
- flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
- flwr/common/serde.py +9 -6
- flwr/common/serde_utils.py +2 -2
- flwr/common/telemetry.py +9 -5
- flwr/common/typing.py +59 -43
- flwr/compat/client/app.py +39 -38
- flwr/compat/client/grpc_client/connection.py +13 -13
- flwr/compat/server/app.py +5 -6
- flwr/proto/appio_pb2.py +13 -3
- flwr/proto/appio_pb2.pyi +134 -65
- flwr/proto/appio_pb2_grpc.py +20 -0
- flwr/proto/appio_pb2_grpc.pyi +27 -0
- flwr/proto/clientappio_pb2.py +17 -7
- flwr/proto/clientappio_pb2.pyi +15 -0
- flwr/proto/clientappio_pb2_grpc.py +206 -40
- flwr/proto/clientappio_pb2_grpc.pyi +168 -53
- flwr/proto/control_pb2.py +72 -40
- flwr/proto/control_pb2.pyi +319 -87
- flwr/proto/control_pb2_grpc.py +339 -28
- flwr/proto/control_pb2_grpc.pyi +209 -37
- flwr/proto/error_pb2.py +13 -3
- flwr/proto/error_pb2.pyi +24 -6
- flwr/proto/error_pb2_grpc.py +20 -0
- flwr/proto/error_pb2_grpc.pyi +27 -0
- flwr/proto/fab_pb2.py +24 -10
- flwr/proto/fab_pb2.pyi +68 -20
- flwr/proto/fab_pb2_grpc.py +20 -0
- flwr/proto/fab_pb2_grpc.pyi +27 -0
- flwr/proto/federation_pb2.py +38 -0
- flwr/proto/federation_pb2.pyi +56 -0
- flwr/proto/federation_pb2_grpc.py +24 -0
- flwr/proto/federation_pb2_grpc.pyi +31 -0
- flwr/proto/fleet_pb2.py +45 -27
- flwr/proto/fleet_pb2.pyi +186 -70
- flwr/proto/fleet_pb2_grpc.py +277 -66
- flwr/proto/fleet_pb2_grpc.pyi +201 -55
- flwr/proto/grpcadapter_pb2.py +14 -4
- flwr/proto/grpcadapter_pb2.pyi +38 -16
- flwr/proto/grpcadapter_pb2_grpc.py +35 -4
- flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
- flwr/proto/heartbeat_pb2.py +17 -7
- flwr/proto/heartbeat_pb2.pyi +51 -22
- flwr/proto/heartbeat_pb2_grpc.py +20 -0
- flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
- flwr/proto/log_pb2.py +13 -3
- flwr/proto/log_pb2.pyi +34 -11
- flwr/proto/log_pb2_grpc.py +20 -0
- flwr/proto/log_pb2_grpc.pyi +27 -0
- flwr/proto/message_pb2.py +15 -5
- flwr/proto/message_pb2.pyi +154 -86
- flwr/proto/message_pb2_grpc.py +20 -0
- flwr/proto/message_pb2_grpc.pyi +27 -0
- flwr/proto/node_pb2.py +16 -4
- flwr/proto/node_pb2.pyi +77 -4
- flwr/proto/node_pb2_grpc.py +20 -0
- flwr/proto/node_pb2_grpc.pyi +27 -0
- flwr/proto/recorddict_pb2.py +13 -3
- flwr/proto/recorddict_pb2.pyi +184 -107
- flwr/proto/recorddict_pb2_grpc.py +20 -0
- flwr/proto/recorddict_pb2_grpc.pyi +27 -0
- flwr/proto/run_pb2.py +40 -31
- flwr/proto/run_pb2.pyi +149 -84
- flwr/proto/run_pb2_grpc.py +20 -0
- flwr/proto/run_pb2_grpc.pyi +27 -0
- flwr/proto/serverappio_pb2.py +13 -3
- flwr/proto/serverappio_pb2.pyi +32 -8
- flwr/proto/serverappio_pb2_grpc.py +246 -65
- flwr/proto/serverappio_pb2_grpc.pyi +221 -85
- flwr/proto/simulationio_pb2.py +16 -8
- flwr/proto/simulationio_pb2.pyi +15 -0
- flwr/proto/simulationio_pb2_grpc.py +162 -41
- flwr/proto/simulationio_pb2_grpc.pyi +149 -55
- flwr/proto/transport_pb2.py +20 -10
- flwr/proto/transport_pb2.pyi +249 -160
- flwr/proto/transport_pb2_grpc.py +35 -4
- flwr/proto/transport_pb2_grpc.pyi +38 -8
- flwr/server/app.py +173 -127
- flwr/server/client_manager.py +4 -5
- flwr/server/client_proxy.py +10 -11
- flwr/server/compat/app.py +4 -5
- flwr/server/compat/app_utils.py +2 -1
- flwr/server/compat/grid_client_proxy.py +10 -12
- flwr/server/compat/legacy_context.py +3 -4
- flwr/server/fleet_event_log_interceptor.py +2 -1
- flwr/server/grid/grid.py +2 -3
- flwr/server/grid/grpc_grid.py +10 -8
- flwr/server/grid/inmemory_grid.py +4 -4
- flwr/server/run_serverapp.py +2 -3
- flwr/server/server.py +34 -39
- flwr/server/server_app.py +7 -8
- flwr/server/server_config.py +1 -2
- flwr/server/serverapp/app.py +34 -28
- flwr/server/serverapp_components.py +4 -5
- flwr/server/strategy/aggregate.py +9 -8
- flwr/server/strategy/bulyan.py +13 -11
- flwr/server/strategy/dp_adaptive_clipping.py +16 -20
- flwr/server/strategy/dp_fixed_clipping.py +12 -17
- flwr/server/strategy/dpfedavg_adaptive.py +3 -4
- flwr/server/strategy/dpfedavg_fixed.py +6 -10
- flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
- flwr/server/strategy/fedadagrad.py +18 -14
- flwr/server/strategy/fedadam.py +16 -14
- flwr/server/strategy/fedavg.py +16 -17
- flwr/server/strategy/fedavg_android.py +15 -15
- flwr/server/strategy/fedavgm.py +21 -18
- flwr/server/strategy/fedmedian.py +2 -3
- flwr/server/strategy/fedopt.py +11 -10
- flwr/server/strategy/fedprox.py +10 -9
- flwr/server/strategy/fedtrimmedavg.py +12 -11
- flwr/server/strategy/fedxgb_bagging.py +13 -11
- flwr/server/strategy/fedxgb_cyclic.py +6 -6
- flwr/server/strategy/fedxgb_nn_avg.py +4 -4
- flwr/server/strategy/fedyogi.py +16 -14
- flwr/server/strategy/krum.py +12 -11
- flwr/server/strategy/qfedavg.py +16 -15
- flwr/server/strategy/strategy.py +6 -9
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +19 -8
- flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
- flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
- flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
- flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -51
- flwr/server/superlink/fleet/message_handler/message_handler.py +100 -49
- flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
- flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
- flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
- flwr/server/superlink/fleet/vce/vce_api.py +32 -13
- flwr/server/superlink/linkstate/in_memory_linkstate.py +266 -207
- flwr/server/superlink/linkstate/linkstate.py +161 -62
- flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
- flwr/server/superlink/linkstate/sqlite_linkstate.py +698 -638
- flwr/server/superlink/linkstate/utils.py +9 -60
- flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
- flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
- flwr/server/superlink/utils.py +4 -6
- flwr/server/typing.py +1 -1
- flwr/server/utils/tensorboard.py +15 -8
- flwr/server/utils/validator.py +2 -3
- flwr/server/workflow/default_workflows.py +5 -5
- flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +12 -10
- flwr/serverapp/strategy/bulyan.py +16 -15
- flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
- flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
- flwr/serverapp/strategy/fedadagrad.py +10 -11
- flwr/serverapp/strategy/fedadam.py +10 -11
- flwr/serverapp/strategy/fedavg.py +9 -10
- flwr/serverapp/strategy/fedavgm.py +17 -16
- flwr/serverapp/strategy/fedmedian.py +2 -2
- flwr/serverapp/strategy/fedopt.py +10 -11
- flwr/serverapp/strategy/fedprox.py +7 -8
- flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
- flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
- flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
- flwr/serverapp/strategy/fedyogi.py +9 -11
- flwr/serverapp/strategy/krum.py +7 -7
- flwr/serverapp/strategy/multikrum.py +9 -9
- flwr/serverapp/strategy/qfedavg.py +17 -16
- flwr/serverapp/strategy/strategy.py +6 -9
- flwr/serverapp/strategy/strategy_utils.py +7 -8
- flwr/simulation/app.py +46 -42
- flwr/simulation/legacy_app.py +12 -12
- flwr/simulation/ray_transport/ray_actor.py +11 -12
- flwr/simulation/ray_transport/ray_client_proxy.py +12 -13
- flwr/simulation/run_simulation.py +44 -43
- flwr/simulation/simulationio_connection.py +4 -4
- flwr/supercore/cli/flower_superexec.py +3 -4
- flwr/supercore/constant.py +52 -0
- flwr/supercore/corestate/corestate.py +24 -3
- flwr/supercore/corestate/in_memory_corestate.py +138 -0
- flwr/supercore/corestate/sqlite_corestate.py +157 -0
- flwr/supercore/ffs/disk_ffs.py +1 -2
- flwr/supercore/ffs/ffs.py +1 -2
- flwr/supercore/ffs/ffs_factory.py +1 -2
- flwr/{common → supercore}/heartbeat.py +20 -25
- flwr/supercore/object_store/in_memory_object_store.py +1 -6
- flwr/supercore/object_store/object_store.py +1 -2
- flwr/supercore/object_store/object_store_factory.py +27 -8
- flwr/supercore/object_store/sqlite_object_store.py +253 -0
- flwr/{client/clientapp → supercore/primitives}/__init__.py +1 -1
- flwr/supercore/primitives/asymmetric.py +117 -0
- flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
- flwr/supercore/sqlite_mixin.py +159 -0
- flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
- flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
- flwr/supercore/superexec/run_superexec.py +9 -13
- flwr/supercore/utils.py +20 -0
- flwr/superlink/artifact_provider/artifact_provider.py +1 -2
- flwr/{common → superlink}/auth_plugin/__init__.py +6 -6
- flwr/superlink/auth_plugin/auth_plugin.py +88 -0
- flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
- flwr/superlink/federation/__init__.py +24 -0
- flwr/superlink/federation/federation_manager.py +64 -0
- flwr/superlink/federation/noop_federation_manager.py +71 -0
- flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
- flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
- flwr/superlink/servicer/control/control_grpc.py +18 -17
- flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
- flwr/superlink/servicer/control/control_servicer.py +239 -63
- flwr/supernode/cli/flower_supernode.py +74 -26
- flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
- flwr/supernode/nodestate/nodestate.py +7 -8
- flwr/supernode/nodestate/nodestate_factory.py +7 -4
- flwr/supernode/runtime/run_clientapp.py +43 -24
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
- flwr/supernode/start_client_internal.py +175 -51
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
- flwr-1.24.0.dist-info/RECORD +454 -0
- flwr/common/auth_plugin/auth_plugin.py +0 -149
- flwr/supercore/object_store/utils.py +0 -43
- flwr-1.22.0.dist-info/RECORD +0 -428
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
|
@@ -16,19 +16,26 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import abc
|
|
19
|
-
from
|
|
19
|
+
from collections.abc import Sequence
|
|
20
20
|
|
|
21
21
|
from flwr.common import Context, Message
|
|
22
22
|
from flwr.common.record import ConfigRecord
|
|
23
23
|
from flwr.common.typing import Run, RunStatus, UserConfig
|
|
24
|
+
from flwr.proto.node_pb2 import NodeInfo # pylint: disable=E0611
|
|
24
25
|
from flwr.supercore.corestate import CoreState
|
|
26
|
+
from flwr.superlink.federation import FederationManager
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
class LinkState(CoreState): # pylint: disable=R0904
|
|
28
30
|
"""Abstract LinkState."""
|
|
29
31
|
|
|
32
|
+
@property
|
|
30
33
|
@abc.abstractmethod
|
|
31
|
-
def
|
|
34
|
+
def federation_manager(self) -> FederationManager:
|
|
35
|
+
"""Return the FederationManager instance."""
|
|
36
|
+
|
|
37
|
+
@abc.abstractmethod
|
|
38
|
+
def store_message_ins(self, message: Message) -> str | None:
|
|
32
39
|
"""Store one Message.
|
|
33
40
|
|
|
34
41
|
Usually, the ServerAppIo API calls this to schedule instructions.
|
|
@@ -46,7 +53,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
46
53
|
"""
|
|
47
54
|
|
|
48
55
|
@abc.abstractmethod
|
|
49
|
-
def get_message_ins(self, node_id: int, limit:
|
|
56
|
+
def get_message_ins(self, node_id: int, limit: int | None) -> list[Message]:
|
|
50
57
|
"""Get zero or more `Message` objects for the provided `node_id`.
|
|
51
58
|
|
|
52
59
|
Usually, the Fleet API calls this for Nodes planning to work on one or more
|
|
@@ -61,7 +68,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
61
68
|
"""
|
|
62
69
|
|
|
63
70
|
@abc.abstractmethod
|
|
64
|
-
def store_message_res(self, message: Message) ->
|
|
71
|
+
def store_message_res(self, message: Message) -> str | None:
|
|
65
72
|
"""Store one Message.
|
|
66
73
|
|
|
67
74
|
Usually, the Fleet API calls this for Nodes returning results.
|
|
@@ -128,13 +135,58 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
128
135
|
"""Get all instruction Message IDs for the given run_id."""
|
|
129
136
|
|
|
130
137
|
@abc.abstractmethod
|
|
131
|
-
def create_node(
|
|
138
|
+
def create_node(
|
|
139
|
+
self,
|
|
140
|
+
owner_aid: str,
|
|
141
|
+
owner_name: str,
|
|
142
|
+
public_key: bytes,
|
|
143
|
+
heartbeat_interval: float,
|
|
144
|
+
) -> int:
|
|
132
145
|
"""Create, store in the link state, and return `node_id`."""
|
|
133
146
|
|
|
134
147
|
@abc.abstractmethod
|
|
135
|
-
def delete_node(self, node_id: int) -> None:
|
|
148
|
+
def delete_node(self, owner_aid: str, node_id: int) -> None:
|
|
136
149
|
"""Remove `node_id` from the link state."""
|
|
137
150
|
|
|
151
|
+
@abc.abstractmethod
|
|
152
|
+
def activate_node(self, node_id: int, heartbeat_interval: float) -> bool:
|
|
153
|
+
"""Activate the node with the specified `node_id`.
|
|
154
|
+
|
|
155
|
+
Transitions the node status to "online". The transition will fail
|
|
156
|
+
if the current status is not "registered" or "offline".
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
node_id : int
|
|
161
|
+
The identifier of the node to activate.
|
|
162
|
+
heartbeat_interval : float
|
|
163
|
+
The interval (in seconds) from the current timestamp within which
|
|
164
|
+
the next heartbeat from this node is expected to be received.
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
bool
|
|
169
|
+
True if the status transition was successful, False otherwise.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
@abc.abstractmethod
|
|
173
|
+
def deactivate_node(self, node_id: int) -> bool:
|
|
174
|
+
"""Deactivate the node with the specified `node_id`.
|
|
175
|
+
|
|
176
|
+
Transitions the node status to "offline". The transition will fail
|
|
177
|
+
if the current status is not "online".
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
node_id : int
|
|
182
|
+
The identifier of the node to deactivate.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
bool
|
|
187
|
+
True if the status transition was successful, False otherwise.
|
|
188
|
+
"""
|
|
189
|
+
|
|
138
190
|
@abc.abstractmethod
|
|
139
191
|
def get_nodes(self, run_id: int) -> set[int]:
|
|
140
192
|
"""Retrieve all currently stored node IDs as a set.
|
|
@@ -146,38 +198,124 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
146
198
|
"""
|
|
147
199
|
|
|
148
200
|
@abc.abstractmethod
|
|
149
|
-
def
|
|
150
|
-
"""
|
|
201
|
+
def get_node_id_by_public_key(self, public_key: bytes) -> int | None:
|
|
202
|
+
"""Get `node_id` for the specified `public_key` if it exists and is not deleted.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
public_key : bytes
|
|
207
|
+
The public key of the node whose information is to be retrieved.
|
|
208
|
+
|
|
209
|
+
Returns
|
|
210
|
+
-------
|
|
211
|
+
Optional[int]
|
|
212
|
+
The `node_id` associated with the specified `public_key` if it exists
|
|
213
|
+
and is not deleted; otherwise, `None`.
|
|
214
|
+
"""
|
|
151
215
|
|
|
152
216
|
@abc.abstractmethod
|
|
153
|
-
def
|
|
154
|
-
|
|
217
|
+
def get_node_info(
|
|
218
|
+
self,
|
|
219
|
+
*,
|
|
220
|
+
node_ids: Sequence[int] | None = None,
|
|
221
|
+
owner_aids: Sequence[str] | None = None,
|
|
222
|
+
statuses: Sequence[str] | None = None,
|
|
223
|
+
) -> Sequence[NodeInfo]:
|
|
224
|
+
"""Retrieve information about nodes based on the specified filters.
|
|
225
|
+
|
|
226
|
+
If a filter is set to None, it is ignored.
|
|
227
|
+
If multiple filters are provided, they are combined using AND logic.
|
|
228
|
+
|
|
229
|
+
Parameters
|
|
230
|
+
----------
|
|
231
|
+
node_ids : Optional[Sequence[int]] (default: None)
|
|
232
|
+
Sequence of node IDs to filter by. If a sequence is provided,
|
|
233
|
+
it is treated as an OR condition.
|
|
234
|
+
owner_aids : Optional[Sequence[str]] (default: None)
|
|
235
|
+
Sequence of owner account IDs to filter by. If a sequence is provided,
|
|
236
|
+
it is treated as an OR condition.
|
|
237
|
+
statuses : Optional[Sequence[str]] (default: None)
|
|
238
|
+
Sequence of node status values (e.g., "created", "activated")
|
|
239
|
+
to filter by. If a sequence is provided, it is treated as an OR condition.
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
Sequence[NodeInfo]
|
|
244
|
+
A sequence of NodeInfo objects representing the nodes matching
|
|
245
|
+
the specified filters.
|
|
246
|
+
"""
|
|
155
247
|
|
|
156
248
|
@abc.abstractmethod
|
|
157
|
-
def
|
|
158
|
-
"""
|
|
249
|
+
def get_node_public_key(self, node_id: int) -> bytes:
|
|
250
|
+
"""Get `public_key` for the specified `node_id`.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
node_id : int
|
|
255
|
+
The identifier of the node whose public key is to be retrieved.
|
|
256
|
+
|
|
257
|
+
Returns
|
|
258
|
+
-------
|
|
259
|
+
bytes
|
|
260
|
+
The public key associated with the specified `node_id`.
|
|
261
|
+
|
|
262
|
+
Raises
|
|
263
|
+
------
|
|
264
|
+
ValueError
|
|
265
|
+
If the specified `node_id` does not exist in the link state.
|
|
266
|
+
"""
|
|
159
267
|
|
|
160
268
|
@abc.abstractmethod
|
|
161
269
|
def create_run( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
162
270
|
self,
|
|
163
|
-
fab_id:
|
|
164
|
-
fab_version:
|
|
165
|
-
fab_hash:
|
|
271
|
+
fab_id: str | None,
|
|
272
|
+
fab_version: str | None,
|
|
273
|
+
fab_hash: str | None,
|
|
166
274
|
override_config: UserConfig,
|
|
275
|
+
federation: str,
|
|
167
276
|
federation_options: ConfigRecord,
|
|
168
|
-
flwr_aid:
|
|
277
|
+
flwr_aid: str | None,
|
|
169
278
|
) -> int:
|
|
170
|
-
"""Create a new run
|
|
279
|
+
"""Create a new run.
|
|
280
|
+
|
|
281
|
+
Parameters
|
|
282
|
+
----------
|
|
283
|
+
fab_id : Optional[str]
|
|
284
|
+
The ID of the FAB, of format `<publisher>/<app-name>`.
|
|
285
|
+
fab_version : Optional[str]
|
|
286
|
+
The version of the FAB.
|
|
287
|
+
fab_hash : Optional[str]
|
|
288
|
+
The SHA256 hex hash of the FAB.
|
|
289
|
+
override_config : UserConfig
|
|
290
|
+
Configuration overrides for the run config.
|
|
291
|
+
federation : str
|
|
292
|
+
The federation this run belongs to.
|
|
293
|
+
federation_options : ConfigRecord
|
|
294
|
+
Federation configurations. For now, only `num-supernodes` for
|
|
295
|
+
the simulation runtime.
|
|
296
|
+
flwr_aid : Optional[str]
|
|
297
|
+
Flower Account ID of the creator.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
int
|
|
302
|
+
The run ID of the newly created run.
|
|
303
|
+
|
|
304
|
+
Notes
|
|
305
|
+
-----
|
|
306
|
+
This method will not verify if the account has permission to create
|
|
307
|
+
a run in the federation.
|
|
308
|
+
"""
|
|
171
309
|
|
|
172
310
|
@abc.abstractmethod
|
|
173
|
-
def get_run_ids(self, flwr_aid:
|
|
311
|
+
def get_run_ids(self, flwr_aid: str | None) -> set[int]:
|
|
174
312
|
"""Retrieve all run IDs if `flwr_aid` is not specified.
|
|
175
313
|
|
|
176
314
|
Otherwise, retrieve all run IDs for the specified `flwr_aid`.
|
|
177
315
|
"""
|
|
178
316
|
|
|
179
317
|
@abc.abstractmethod
|
|
180
|
-
def get_run(self, run_id: int) ->
|
|
318
|
+
def get_run(self, run_id: int) -> Run | None:
|
|
181
319
|
"""Retrieve information about the run with the specified `run_id`.
|
|
182
320
|
|
|
183
321
|
Parameters
|
|
@@ -229,7 +367,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
229
367
|
"""
|
|
230
368
|
|
|
231
369
|
@abc.abstractmethod
|
|
232
|
-
def get_pending_run_id(self) ->
|
|
370
|
+
def get_pending_run_id(self) -> int | None:
|
|
233
371
|
"""Get the `run_id` of a run with `Status.PENDING` status.
|
|
234
372
|
|
|
235
373
|
Returns
|
|
@@ -240,7 +378,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
240
378
|
"""
|
|
241
379
|
|
|
242
380
|
@abc.abstractmethod
|
|
243
|
-
def get_federation_options(self, run_id: int) ->
|
|
381
|
+
def get_federation_options(self, run_id: int) -> ConfigRecord | None:
|
|
244
382
|
"""Retrieve the federation options for the specified `run_id`.
|
|
245
383
|
|
|
246
384
|
Parameters
|
|
@@ -254,22 +392,6 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
254
392
|
The federation options for the run if it exists; None otherwise.
|
|
255
393
|
"""
|
|
256
394
|
|
|
257
|
-
@abc.abstractmethod
|
|
258
|
-
def clear_supernode_auth_keys(self) -> None:
|
|
259
|
-
"""Clear stored `node_public_keys` in the link state if any."""
|
|
260
|
-
|
|
261
|
-
@abc.abstractmethod
|
|
262
|
-
def store_node_public_keys(self, public_keys: set[bytes]) -> None:
|
|
263
|
-
"""Store a set of `node_public_keys` in the link state."""
|
|
264
|
-
|
|
265
|
-
@abc.abstractmethod
|
|
266
|
-
def store_node_public_key(self, public_key: bytes) -> None:
|
|
267
|
-
"""Store a `node_public_key` in the link state."""
|
|
268
|
-
|
|
269
|
-
@abc.abstractmethod
|
|
270
|
-
def get_node_public_keys(self) -> set[bytes]:
|
|
271
|
-
"""Retrieve all currently stored `node_public_keys` as a set."""
|
|
272
|
-
|
|
273
395
|
@abc.abstractmethod
|
|
274
396
|
def acknowledge_node_heartbeat(
|
|
275
397
|
self, node_id: int, heartbeat_interval: float
|
|
@@ -297,30 +419,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
297
419
|
"""
|
|
298
420
|
|
|
299
421
|
@abc.abstractmethod
|
|
300
|
-
def
|
|
301
|
-
"""Acknowledge a heartbeat received from a ServerApp for a given run.
|
|
302
|
-
|
|
303
|
-
A run with status `"running"` is considered alive as long as it sends heartbeats
|
|
304
|
-
within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
|
|
305
|
-
HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
|
|
306
|
-
marked as `"completed:failed"`.
|
|
307
|
-
|
|
308
|
-
Parameters
|
|
309
|
-
----------
|
|
310
|
-
run_id : int
|
|
311
|
-
The `run_id` from which the heartbeat was received.
|
|
312
|
-
heartbeat_interval : float
|
|
313
|
-
The interval (in seconds) from the current timestamp within which the next
|
|
314
|
-
heartbeat from the ServerApp for this run must be received.
|
|
315
|
-
|
|
316
|
-
Returns
|
|
317
|
-
-------
|
|
318
|
-
is_acknowledged : bool
|
|
319
|
-
True if the heartbeat is successfully acknowledged; otherwise, False.
|
|
320
|
-
"""
|
|
321
|
-
|
|
322
|
-
@abc.abstractmethod
|
|
323
|
-
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
|
422
|
+
def get_serverapp_context(self, run_id: int) -> Context | None:
|
|
324
423
|
"""Get the context for the specified `run_id`.
|
|
325
424
|
|
|
326
425
|
Parameters
|
|
@@ -361,7 +460,7 @@ class LinkState(CoreState): # pylint: disable=R0904
|
|
|
361
460
|
|
|
362
461
|
@abc.abstractmethod
|
|
363
462
|
def get_serverapp_log(
|
|
364
|
-
self, run_id: int, after_timestamp:
|
|
463
|
+
self, run_id: int, after_timestamp: float | None
|
|
365
464
|
) -> tuple[str, float]:
|
|
366
465
|
"""Get the ServerApp logs for the specified `run_id`.
|
|
367
466
|
|
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
from logging import DEBUG
|
|
19
|
-
from typing import Optional
|
|
20
19
|
|
|
21
20
|
from flwr.common.logger import log
|
|
21
|
+
from flwr.supercore.constant import FLWR_IN_MEMORY_DB_NAME
|
|
22
|
+
from flwr.supercore.object_store import ObjectStoreFactory
|
|
23
|
+
from flwr.superlink.federation import FederationManager
|
|
22
24
|
|
|
23
25
|
from .in_memory_linkstate import InMemoryLinkState
|
|
24
26
|
from .linkstate import LinkState
|
|
@@ -35,23 +37,39 @@ class LinkStateFactory:
|
|
|
35
37
|
Note that passing ':memory:' will open a connection to a database that is
|
|
36
38
|
in RAM, instead of on disk. For more information on special in-memory
|
|
37
39
|
databases, please refer to https://sqlite.org/inmemorydb.html.
|
|
40
|
+
federation_manager : FederationManager
|
|
41
|
+
An instance of FederationManager to manage federations.
|
|
42
|
+
objectstore_factory : ObjectStoreFactory
|
|
43
|
+
An instance of ObjectStoreFactory to create object stores.
|
|
38
44
|
"""
|
|
39
45
|
|
|
40
|
-
def __init__(
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
database: str,
|
|
49
|
+
federation_manager: FederationManager,
|
|
50
|
+
objectstore_factory: ObjectStoreFactory,
|
|
51
|
+
) -> None:
|
|
41
52
|
self.database = database
|
|
42
|
-
self.state_instance:
|
|
53
|
+
self.state_instance: LinkState | None = None
|
|
54
|
+
self.federation_manager = federation_manager
|
|
55
|
+
self.objectstore_factory = objectstore_factory
|
|
43
56
|
|
|
44
57
|
def state(self) -> LinkState:
|
|
45
58
|
"""Return a State instance and create it, if necessary."""
|
|
59
|
+
# Get the ObjectStore instance
|
|
60
|
+
object_store = self.objectstore_factory.store()
|
|
61
|
+
|
|
46
62
|
# InMemoryState
|
|
47
|
-
if self.database ==
|
|
63
|
+
if self.database == FLWR_IN_MEMORY_DB_NAME:
|
|
48
64
|
if self.state_instance is None:
|
|
49
|
-
self.state_instance = InMemoryLinkState(
|
|
65
|
+
self.state_instance = InMemoryLinkState(
|
|
66
|
+
self.federation_manager, object_store
|
|
67
|
+
)
|
|
50
68
|
log(DEBUG, "Using InMemoryState")
|
|
51
69
|
return self.state_instance
|
|
52
70
|
|
|
53
71
|
# SqliteState
|
|
54
|
-
state = SqliteLinkState(self.database)
|
|
72
|
+
state = SqliteLinkState(self.database, self.federation_manager, object_store)
|
|
55
73
|
state.initialize()
|
|
56
74
|
log(DEBUG, "Using SqliteState")
|
|
57
75
|
return state
|