flwr-nightly 1.15.0.dev20250108__py3-none-any.whl → 1.15.0.dev20250110__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/client/app.py +17 -9
- flwr/client/grpc_rere_client/client_interceptor.py +6 -0
- flwr/client/grpc_rere_client/grpc_adapter.py +16 -0
- flwr/common/grpc.py +154 -3
- flwr/proto/fleet_pb2.py +40 -27
- flwr/proto/fleet_pb2.pyi +84 -0
- flwr/proto/fleet_pb2_grpc.py +66 -0
- flwr/proto/fleet_pb2_grpc.pyi +20 -0
- flwr/server/app.py +42 -20
- flwr/server/superlink/driver/serverappio_grpc.py +1 -1
- flwr/server/superlink/driver/serverappio_servicer.py +22 -8
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +2 -165
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +16 -0
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -1
- flwr/server/superlink/linkstate/in_memory_linkstate.py +26 -22
- flwr/server/superlink/linkstate/linkstate.py +10 -4
- flwr/server/superlink/linkstate/sqlite_linkstate.py +42 -20
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
- flwr/superexec/exec_grpc.py +1 -1
- {flwr_nightly-1.15.0.dev20250108.dist-info → flwr_nightly-1.15.0.dev20250110.dist-info}/METADATA +2 -2
- {flwr_nightly-1.15.0.dev20250108.dist-info → flwr_nightly-1.15.0.dev20250110.dist-info}/RECORD +24 -24
- {flwr_nightly-1.15.0.dev20250108.dist-info → flwr_nightly-1.15.0.dev20250110.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.15.0.dev20250108.dist-info → flwr_nightly-1.15.0.dev20250110.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.15.0.dev20250108.dist-info → flwr_nightly-1.15.0.dev20250110.dist-info}/entry_points.txt +0 -0
flwr/client/app.py
CHANGED
@@ -15,13 +15,14 @@
|
|
15
15
|
"""Flower client app."""
|
16
16
|
|
17
17
|
|
18
|
+
import multiprocessing
|
18
19
|
import signal
|
19
|
-
import subprocess
|
20
20
|
import sys
|
21
21
|
import time
|
22
22
|
from contextlib import AbstractContextManager
|
23
23
|
from dataclasses import dataclass
|
24
24
|
from logging import ERROR, INFO, WARN
|
25
|
+
from os import urandom
|
25
26
|
from pathlib import Path
|
26
27
|
from typing import Callable, Optional, Union, cast
|
27
28
|
|
@@ -33,6 +34,7 @@ from flwr.cli.config_utils import get_fab_metadata
|
|
33
34
|
from flwr.cli.install import install_from_fab
|
34
35
|
from flwr.client.client import Client
|
35
36
|
from flwr.client.client_app import ClientApp, LoadClientAppError
|
37
|
+
from flwr.client.clientapp.app import flwr_clientapp
|
36
38
|
from flwr.client.nodestate.nodestate_factory import NodeStateFactory
|
37
39
|
from flwr.client.typing import ClientFnExt
|
38
40
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH, Context, EventType, Message, event
|
@@ -53,13 +55,12 @@ from flwr.common.constant import (
|
|
53
55
|
TRANSPORT_TYPES,
|
54
56
|
ErrorCode,
|
55
57
|
)
|
58
|
+
from flwr.common.grpc import generic_create_grpc_server
|
56
59
|
from flwr.common.logger import log, warn_deprecated_feature
|
57
60
|
from flwr.common.message import Error
|
58
61
|
from flwr.common.retry_invoker import RetryInvoker, RetryState, exponential
|
59
62
|
from flwr.common.typing import Fab, Run, RunNotRunningException, UserConfig
|
60
63
|
from flwr.proto.clientappio_pb2_grpc import add_ClientAppIoServicer_to_server
|
61
|
-
from flwr.server.superlink.fleet.grpc_bidi.grpc_server import generic_create_grpc_server
|
62
|
-
from flwr.server.superlink.linkstate.utils import generate_rand_int_from_bytes
|
63
64
|
|
64
65
|
from .clientapp.clientappio_servicer import ClientAppInputs, ClientAppIoServicer
|
65
66
|
from .grpc_adapter_client.connection import grpc_adapter
|
@@ -391,6 +392,7 @@ def start_client_internal(
|
|
391
392
|
run_info_store: Optional[DeprecatedRunInfoStore] = None
|
392
393
|
state_factory = NodeStateFactory()
|
393
394
|
state = state_factory.state()
|
395
|
+
mp_spawn_context = multiprocessing.get_context("spawn")
|
394
396
|
|
395
397
|
runs: dict[int, Run] = {}
|
396
398
|
|
@@ -513,7 +515,7 @@ def start_client_internal(
|
|
513
515
|
# Docker container.
|
514
516
|
|
515
517
|
# Generate SuperNode token
|
516
|
-
token
|
518
|
+
token = int.from_bytes(urandom(RUN_ID_NUM_BYTES), "little")
|
517
519
|
|
518
520
|
# Mode 1: SuperNode starts ClientApp as subprocess
|
519
521
|
start_subprocess = isolation == ISOLATION_MODE_SUBPROCESS
|
@@ -549,12 +551,13 @@ def start_client_internal(
|
|
549
551
|
]
|
550
552
|
command.append("--insecure")
|
551
553
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
check=True,
|
554
|
+
proc = mp_spawn_context.Process(
|
555
|
+
target=_run_flwr_clientapp,
|
556
|
+
args=(command,),
|
557
|
+
daemon=True,
|
557
558
|
)
|
559
|
+
proc.start()
|
560
|
+
proc.join()
|
558
561
|
else:
|
559
562
|
# Wait for output to become available
|
560
563
|
while not clientappio_servicer.has_outputs():
|
@@ -826,6 +829,11 @@ class _AppStateTracker:
|
|
826
829
|
signal.signal(signal.SIGTERM, signal_handler)
|
827
830
|
|
828
831
|
|
832
|
+
def _run_flwr_clientapp(args: list[str]) -> None:
|
833
|
+
sys.argv = args
|
834
|
+
flwr_clientapp()
|
835
|
+
|
836
|
+
|
829
837
|
def run_clientappio_api_grpc(
|
830
838
|
address: str,
|
831
839
|
certificates: Optional[tuple[bytes, bytes, bytes]],
|
@@ -36,7 +36,9 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
36
36
|
CreateNodeRequest,
|
37
37
|
DeleteNodeRequest,
|
38
38
|
PingRequest,
|
39
|
+
PullMessagesRequest,
|
39
40
|
PullTaskInsRequest,
|
41
|
+
PushMessagesRequest,
|
40
42
|
PushTaskResRequest,
|
41
43
|
)
|
42
44
|
from flwr.proto.run_pb2 import GetRunRequest # pylint: disable=E0611
|
@@ -52,6 +54,8 @@ Request = Union[
|
|
52
54
|
GetRunRequest,
|
53
55
|
PingRequest,
|
54
56
|
GetFabRequest,
|
57
|
+
PullMessagesRequest,
|
58
|
+
PushMessagesRequest,
|
55
59
|
]
|
56
60
|
|
57
61
|
|
@@ -129,6 +133,8 @@ class AuthenticateClientInterceptor(grpc.UnaryUnaryClientInterceptor): # type:
|
|
129
133
|
GetRunRequest,
|
130
134
|
PingRequest,
|
131
135
|
GetFabRequest,
|
136
|
+
PullMessagesRequest,
|
137
|
+
PushMessagesRequest,
|
132
138
|
),
|
133
139
|
):
|
134
140
|
if self.shared_secret is None:
|
@@ -40,8 +40,12 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
40
40
|
DeleteNodeResponse,
|
41
41
|
PingRequest,
|
42
42
|
PingResponse,
|
43
|
+
PullMessagesRequest,
|
44
|
+
PullMessagesResponse,
|
43
45
|
PullTaskInsRequest,
|
44
46
|
PullTaskInsResponse,
|
47
|
+
PushMessagesRequest,
|
48
|
+
PushMessagesResponse,
|
45
49
|
PushTaskResRequest,
|
46
50
|
PushTaskResResponse,
|
47
51
|
)
|
@@ -132,12 +136,24 @@ class GrpcAdapter:
|
|
132
136
|
"""."""
|
133
137
|
return self._send_and_receive(request, PullTaskInsResponse, **kwargs)
|
134
138
|
|
139
|
+
def PullMessages( # pylint: disable=C0103
|
140
|
+
self, request: PullMessagesRequest, **kwargs: Any
|
141
|
+
) -> PullMessagesResponse:
|
142
|
+
"""."""
|
143
|
+
return self._send_and_receive(request, PullMessagesResponse, **kwargs)
|
144
|
+
|
135
145
|
def PushTaskRes( # pylint: disable=C0103
|
136
146
|
self, request: PushTaskResRequest, **kwargs: Any
|
137
147
|
) -> PushTaskResResponse:
|
138
148
|
"""."""
|
139
149
|
return self._send_and_receive(request, PushTaskResResponse, **kwargs)
|
140
150
|
|
151
|
+
def PushMessages( # pylint: disable=C0103
|
152
|
+
self, request: PushMessagesRequest, **kwargs: Any
|
153
|
+
) -> PushMessagesResponse:
|
154
|
+
"""."""
|
155
|
+
return self._send_and_receive(request, PushMessagesResponse, **kwargs)
|
156
|
+
|
141
157
|
def GetRun( # pylint: disable=C0103
|
142
158
|
self, request: GetRunRequest, **kwargs: Any
|
143
159
|
) -> GetRunResponse:
|
flwr/common/grpc.py
CHANGED
@@ -15,16 +15,26 @@
|
|
15
15
|
"""Utility functions for gRPC."""
|
16
16
|
|
17
17
|
|
18
|
+
import concurrent.futures
|
19
|
+
import sys
|
18
20
|
from collections.abc import Sequence
|
19
|
-
from logging import DEBUG
|
20
|
-
from typing import Optional
|
21
|
+
from logging import DEBUG, ERROR
|
22
|
+
from typing import Any, Callable, Optional
|
21
23
|
|
22
24
|
import grpc
|
23
25
|
|
24
|
-
from
|
26
|
+
from .address import is_port_in_use
|
27
|
+
from .logger import log
|
25
28
|
|
26
29
|
GRPC_MAX_MESSAGE_LENGTH: int = 536_870_912 # == 512 * 1024 * 1024
|
27
30
|
|
31
|
+
INVALID_CERTIFICATES_ERR_MSG = """
|
32
|
+
When setting any of root_certificate, certificate, or private_key,
|
33
|
+
all of them need to be set.
|
34
|
+
"""
|
35
|
+
|
36
|
+
AddServicerToServerFn = Callable[..., Any]
|
37
|
+
|
28
38
|
|
29
39
|
def create_channel(
|
30
40
|
server_address: str,
|
@@ -66,3 +76,144 @@ def create_channel(
|
|
66
76
|
channel = grpc.intercept_channel(channel, interceptors)
|
67
77
|
|
68
78
|
return channel
|
79
|
+
|
80
|
+
|
81
|
+
def valid_certificates(certificates: tuple[bytes, bytes, bytes]) -> bool:
|
82
|
+
"""Validate certificates tuple."""
|
83
|
+
is_valid = (
|
84
|
+
all(isinstance(certificate, bytes) for certificate in certificates)
|
85
|
+
and len(certificates) == 3
|
86
|
+
)
|
87
|
+
|
88
|
+
if not is_valid:
|
89
|
+
log(ERROR, INVALID_CERTIFICATES_ERR_MSG)
|
90
|
+
|
91
|
+
return is_valid
|
92
|
+
|
93
|
+
|
94
|
+
def generic_create_grpc_server( # pylint: disable=too-many-arguments,R0917
|
95
|
+
servicer_and_add_fn: tuple[Any, AddServicerToServerFn],
|
96
|
+
server_address: str,
|
97
|
+
max_concurrent_workers: int = 1000,
|
98
|
+
max_message_length: int = GRPC_MAX_MESSAGE_LENGTH,
|
99
|
+
keepalive_time_ms: int = 210000,
|
100
|
+
certificates: Optional[tuple[bytes, bytes, bytes]] = None,
|
101
|
+
interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
|
102
|
+
) -> grpc.Server:
|
103
|
+
"""Create a gRPC server with a single servicer.
|
104
|
+
|
105
|
+
Parameters
|
106
|
+
----------
|
107
|
+
servicer_and_add_fn : tuple
|
108
|
+
A tuple holding a servicer implementation and a matching
|
109
|
+
add_Servicer_to_server function.
|
110
|
+
server_address : str
|
111
|
+
Server address in the form of HOST:PORT e.g. "[::]:8080"
|
112
|
+
max_concurrent_workers : int
|
113
|
+
Maximum number of clients the server can process before returning
|
114
|
+
RESOURCE_EXHAUSTED status (default: 1000)
|
115
|
+
max_message_length : int
|
116
|
+
Maximum message length that the server can send or receive.
|
117
|
+
Int valued in bytes. -1 means unlimited. (default: GRPC_MAX_MESSAGE_LENGTH)
|
118
|
+
keepalive_time_ms : int
|
119
|
+
Flower uses a default gRPC keepalive time of 210000ms (3 minutes 30 seconds)
|
120
|
+
because some cloud providers (for example, Azure) agressively clean up idle
|
121
|
+
TCP connections by terminating them after some time (4 minutes in the case
|
122
|
+
of Azure). Flower does not use application-level keepalive signals and relies
|
123
|
+
on the assumption that the transport layer will fail in cases where the
|
124
|
+
connection is no longer active. `keepalive_time_ms` can be used to customize
|
125
|
+
the keepalive interval for specific environments. The default Flower gRPC
|
126
|
+
keepalive of 210000 ms (3 minutes 30 seconds) ensures that Flower can keep
|
127
|
+
the long running streaming connection alive in most environments. The actual
|
128
|
+
gRPC default of this setting is 7200000 (2 hours), which results in dropped
|
129
|
+
connections in some cloud environments.
|
130
|
+
|
131
|
+
These settings are related to the issue described here:
|
132
|
+
- https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md
|
133
|
+
- https://github.com/grpc/grpc/blob/master/doc/keepalive.md
|
134
|
+
- https://grpc.io/docs/guides/performance/
|
135
|
+
|
136
|
+
Mobile Flower clients may choose to increase this value if their server
|
137
|
+
environment allows long-running idle TCP connections.
|
138
|
+
(default: 210000)
|
139
|
+
certificates : Tuple[bytes, bytes, bytes] (default: None)
|
140
|
+
Tuple containing root certificate, server certificate, and private key to
|
141
|
+
start a secure SSL-enabled server. The tuple is expected to have three bytes
|
142
|
+
elements in the following order:
|
143
|
+
|
144
|
+
* CA certificate.
|
145
|
+
* server certificate.
|
146
|
+
* server private key.
|
147
|
+
interceptors : Optional[Sequence[grpc.ServerInterceptor]] (default: None)
|
148
|
+
A list of gRPC interceptors.
|
149
|
+
|
150
|
+
Returns
|
151
|
+
-------
|
152
|
+
server : grpc.Server
|
153
|
+
A non-running instance of a gRPC server.
|
154
|
+
"""
|
155
|
+
# Check if port is in use
|
156
|
+
if is_port_in_use(server_address):
|
157
|
+
sys.exit(f"Port in server address {server_address} is already in use.")
|
158
|
+
|
159
|
+
# Deconstruct tuple into servicer and function
|
160
|
+
servicer, add_servicer_to_server_fn = servicer_and_add_fn
|
161
|
+
|
162
|
+
# Possible options:
|
163
|
+
# https://github.com/grpc/grpc/blob/v1.43.x/include/grpc/impl/codegen/grpc_types.h
|
164
|
+
options = [
|
165
|
+
# Maximum number of concurrent incoming streams to allow on a http2
|
166
|
+
# connection. Int valued.
|
167
|
+
("grpc.max_concurrent_streams", max(100, max_concurrent_workers)),
|
168
|
+
# Maximum message length that the channel can send.
|
169
|
+
# Int valued, bytes. -1 means unlimited.
|
170
|
+
("grpc.max_send_message_length", max_message_length),
|
171
|
+
# Maximum message length that the channel can receive.
|
172
|
+
# Int valued, bytes. -1 means unlimited.
|
173
|
+
("grpc.max_receive_message_length", max_message_length),
|
174
|
+
# The gRPC default for this setting is 7200000 (2 hours). Flower uses a
|
175
|
+
# customized default of 210000 (3 minutes and 30 seconds) to improve
|
176
|
+
# compatibility with popular cloud providers. Mobile Flower clients may
|
177
|
+
# choose to increase this value if their server environment allows
|
178
|
+
# long-running idle TCP connections.
|
179
|
+
("grpc.keepalive_time_ms", keepalive_time_ms),
|
180
|
+
# Setting this to zero will allow sending unlimited keepalive pings in between
|
181
|
+
# sending actual data frames.
|
182
|
+
("grpc.http2.max_pings_without_data", 0),
|
183
|
+
# Is it permissible to send keepalive pings from the client without
|
184
|
+
# any outstanding streams. More explanation here:
|
185
|
+
# https://github.com/adap/flower/pull/2197
|
186
|
+
("grpc.keepalive_permit_without_calls", 0),
|
187
|
+
]
|
188
|
+
|
189
|
+
server = grpc.server(
|
190
|
+
concurrent.futures.ThreadPoolExecutor(max_workers=max_concurrent_workers),
|
191
|
+
# Set the maximum number of concurrent RPCs this server will service before
|
192
|
+
# returning RESOURCE_EXHAUSTED status, or None to indicate no limit.
|
193
|
+
maximum_concurrent_rpcs=max_concurrent_workers,
|
194
|
+
options=options,
|
195
|
+
interceptors=interceptors,
|
196
|
+
)
|
197
|
+
add_servicer_to_server_fn(servicer, server)
|
198
|
+
|
199
|
+
if certificates is not None:
|
200
|
+
if not valid_certificates(certificates):
|
201
|
+
sys.exit(1)
|
202
|
+
|
203
|
+
root_certificate_b, certificate_b, private_key_b = certificates
|
204
|
+
|
205
|
+
server_credentials = grpc.ssl_server_credentials(
|
206
|
+
((private_key_b, certificate_b),),
|
207
|
+
root_certificates=root_certificate_b,
|
208
|
+
# A boolean indicating whether or not to require clients to be
|
209
|
+
# authenticated. May only be True if root_certificates is not None.
|
210
|
+
# We are explicitly setting the current gRPC default to document
|
211
|
+
# the option. For further reference see:
|
212
|
+
# https://grpc.github.io/grpc/python/grpc.html#create-server-credentials
|
213
|
+
require_client_auth=False,
|
214
|
+
)
|
215
|
+
server.add_secure_port(server_address, server_credentials)
|
216
|
+
else:
|
217
|
+
server.add_insecure_port(server_address)
|
218
|
+
|
219
|
+
return server
|
flwr/proto/fleet_pb2.py
CHANGED
@@ -16,9 +16,10 @@ from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
|
|
16
16
|
from flwr.proto import task_pb2 as flwr_dot_proto_dot_task__pb2
|
17
17
|
from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
|
18
18
|
from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
|
19
|
+
from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
|
19
20
|
|
20
21
|
|
21
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"*\n\x11\x43reateNodeRequest\x12\x15\n\rping_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"D\n\x0bPingRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x15\n\rping_interval\x18\x02 \x01(\x01\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"F\n\x12PullTaskInsRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"k\n\x13PullTaskInsResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rtask_ins_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"`\n\x12PushTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rtask_res_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskRes\"\xae\x01\n\x13PushTaskResResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12=\n\x07results\x18\x02 \x03(\x0b\x32,.flwr.proto.PushTaskResResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\
|
22
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"*\n\x11\x43reateNodeRequest\x12\x15\n\rping_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"D\n\x0bPingRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x15\n\rping_interval\x18\x02 \x01(\x01\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"F\n\x12PullTaskInsRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"k\n\x13PullTaskInsResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rtask_ins_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"`\n\x12PushTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rtask_res_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskRes\"\xae\x01\n\x13PushTaskResResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12=\n\x07results\x18\x02 \x03(\x0b\x32,.flwr.proto.PushTaskResResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"l\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"a\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"\xb0\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xb6\x05\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12;\n\x04Ping\x12\x17.flwr.proto.PingRequest\x1a\x18.flwr.proto.PingResponse\"\x00\x12P\n\x0bPullTaskIns\x12\x1e.flwr.proto.PullTaskInsRequest\x1a\x1f.flwr.proto.PullTaskInsResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12P\n\x0bPushTaskRes\x12\x1e.flwr.proto.PushTaskResRequest\x1a\x1f.flwr.proto.PushTaskResResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x62\x06proto3')
|
22
23
|
|
23
24
|
_globals = globals()
|
24
25
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -27,30 +28,42 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
27
28
|
DESCRIPTOR._options = None
|
28
29
|
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._options = None
|
29
30
|
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
|
30
|
-
_globals['
|
31
|
-
_globals['
|
32
|
-
_globals['
|
33
|
-
_globals['
|
34
|
-
_globals['
|
35
|
-
_globals['
|
36
|
-
_globals['
|
37
|
-
_globals['
|
38
|
-
_globals['
|
39
|
-
_globals['
|
40
|
-
_globals['
|
41
|
-
_globals['
|
42
|
-
_globals['
|
43
|
-
_globals['
|
44
|
-
_globals['
|
45
|
-
_globals['
|
46
|
-
_globals['
|
47
|
-
_globals['
|
48
|
-
_globals['
|
49
|
-
_globals['
|
50
|
-
_globals['
|
51
|
-
_globals['
|
52
|
-
_globals['
|
53
|
-
_globals['
|
54
|
-
_globals['
|
55
|
-
_globals['
|
31
|
+
_globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._options = None
|
32
|
+
_globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
|
33
|
+
_globals['_CREATENODEREQUEST']._serialized_start=154
|
34
|
+
_globals['_CREATENODEREQUEST']._serialized_end=196
|
35
|
+
_globals['_CREATENODERESPONSE']._serialized_start=198
|
36
|
+
_globals['_CREATENODERESPONSE']._serialized_end=250
|
37
|
+
_globals['_DELETENODEREQUEST']._serialized_start=252
|
38
|
+
_globals['_DELETENODEREQUEST']._serialized_end=303
|
39
|
+
_globals['_DELETENODERESPONSE']._serialized_start=305
|
40
|
+
_globals['_DELETENODERESPONSE']._serialized_end=325
|
41
|
+
_globals['_PINGREQUEST']._serialized_start=327
|
42
|
+
_globals['_PINGREQUEST']._serialized_end=395
|
43
|
+
_globals['_PINGRESPONSE']._serialized_start=397
|
44
|
+
_globals['_PINGRESPONSE']._serialized_end=428
|
45
|
+
_globals['_PULLTASKINSREQUEST']._serialized_start=430
|
46
|
+
_globals['_PULLTASKINSREQUEST']._serialized_end=500
|
47
|
+
_globals['_PULLTASKINSRESPONSE']._serialized_start=502
|
48
|
+
_globals['_PULLTASKINSRESPONSE']._serialized_end=609
|
49
|
+
_globals['_PUSHTASKRESREQUEST']._serialized_start=611
|
50
|
+
_globals['_PUSHTASKRESREQUEST']._serialized_end=707
|
51
|
+
_globals['_PUSHTASKRESRESPONSE']._serialized_start=710
|
52
|
+
_globals['_PUSHTASKRESRESPONSE']._serialized_end=884
|
53
|
+
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_start=838
|
54
|
+
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_end=884
|
55
|
+
_globals['_PULLMESSAGESREQUEST']._serialized_start=886
|
56
|
+
_globals['_PULLMESSAGESREQUEST']._serialized_end=960
|
57
|
+
_globals['_PULLMESSAGESRESPONSE']._serialized_start=962
|
58
|
+
_globals['_PULLMESSAGESRESPONSE']._serialized_end=1070
|
59
|
+
_globals['_PUSHMESSAGESREQUEST']._serialized_start=1072
|
60
|
+
_globals['_PUSHMESSAGESREQUEST']._serialized_end=1169
|
61
|
+
_globals['_PUSHMESSAGESRESPONSE']._serialized_start=1172
|
62
|
+
_globals['_PUSHMESSAGESRESPONSE']._serialized_end=1348
|
63
|
+
_globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=838
|
64
|
+
_globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=884
|
65
|
+
_globals['_RECONNECT']._serialized_start=1350
|
66
|
+
_globals['_RECONNECT']._serialized_end=1380
|
67
|
+
_globals['_FLEET']._serialized_start=1383
|
68
|
+
_globals['_FLEET']._serialized_end=2077
|
56
69
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/fleet_pb2.pyi
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
isort:skip_file
|
4
4
|
"""
|
5
5
|
import builtins
|
6
|
+
import flwr.proto.message_pb2
|
6
7
|
import flwr.proto.node_pb2
|
7
8
|
import flwr.proto.task_pb2
|
8
9
|
import google.protobuf.descriptor
|
@@ -169,6 +170,89 @@ class PushTaskResResponse(google.protobuf.message.Message):
|
|
169
170
|
def ClearField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect","results",b"results"]) -> None: ...
|
170
171
|
global___PushTaskResResponse = PushTaskResResponse
|
171
172
|
|
173
|
+
class PullMessagesRequest(google.protobuf.message.Message):
|
174
|
+
"""PullMessages messages"""
|
175
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
176
|
+
NODE_FIELD_NUMBER: builtins.int
|
177
|
+
MESSAGE_IDS_FIELD_NUMBER: builtins.int
|
178
|
+
@property
|
179
|
+
def node(self) -> flwr.proto.node_pb2.Node: ...
|
180
|
+
@property
|
181
|
+
def message_ids(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ...
|
182
|
+
def __init__(self,
|
183
|
+
*,
|
184
|
+
node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
|
185
|
+
message_ids: typing.Optional[typing.Iterable[typing.Text]] = ...,
|
186
|
+
) -> None: ...
|
187
|
+
def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
|
188
|
+
def ClearField(self, field_name: typing_extensions.Literal["message_ids",b"message_ids","node",b"node"]) -> None: ...
|
189
|
+
global___PullMessagesRequest = PullMessagesRequest
|
190
|
+
|
191
|
+
class PullMessagesResponse(google.protobuf.message.Message):
|
192
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
193
|
+
RECONNECT_FIELD_NUMBER: builtins.int
|
194
|
+
MESSAGES_LIST_FIELD_NUMBER: builtins.int
|
195
|
+
@property
|
196
|
+
def reconnect(self) -> global___Reconnect: ...
|
197
|
+
@property
|
198
|
+
def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
|
199
|
+
def __init__(self,
|
200
|
+
*,
|
201
|
+
reconnect: typing.Optional[global___Reconnect] = ...,
|
202
|
+
messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
|
203
|
+
) -> None: ...
|
204
|
+
def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
|
205
|
+
def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","reconnect",b"reconnect"]) -> None: ...
|
206
|
+
global___PullMessagesResponse = PullMessagesResponse
|
207
|
+
|
208
|
+
class PushMessagesRequest(google.protobuf.message.Message):
|
209
|
+
"""PushMessages messages"""
|
210
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
211
|
+
NODE_FIELD_NUMBER: builtins.int
|
212
|
+
MESSAGES_LIST_FIELD_NUMBER: builtins.int
|
213
|
+
@property
|
214
|
+
def node(self) -> flwr.proto.node_pb2.Node: ...
|
215
|
+
@property
|
216
|
+
def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
|
217
|
+
def __init__(self,
|
218
|
+
*,
|
219
|
+
node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
|
220
|
+
messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
|
221
|
+
) -> None: ...
|
222
|
+
def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
|
223
|
+
def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","node",b"node"]) -> None: ...
|
224
|
+
global___PushMessagesRequest = PushMessagesRequest
|
225
|
+
|
226
|
+
class PushMessagesResponse(google.protobuf.message.Message):
|
227
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
228
|
+
class ResultsEntry(google.protobuf.message.Message):
|
229
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
230
|
+
KEY_FIELD_NUMBER: builtins.int
|
231
|
+
VALUE_FIELD_NUMBER: builtins.int
|
232
|
+
key: typing.Text
|
233
|
+
value: builtins.int
|
234
|
+
def __init__(self,
|
235
|
+
*,
|
236
|
+
key: typing.Text = ...,
|
237
|
+
value: builtins.int = ...,
|
238
|
+
) -> None: ...
|
239
|
+
def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
|
240
|
+
|
241
|
+
RECONNECT_FIELD_NUMBER: builtins.int
|
242
|
+
RESULTS_FIELD_NUMBER: builtins.int
|
243
|
+
@property
|
244
|
+
def reconnect(self) -> global___Reconnect: ...
|
245
|
+
@property
|
246
|
+
def results(self) -> google.protobuf.internal.containers.ScalarMap[typing.Text, builtins.int]: ...
|
247
|
+
def __init__(self,
|
248
|
+
*,
|
249
|
+
reconnect: typing.Optional[global___Reconnect] = ...,
|
250
|
+
results: typing.Optional[typing.Mapping[typing.Text, builtins.int]] = ...,
|
251
|
+
) -> None: ...
|
252
|
+
def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
|
253
|
+
def ClearField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect","results",b"results"]) -> None: ...
|
254
|
+
global___PushMessagesResponse = PushMessagesResponse
|
255
|
+
|
172
256
|
class Reconnect(google.protobuf.message.Message):
|
173
257
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
174
258
|
RECONNECT_FIELD_NUMBER: builtins.int
|
flwr/proto/fleet_pb2_grpc.py
CHANGED
@@ -36,11 +36,21 @@ class FleetStub(object):
|
|
36
36
|
request_serializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsRequest.SerializeToString,
|
37
37
|
response_deserializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsResponse.FromString,
|
38
38
|
)
|
39
|
+
self.PullMessages = channel.unary_unary(
|
40
|
+
'/flwr.proto.Fleet/PullMessages',
|
41
|
+
request_serializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesRequest.SerializeToString,
|
42
|
+
response_deserializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesResponse.FromString,
|
43
|
+
)
|
39
44
|
self.PushTaskRes = channel.unary_unary(
|
40
45
|
'/flwr.proto.Fleet/PushTaskRes',
|
41
46
|
request_serializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResRequest.SerializeToString,
|
42
47
|
response_deserializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResResponse.FromString,
|
43
48
|
)
|
49
|
+
self.PushMessages = channel.unary_unary(
|
50
|
+
'/flwr.proto.Fleet/PushMessages',
|
51
|
+
request_serializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesRequest.SerializeToString,
|
52
|
+
response_deserializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesResponse.FromString,
|
53
|
+
)
|
44
54
|
self.GetRun = channel.unary_unary(
|
45
55
|
'/flwr.proto.Fleet/GetRun',
|
46
56
|
request_serializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.SerializeToString,
|
@@ -83,6 +93,12 @@ class FleetServicer(object):
|
|
83
93
|
context.set_details('Method not implemented!')
|
84
94
|
raise NotImplementedError('Method not implemented!')
|
85
95
|
|
96
|
+
def PullMessages(self, request, context):
|
97
|
+
"""Missing associated documentation comment in .proto file."""
|
98
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
99
|
+
context.set_details('Method not implemented!')
|
100
|
+
raise NotImplementedError('Method not implemented!')
|
101
|
+
|
86
102
|
def PushTaskRes(self, request, context):
|
87
103
|
"""Complete one or more tasks, if possible
|
88
104
|
|
@@ -92,6 +108,12 @@ class FleetServicer(object):
|
|
92
108
|
context.set_details('Method not implemented!')
|
93
109
|
raise NotImplementedError('Method not implemented!')
|
94
110
|
|
111
|
+
def PushMessages(self, request, context):
|
112
|
+
"""Missing associated documentation comment in .proto file."""
|
113
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
114
|
+
context.set_details('Method not implemented!')
|
115
|
+
raise NotImplementedError('Method not implemented!')
|
116
|
+
|
95
117
|
def GetRun(self, request, context):
|
96
118
|
"""Missing associated documentation comment in .proto file."""
|
97
119
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
@@ -128,11 +150,21 @@ def add_FleetServicer_to_server(servicer, server):
|
|
128
150
|
request_deserializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsRequest.FromString,
|
129
151
|
response_serializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsResponse.SerializeToString,
|
130
152
|
),
|
153
|
+
'PullMessages': grpc.unary_unary_rpc_method_handler(
|
154
|
+
servicer.PullMessages,
|
155
|
+
request_deserializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesRequest.FromString,
|
156
|
+
response_serializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesResponse.SerializeToString,
|
157
|
+
),
|
131
158
|
'PushTaskRes': grpc.unary_unary_rpc_method_handler(
|
132
159
|
servicer.PushTaskRes,
|
133
160
|
request_deserializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResRequest.FromString,
|
134
161
|
response_serializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResResponse.SerializeToString,
|
135
162
|
),
|
163
|
+
'PushMessages': grpc.unary_unary_rpc_method_handler(
|
164
|
+
servicer.PushMessages,
|
165
|
+
request_deserializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesRequest.FromString,
|
166
|
+
response_serializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesResponse.SerializeToString,
|
167
|
+
),
|
136
168
|
'GetRun': grpc.unary_unary_rpc_method_handler(
|
137
169
|
servicer.GetRun,
|
138
170
|
request_deserializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.FromString,
|
@@ -221,6 +253,23 @@ class Fleet(object):
|
|
221
253
|
options, channel_credentials,
|
222
254
|
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
223
255
|
|
256
|
+
@staticmethod
|
257
|
+
def PullMessages(request,
|
258
|
+
target,
|
259
|
+
options=(),
|
260
|
+
channel_credentials=None,
|
261
|
+
call_credentials=None,
|
262
|
+
insecure=False,
|
263
|
+
compression=None,
|
264
|
+
wait_for_ready=None,
|
265
|
+
timeout=None,
|
266
|
+
metadata=None):
|
267
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.Fleet/PullMessages',
|
268
|
+
flwr_dot_proto_dot_fleet__pb2.PullMessagesRequest.SerializeToString,
|
269
|
+
flwr_dot_proto_dot_fleet__pb2.PullMessagesResponse.FromString,
|
270
|
+
options, channel_credentials,
|
271
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
272
|
+
|
224
273
|
@staticmethod
|
225
274
|
def PushTaskRes(request,
|
226
275
|
target,
|
@@ -238,6 +287,23 @@ class Fleet(object):
|
|
238
287
|
options, channel_credentials,
|
239
288
|
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
240
289
|
|
290
|
+
@staticmethod
|
291
|
+
def PushMessages(request,
|
292
|
+
target,
|
293
|
+
options=(),
|
294
|
+
channel_credentials=None,
|
295
|
+
call_credentials=None,
|
296
|
+
insecure=False,
|
297
|
+
compression=None,
|
298
|
+
wait_for_ready=None,
|
299
|
+
timeout=None,
|
300
|
+
metadata=None):
|
301
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.Fleet/PushMessages',
|
302
|
+
flwr_dot_proto_dot_fleet__pb2.PushMessagesRequest.SerializeToString,
|
303
|
+
flwr_dot_proto_dot_fleet__pb2.PushMessagesResponse.FromString,
|
304
|
+
options, channel_credentials,
|
305
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
306
|
+
|
241
307
|
@staticmethod
|
242
308
|
def GetRun(request,
|
243
309
|
target,
|