flwr-nightly 1.8.0.dev20240328__tar.gz → 1.9.0.dev20240404__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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/PKG-INFO +1 -1
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/pyproject.toml +1 -1
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -1
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/requirements.pytorch.txt.tpl +1 -1
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/app.py +26 -13
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/client_app.py +16 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/grpc_rere_client/connection.py +71 -29
- flwr_nightly-1.9.0.dev20240404/src/py/flwr/client/heartbeat.py +72 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/rest_client/connection.py +102 -28
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/constant.py +20 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/logger.py +4 -4
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/message.py +15 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/retry_invoker.py +24 -13
- flwr_nightly-1.9.0.dev20240404/src/py/flwr/proto/fleet_pb2.py +54 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/fleet_pb2.pyi +5 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/driver/driver.py +15 -5
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/server_app.py +3 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +3 -2
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +28 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +22 -4
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/state/in_memory_state.py +25 -8
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/state/sqlite_state.py +53 -5
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/state/state.py +1 -1
- flwr_nightly-1.9.0.dev20240404/src/py/flwr/server/superlink/state/utils.py +56 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/default_workflows.py +1 -4
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -5
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/ray_transport/ray_actor.py +2 -22
- flwr_nightly-1.8.0.dev20240328/src/py/flwr/proto/fleet_pb2.py +0 -54
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/LICENSE +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/README.md +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/app.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/example.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/flower_toml.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/new.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/flower.toml.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/requirements.numpy.txt.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/run/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/run/run.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/cli/utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/client.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/grpc_client/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/grpc_client/connection.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/message_handler/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/message_handler/message_handler.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/message_handler/task_handler.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/comms_mods.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/localdp_mod.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/mod/utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/node_state.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/node_state_tests.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/numpy_client.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/rest_client/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/typing.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/address.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/context.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/date.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/differential_privacy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/differential_privacy_constants.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/dp.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/exit_handlers.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/object_ref.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/parameter.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/pyproject.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/configsrecord.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/conversion_utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/metricsrecord.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/parametersrecord.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/recordset.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/record/typeddict.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/recordset_compat.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/serde.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/telemetry.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/typing.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/common/version.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/driver_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/driver_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/error_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/error_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/node_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/node_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/recordset_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/task_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/task_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/transport_pb2.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/transport_pb2.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/py.typed +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/app.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/client_manager.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/client_proxy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/compat/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/compat/app.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/compat/app_utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/compat/legacy_context.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/criterion.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/driver/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/driver/grpc_driver.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/history.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/run_serverapp.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/server.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/server_config.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/aggregate.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/bulyan.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedadam.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedavg.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedavgm.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedmedian.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedopt.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedprox.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/fedyogi.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/krum.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/qfedavg.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/strategy/strategy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/driver/driver_servicer.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/state/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/typing.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/utils/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/utils/tensorboard.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/utils/validator.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/constant.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/app.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
- {flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/simulation/run_simulation.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "flwr-nightly"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.9.0-dev20240404"
|
|
8
8
|
description = "Flower: A Friendly Federated Learning Framework"
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
authors = ["The Flower Authors <hello@flower.ai>"]
|
|
@@ -39,7 +39,7 @@ def load_data(partition_id, num_partitions):
|
|
|
39
39
|
fds = FederatedDataset(dataset="cifar10", partitioners={"train": num_partitions})
|
|
40
40
|
partition = fds.load_partition(partition_id)
|
|
41
41
|
# Divide data on each node: 80% train, 20% test
|
|
42
|
-
partition_train_test = partition.train_test_split(test_size=0.2)
|
|
42
|
+
partition_train_test = partition.train_test_split(test_size=0.2, seed=42)
|
|
43
43
|
pytorch_transforms = Compose(
|
|
44
44
|
[ToTensor(), Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]
|
|
45
45
|
)
|
|
@@ -15,7 +15,7 @@ readme = "README.md"
|
|
|
15
15
|
[tool.poetry.dependencies]
|
|
16
16
|
python = "^3.9"
|
|
17
17
|
# Mandatory dependencies
|
|
18
|
-
flwr
|
|
18
|
+
flwr = { version = "^1.8.0", extras = ["simulation"] }
|
|
19
19
|
flwr-datasets = { version = "0.0.2", extras = ["vision"] }
|
|
20
20
|
torch = "2.2.1"
|
|
21
21
|
torchvision = "0.17.1"
|
|
@@ -34,9 +34,10 @@ from flwr.common.constant import (
|
|
|
34
34
|
TRANSPORT_TYPE_GRPC_RERE,
|
|
35
35
|
TRANSPORT_TYPE_REST,
|
|
36
36
|
TRANSPORT_TYPES,
|
|
37
|
+
ErrorCode,
|
|
37
38
|
)
|
|
38
39
|
from flwr.common.exit_handlers import register_exit_handlers
|
|
39
|
-
from flwr.common.logger import log, warn_deprecated_feature
|
|
40
|
+
from flwr.common.logger import log, warn_deprecated_feature
|
|
40
41
|
from flwr.common.message import Error
|
|
41
42
|
from flwr.common.object_ref import load_app, validate
|
|
42
43
|
from flwr.common.retry_invoker import RetryInvoker, exponential
|
|
@@ -385,8 +386,6 @@ def _start_client_internal(
|
|
|
385
386
|
return ClientApp(client_fn=client_fn)
|
|
386
387
|
|
|
387
388
|
load_client_app_fn = _load_client_app
|
|
388
|
-
else:
|
|
389
|
-
warn_experimental_feature("`load_client_app_fn`")
|
|
390
389
|
|
|
391
390
|
# At this point, only `load_client_app_fn` should be used
|
|
392
391
|
# Both `client` and `client_fn` must not be used directly
|
|
@@ -397,7 +396,7 @@ def _start_client_internal(
|
|
|
397
396
|
)
|
|
398
397
|
|
|
399
398
|
retry_invoker = RetryInvoker(
|
|
400
|
-
|
|
399
|
+
wait_gen_factory=exponential,
|
|
401
400
|
recoverable_exceptions=connection_error_type,
|
|
402
401
|
max_tries=max_retries,
|
|
403
402
|
max_time=max_wait_time,
|
|
@@ -485,7 +484,7 @@ def _start_client_internal(
|
|
|
485
484
|
# Create an error reply message that will never be used to prevent
|
|
486
485
|
# the used-before-assignment linting error
|
|
487
486
|
reply_message = message.create_error_reply(
|
|
488
|
-
error=Error(code=
|
|
487
|
+
error=Error(code=ErrorCode.UNKNOWN, reason="Unknown")
|
|
489
488
|
)
|
|
490
489
|
|
|
491
490
|
# Handle app loading and task message
|
|
@@ -493,27 +492,41 @@ def _start_client_internal(
|
|
|
493
492
|
# Load ClientApp instance
|
|
494
493
|
client_app: ClientApp = load_client_app_fn()
|
|
495
494
|
|
|
495
|
+
# Execute ClientApp
|
|
496
496
|
reply_message = client_app(message=message, context=context)
|
|
497
|
-
# Update node state
|
|
498
|
-
node_state.update_context(
|
|
499
|
-
run_id=message.metadata.run_id,
|
|
500
|
-
context=context,
|
|
501
|
-
)
|
|
502
497
|
except Exception as ex: # pylint: disable=broad-exception-caught
|
|
503
|
-
log(ERROR, "ClientApp raised an exception", exc_info=ex)
|
|
504
498
|
|
|
505
499
|
# Legacy grpc-bidi
|
|
506
500
|
if transport in ["grpc-bidi", None]:
|
|
501
|
+
log(ERROR, "Client raised an exception.", exc_info=ex)
|
|
507
502
|
# Raise exception, crash process
|
|
508
503
|
raise ex
|
|
509
504
|
|
|
510
505
|
# Don't update/change NodeState
|
|
511
506
|
|
|
512
|
-
|
|
507
|
+
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
513
508
|
# Reason example: "<class 'ZeroDivisionError'>:<'division by zero'>"
|
|
514
509
|
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
510
|
+
exc_entity = "ClientApp"
|
|
511
|
+
if isinstance(ex, LoadClientAppError):
|
|
512
|
+
reason = (
|
|
513
|
+
"An exception was raised when attempting to load "
|
|
514
|
+
"`ClientApp`"
|
|
515
|
+
)
|
|
516
|
+
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
517
|
+
exc_entity = "SuperNode"
|
|
518
|
+
|
|
519
|
+
log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
|
|
520
|
+
|
|
521
|
+
# Create error message
|
|
515
522
|
reply_message = message.create_error_reply(
|
|
516
|
-
error=Error(code=
|
|
523
|
+
error=Error(code=e_code, reason=reason)
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
# No exception, update node state
|
|
527
|
+
node_state.update_context(
|
|
528
|
+
run_id=message.metadata.run_id,
|
|
529
|
+
context=context,
|
|
517
530
|
)
|
|
518
531
|
|
|
519
532
|
# Send
|
{flwr_nightly-1.8.0.dev20240328 → flwr_nightly-1.9.0.dev20240404}/src/py/flwr/client/client_app.py
RENAMED
|
@@ -23,10 +23,20 @@ from flwr.client.message_handler.message_handler import (
|
|
|
23
23
|
from flwr.client.mod.utils import make_ffn
|
|
24
24
|
from flwr.client.typing import ClientFn, Mod
|
|
25
25
|
from flwr.common import Context, Message, MessageType
|
|
26
|
+
from flwr.common.logger import warn_preview_feature
|
|
26
27
|
|
|
27
28
|
from .typing import ClientAppCallable
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
class ClientAppException(Exception):
|
|
32
|
+
"""Exception raised when an exception is raised while executing a ClientApp."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, message: str):
|
|
35
|
+
ex_name = self.__class__.__name__
|
|
36
|
+
self.message = f"\nException {ex_name} occurred. Message: " + message
|
|
37
|
+
super().__init__(self.message)
|
|
38
|
+
|
|
39
|
+
|
|
30
40
|
class ClientApp:
|
|
31
41
|
"""Flower ClientApp.
|
|
32
42
|
|
|
@@ -123,6 +133,8 @@ class ClientApp:
|
|
|
123
133
|
if self._call:
|
|
124
134
|
raise _registration_error(MessageType.TRAIN)
|
|
125
135
|
|
|
136
|
+
warn_preview_feature("ClientApp-register-train-function")
|
|
137
|
+
|
|
126
138
|
# Register provided function with the ClientApp object
|
|
127
139
|
# Wrap mods around the wrapped step function
|
|
128
140
|
self._train = make_ffn(train_fn, self._mods)
|
|
@@ -151,6 +163,8 @@ class ClientApp:
|
|
|
151
163
|
if self._call:
|
|
152
164
|
raise _registration_error(MessageType.EVALUATE)
|
|
153
165
|
|
|
166
|
+
warn_preview_feature("ClientApp-register-evaluate-function")
|
|
167
|
+
|
|
154
168
|
# Register provided function with the ClientApp object
|
|
155
169
|
# Wrap mods around the wrapped step function
|
|
156
170
|
self._evaluate = make_ffn(evaluate_fn, self._mods)
|
|
@@ -179,6 +193,8 @@ class ClientApp:
|
|
|
179
193
|
if self._call:
|
|
180
194
|
raise _registration_error(MessageType.QUERY)
|
|
181
195
|
|
|
196
|
+
warn_preview_feature("ClientApp-register-query-function")
|
|
197
|
+
|
|
182
198
|
# Register provided function with the ClientApp object
|
|
183
199
|
# Wrap mods around the wrapped step function
|
|
184
200
|
self._query = make_ffn(query_fn, self._mods)
|
|
@@ -15,23 +15,34 @@
|
|
|
15
15
|
"""Contextmanager for a gRPC request-response channel to the Flower server."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
import random
|
|
19
|
+
import threading
|
|
18
20
|
from contextlib import contextmanager
|
|
19
21
|
from copy import copy
|
|
20
22
|
from logging import DEBUG, ERROR
|
|
21
23
|
from pathlib import Path
|
|
22
|
-
from typing import Callable,
|
|
24
|
+
from typing import Callable, Iterator, Optional, Tuple, Union, cast
|
|
23
25
|
|
|
26
|
+
from flwr.client.heartbeat import start_ping_loop
|
|
24
27
|
from flwr.client.message_handler.message_handler import validate_out_message
|
|
25
28
|
from flwr.client.message_handler.task_handler import get_task_ins, validate_task_ins
|
|
26
29
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH
|
|
30
|
+
from flwr.common.constant import (
|
|
31
|
+
PING_BASE_MULTIPLIER,
|
|
32
|
+
PING_CALL_TIMEOUT,
|
|
33
|
+
PING_DEFAULT_INTERVAL,
|
|
34
|
+
PING_RANDOM_RANGE,
|
|
35
|
+
)
|
|
27
36
|
from flwr.common.grpc import create_channel
|
|
28
|
-
from flwr.common.logger import log
|
|
37
|
+
from flwr.common.logger import log
|
|
29
38
|
from flwr.common.message import Message, Metadata
|
|
30
39
|
from flwr.common.retry_invoker import RetryInvoker
|
|
31
40
|
from flwr.common.serde import message_from_taskins, message_to_taskres
|
|
32
41
|
from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
33
42
|
CreateNodeRequest,
|
|
34
43
|
DeleteNodeRequest,
|
|
44
|
+
PingRequest,
|
|
45
|
+
PingResponse,
|
|
35
46
|
PullTaskInsRequest,
|
|
36
47
|
PushTaskResRequest,
|
|
37
48
|
)
|
|
@@ -39,9 +50,6 @@ from flwr.proto.fleet_pb2_grpc import FleetStub # pylint: disable=E0611
|
|
|
39
50
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
40
51
|
from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
|
|
41
52
|
|
|
42
|
-
KEY_NODE = "node"
|
|
43
|
-
KEY_METADATA = "in_message_metadata"
|
|
44
|
-
|
|
45
53
|
|
|
46
54
|
def on_channel_state_change(channel_connectivity: str) -> None:
|
|
47
55
|
"""Log channel connectivity."""
|
|
@@ -49,7 +57,7 @@ def on_channel_state_change(channel_connectivity: str) -> None:
|
|
|
49
57
|
|
|
50
58
|
|
|
51
59
|
@contextmanager
|
|
52
|
-
def grpc_request_response(
|
|
60
|
+
def grpc_request_response( # pylint: disable=R0914, R0915
|
|
53
61
|
server_address: str,
|
|
54
62
|
insecure: bool,
|
|
55
63
|
retry_invoker: RetryInvoker,
|
|
@@ -95,8 +103,6 @@ def grpc_request_response(
|
|
|
95
103
|
create_node : Optional[Callable]
|
|
96
104
|
delete_node : Optional[Callable]
|
|
97
105
|
"""
|
|
98
|
-
warn_experimental_feature("`grpc-rere`")
|
|
99
|
-
|
|
100
106
|
if isinstance(root_certificates, str):
|
|
101
107
|
root_certificates = Path(root_certificates).read_bytes()
|
|
102
108
|
|
|
@@ -107,47 +113,81 @@ def grpc_request_response(
|
|
|
107
113
|
max_message_length=max_message_length,
|
|
108
114
|
)
|
|
109
115
|
channel.subscribe(on_channel_state_change)
|
|
110
|
-
stub = FleetStub(channel)
|
|
111
116
|
|
|
112
|
-
#
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
# Shared variables for inner functions
|
|
118
|
+
stub = FleetStub(channel)
|
|
119
|
+
metadata: Optional[Metadata] = None
|
|
120
|
+
node: Optional[Node] = None
|
|
121
|
+
ping_thread: Optional[threading.Thread] = None
|
|
122
|
+
ping_stop_event = threading.Event()
|
|
117
123
|
|
|
118
124
|
###########################################################################
|
|
119
|
-
# receive/send functions
|
|
125
|
+
# ping/create_node/delete_node/receive/send functions
|
|
120
126
|
###########################################################################
|
|
121
127
|
|
|
128
|
+
def ping() -> None:
|
|
129
|
+
# Get Node
|
|
130
|
+
if node is None:
|
|
131
|
+
log(ERROR, "Node instance missing")
|
|
132
|
+
return
|
|
133
|
+
|
|
134
|
+
# Construct the ping request
|
|
135
|
+
req = PingRequest(node=node, ping_interval=PING_DEFAULT_INTERVAL)
|
|
136
|
+
|
|
137
|
+
# Call FleetAPI
|
|
138
|
+
res: PingResponse = stub.Ping(req, timeout=PING_CALL_TIMEOUT)
|
|
139
|
+
|
|
140
|
+
# Check if success
|
|
141
|
+
if not res.success:
|
|
142
|
+
raise RuntimeError("Ping failed unexpectedly.")
|
|
143
|
+
|
|
144
|
+
# Wait
|
|
145
|
+
rd = random.uniform(*PING_RANDOM_RANGE)
|
|
146
|
+
next_interval: float = PING_DEFAULT_INTERVAL - PING_CALL_TIMEOUT
|
|
147
|
+
next_interval *= PING_BASE_MULTIPLIER + rd
|
|
148
|
+
if not ping_stop_event.is_set():
|
|
149
|
+
ping_stop_event.wait(next_interval)
|
|
150
|
+
|
|
122
151
|
def create_node() -> None:
|
|
123
152
|
"""Set create_node."""
|
|
124
|
-
|
|
153
|
+
# Call FleetAPI
|
|
154
|
+
create_node_request = CreateNodeRequest(ping_interval=PING_DEFAULT_INTERVAL)
|
|
125
155
|
create_node_response = retry_invoker.invoke(
|
|
126
156
|
stub.CreateNode,
|
|
127
157
|
request=create_node_request,
|
|
128
158
|
)
|
|
129
|
-
|
|
159
|
+
|
|
160
|
+
# Remember the node and the ping-loop thread
|
|
161
|
+
nonlocal node, ping_thread
|
|
162
|
+
node = cast(Node, create_node_response.node)
|
|
163
|
+
ping_thread = start_ping_loop(ping, ping_stop_event)
|
|
130
164
|
|
|
131
165
|
def delete_node() -> None:
|
|
132
166
|
"""Set delete_node."""
|
|
133
167
|
# Get Node
|
|
134
|
-
|
|
168
|
+
nonlocal node
|
|
169
|
+
if node is None:
|
|
135
170
|
log(ERROR, "Node instance missing")
|
|
136
171
|
return
|
|
137
|
-
node: Node = cast(Node, node_store[KEY_NODE])
|
|
138
172
|
|
|
173
|
+
# Stop the ping-loop thread
|
|
174
|
+
ping_stop_event.set()
|
|
175
|
+
if ping_thread is not None:
|
|
176
|
+
ping_thread.join()
|
|
177
|
+
|
|
178
|
+
# Call FleetAPI
|
|
139
179
|
delete_node_request = DeleteNodeRequest(node=node)
|
|
140
180
|
retry_invoker.invoke(stub.DeleteNode, request=delete_node_request)
|
|
141
181
|
|
|
142
|
-
|
|
182
|
+
# Cleanup
|
|
183
|
+
node = None
|
|
143
184
|
|
|
144
185
|
def receive() -> Optional[Message]:
|
|
145
186
|
"""Receive next task from server."""
|
|
146
187
|
# Get Node
|
|
147
|
-
if
|
|
188
|
+
if node is None:
|
|
148
189
|
log(ERROR, "Node instance missing")
|
|
149
190
|
return None
|
|
150
|
-
node: Node = cast(Node, node_store[KEY_NODE])
|
|
151
191
|
|
|
152
192
|
# Request instructions (task) from server
|
|
153
193
|
request = PullTaskInsRequest(node=node)
|
|
@@ -167,7 +207,8 @@ def grpc_request_response(
|
|
|
167
207
|
in_message = message_from_taskins(task_ins) if task_ins else None
|
|
168
208
|
|
|
169
209
|
# Remember `metadata` of the in message
|
|
170
|
-
|
|
210
|
+
nonlocal metadata
|
|
211
|
+
metadata = copy(in_message.metadata) if in_message else None
|
|
171
212
|
|
|
172
213
|
# Return the message if available
|
|
173
214
|
return in_message
|
|
@@ -175,18 +216,18 @@ def grpc_request_response(
|
|
|
175
216
|
def send(message: Message) -> None:
|
|
176
217
|
"""Send task result back to server."""
|
|
177
218
|
# Get Node
|
|
178
|
-
if
|
|
219
|
+
if node is None:
|
|
179
220
|
log(ERROR, "Node instance missing")
|
|
180
221
|
return
|
|
181
222
|
|
|
182
|
-
# Get incoming message
|
|
183
|
-
|
|
184
|
-
if
|
|
223
|
+
# Get the metadata of the incoming message
|
|
224
|
+
nonlocal metadata
|
|
225
|
+
if metadata is None:
|
|
185
226
|
log(ERROR, "No current message")
|
|
186
227
|
return
|
|
187
228
|
|
|
188
229
|
# Validate out message
|
|
189
|
-
if not validate_out_message(message,
|
|
230
|
+
if not validate_out_message(message, metadata):
|
|
190
231
|
log(ERROR, "Invalid out message")
|
|
191
232
|
return
|
|
192
233
|
|
|
@@ -197,7 +238,8 @@ def grpc_request_response(
|
|
|
197
238
|
request = PushTaskResRequest(task_res_list=[task_res])
|
|
198
239
|
_ = retry_invoker.invoke(stub.PushTaskRes, request)
|
|
199
240
|
|
|
200
|
-
|
|
241
|
+
# Cleanup
|
|
242
|
+
metadata = None
|
|
201
243
|
|
|
202
244
|
try:
|
|
203
245
|
# Yield methods
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 2024 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Heartbeat utility functions."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import threading
|
|
19
|
+
from typing import Callable
|
|
20
|
+
|
|
21
|
+
import grpc
|
|
22
|
+
|
|
23
|
+
from flwr.common.constant import PING_CALL_TIMEOUT
|
|
24
|
+
from flwr.common.retry_invoker import RetryInvoker, RetryState, exponential
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _ping_loop(ping_fn: Callable[[], None], stop_event: threading.Event) -> None:
|
|
28
|
+
def wait_fn(wait_time: float) -> None:
|
|
29
|
+
if not stop_event.is_set():
|
|
30
|
+
stop_event.wait(wait_time)
|
|
31
|
+
|
|
32
|
+
def on_backoff(state: RetryState) -> None:
|
|
33
|
+
err = state.exception
|
|
34
|
+
if not isinstance(err, grpc.RpcError):
|
|
35
|
+
return
|
|
36
|
+
status_code = err.code()
|
|
37
|
+
# If ping call timeout is triggered
|
|
38
|
+
if status_code == grpc.StatusCode.DEADLINE_EXCEEDED:
|
|
39
|
+
# Avoid long wait time.
|
|
40
|
+
if state.actual_wait is None:
|
|
41
|
+
return
|
|
42
|
+
state.actual_wait = max(state.actual_wait - PING_CALL_TIMEOUT, 0.0)
|
|
43
|
+
|
|
44
|
+
def wrapped_ping() -> None:
|
|
45
|
+
if not stop_event.is_set():
|
|
46
|
+
ping_fn()
|
|
47
|
+
|
|
48
|
+
retrier = RetryInvoker(
|
|
49
|
+
exponential,
|
|
50
|
+
grpc.RpcError,
|
|
51
|
+
max_tries=None,
|
|
52
|
+
max_time=None,
|
|
53
|
+
on_backoff=on_backoff,
|
|
54
|
+
wait_function=wait_fn,
|
|
55
|
+
)
|
|
56
|
+
while not stop_event.is_set():
|
|
57
|
+
retrier.invoke(wrapped_ping)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def start_ping_loop(
|
|
61
|
+
ping_fn: Callable[[], None], stop_event: threading.Event
|
|
62
|
+
) -> threading.Thread:
|
|
63
|
+
"""Start a ping loop in a separate thread.
|
|
64
|
+
|
|
65
|
+
This function initializes a new thread that runs a ping loop, allowing for
|
|
66
|
+
asynchronous ping operations. The loop can be terminated through the provided stop
|
|
67
|
+
event.
|
|
68
|
+
"""
|
|
69
|
+
thread = threading.Thread(target=_ping_loop, args=(ping_fn, stop_event))
|
|
70
|
+
thread.start()
|
|
71
|
+
|
|
72
|
+
return thread
|