flwr-nightly 1.13.0.dev20241023__py3-none-any.whl → 1.13.0.dev20241024__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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/proto/driver_pb2.py +24 -15
- flwr/proto/driver_pb2.pyi +59 -0
- flwr/proto/driver_pb2_grpc.py +68 -0
- flwr/proto/driver_pb2_grpc.pyi +26 -0
- flwr/server/app.py +4 -2
- flwr/server/run_serverapp.py +13 -9
- flwr/server/superlink/driver/driver_servicer.py +16 -0
- flwr/server/superlink/linkstate/in_memory_linkstate.py +12 -1
- flwr/server/superlink/linkstate/linkstate.py +29 -0
- flwr/server/superlink/linkstate/sqlite_linkstate.py +51 -6
- flwr/server/superlink/linkstate/utils.py +12 -1
- flwr/simulation/run_simulation.py +12 -4
- flwr/superexec/app.py +3 -138
- flwr/superexec/deployment.py +34 -25
- flwr/superexec/exec_grpc.py +15 -8
- flwr/superexec/exec_servicer.py +11 -1
- flwr/superexec/executor.py +19 -0
- flwr/superexec/simulation.py +8 -0
- {flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/METADATA +1 -1
- {flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/RECORD +23 -24
- flwr/client/node_state_tests.py +0 -65
- {flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/entry_points.txt +0 -0
flwr/proto/driver_pb2.py
CHANGED
|
@@ -13,30 +13,39 @@ _sym_db = _symbol_database.Default()
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
|
|
16
|
+
from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
|
|
16
17
|
from flwr.proto import task_pb2 as flwr_dot_proto_dot_task__pb2
|
|
17
18
|
from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
|
|
18
19
|
from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66lwr/proto/driver.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\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"@\n\x12PushTaskInsRequest\x12*\n\rtask_ins_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"\'\n\x13PushTaskInsResponse\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"F\n\x12PullTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"A\n\x13PullTaskResResponse\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.
|
|
22
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66lwr/proto/driver.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x15\x66lwr/proto/task.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"@\n\x12PushTaskInsRequest\x12*\n\rtask_ins_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"\'\n\x13PushTaskInsResponse\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"F\n\x12PullTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"A\n\x13PullTaskResResponse\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes\",\n\x1aPullServerAppInputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"\x7f\n\x1bPullServerAppInputsResponse\x12$\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Fab\"S\n\x1bPushServerAppOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1e\n\x1cPushServerAppOutputsResponse2\x9e\x05\n\x06\x44river\x12J\n\tCreateRun\x12\x1c.flwr.proto.CreateRunRequest\x1a\x1d.flwr.proto.CreateRunResponse\"\x00\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12P\n\x0bPushTaskIns\x12\x1e.flwr.proto.PushTaskInsRequest\x1a\x1f.flwr.proto.PushTaskInsResponse\"\x00\x12P\n\x0bPullTaskRes\x12\x1e.flwr.proto.PullTaskResRequest\x1a\x1f.flwr.proto.PullTaskResResponse\"\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\x12h\n\x13PullServerAppInputs\x12&.flwr.proto.PullServerAppInputsRequest\x1a\'.flwr.proto.PullServerAppInputsResponse\"\x00\x12k\n\x14PushServerAppOutputs\x12\'.flwr.proto.PushServerAppOutputsRequest\x1a(.flwr.proto.PushServerAppOutputsResponse\"\x00\x62\x06proto3')
|
|
22
23
|
|
|
23
24
|
_globals = globals()
|
|
24
25
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
25
26
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.driver_pb2', _globals)
|
|
26
27
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
27
28
|
DESCRIPTOR._options = None
|
|
28
|
-
_globals['_GETNODESREQUEST']._serialized_start=
|
|
29
|
-
_globals['_GETNODESREQUEST']._serialized_end=
|
|
30
|
-
_globals['_GETNODESRESPONSE']._serialized_start=
|
|
31
|
-
_globals['_GETNODESRESPONSE']._serialized_end=
|
|
32
|
-
_globals['_PUSHTASKINSREQUEST']._serialized_start=
|
|
33
|
-
_globals['_PUSHTASKINSREQUEST']._serialized_end=
|
|
34
|
-
_globals['_PUSHTASKINSRESPONSE']._serialized_start=
|
|
35
|
-
_globals['_PUSHTASKINSRESPONSE']._serialized_end=
|
|
36
|
-
_globals['_PULLTASKRESREQUEST']._serialized_start=
|
|
37
|
-
_globals['_PULLTASKRESREQUEST']._serialized_end=
|
|
38
|
-
_globals['_PULLTASKRESRESPONSE']._serialized_start=
|
|
39
|
-
_globals['_PULLTASKRESRESPONSE']._serialized_end=
|
|
40
|
-
_globals['
|
|
41
|
-
_globals['
|
|
29
|
+
_globals['_GETNODESREQUEST']._serialized_start=155
|
|
30
|
+
_globals['_GETNODESREQUEST']._serialized_end=188
|
|
31
|
+
_globals['_GETNODESRESPONSE']._serialized_start=190
|
|
32
|
+
_globals['_GETNODESRESPONSE']._serialized_end=241
|
|
33
|
+
_globals['_PUSHTASKINSREQUEST']._serialized_start=243
|
|
34
|
+
_globals['_PUSHTASKINSREQUEST']._serialized_end=307
|
|
35
|
+
_globals['_PUSHTASKINSRESPONSE']._serialized_start=309
|
|
36
|
+
_globals['_PUSHTASKINSRESPONSE']._serialized_end=348
|
|
37
|
+
_globals['_PULLTASKRESREQUEST']._serialized_start=350
|
|
38
|
+
_globals['_PULLTASKRESREQUEST']._serialized_end=420
|
|
39
|
+
_globals['_PULLTASKRESRESPONSE']._serialized_start=422
|
|
40
|
+
_globals['_PULLTASKRESRESPONSE']._serialized_end=487
|
|
41
|
+
_globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_start=489
|
|
42
|
+
_globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_end=533
|
|
43
|
+
_globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_start=535
|
|
44
|
+
_globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_end=662
|
|
45
|
+
_globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_start=664
|
|
46
|
+
_globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_end=747
|
|
47
|
+
_globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_start=749
|
|
48
|
+
_globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_end=779
|
|
49
|
+
_globals['_DRIVER']._serialized_start=782
|
|
50
|
+
_globals['_DRIVER']._serialized_end=1452
|
|
42
51
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/driver_pb2.pyi
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
isort:skip_file
|
|
4
4
|
"""
|
|
5
5
|
import builtins
|
|
6
|
+
import flwr.proto.fab_pb2
|
|
7
|
+
import flwr.proto.message_pb2
|
|
6
8
|
import flwr.proto.node_pb2
|
|
9
|
+
import flwr.proto.run_pb2
|
|
7
10
|
import flwr.proto.task_pb2
|
|
8
11
|
import google.protobuf.descriptor
|
|
9
12
|
import google.protobuf.internal.containers
|
|
@@ -91,3 +94,59 @@ class PullTaskResResponse(google.protobuf.message.Message):
|
|
|
91
94
|
) -> None: ...
|
|
92
95
|
def ClearField(self, field_name: typing_extensions.Literal["task_res_list",b"task_res_list"]) -> None: ...
|
|
93
96
|
global___PullTaskResResponse = PullTaskResResponse
|
|
97
|
+
|
|
98
|
+
class PullServerAppInputsRequest(google.protobuf.message.Message):
|
|
99
|
+
"""PullServerAppInputs messages"""
|
|
100
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
101
|
+
RUN_ID_FIELD_NUMBER: builtins.int
|
|
102
|
+
run_id: builtins.int
|
|
103
|
+
def __init__(self,
|
|
104
|
+
*,
|
|
105
|
+
run_id: builtins.int = ...,
|
|
106
|
+
) -> None: ...
|
|
107
|
+
def ClearField(self, field_name: typing_extensions.Literal["run_id",b"run_id"]) -> None: ...
|
|
108
|
+
global___PullServerAppInputsRequest = PullServerAppInputsRequest
|
|
109
|
+
|
|
110
|
+
class PullServerAppInputsResponse(google.protobuf.message.Message):
|
|
111
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
112
|
+
CONTEXT_FIELD_NUMBER: builtins.int
|
|
113
|
+
RUN_FIELD_NUMBER: builtins.int
|
|
114
|
+
FAB_FIELD_NUMBER: builtins.int
|
|
115
|
+
@property
|
|
116
|
+
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
117
|
+
@property
|
|
118
|
+
def run(self) -> flwr.proto.run_pb2.Run: ...
|
|
119
|
+
@property
|
|
120
|
+
def fab(self) -> flwr.proto.fab_pb2.Fab: ...
|
|
121
|
+
def __init__(self,
|
|
122
|
+
*,
|
|
123
|
+
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
124
|
+
run: typing.Optional[flwr.proto.run_pb2.Run] = ...,
|
|
125
|
+
fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
|
|
126
|
+
) -> None: ...
|
|
127
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","run",b"run"]) -> builtins.bool: ...
|
|
128
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","run",b"run"]) -> None: ...
|
|
129
|
+
global___PullServerAppInputsResponse = PullServerAppInputsResponse
|
|
130
|
+
|
|
131
|
+
class PushServerAppOutputsRequest(google.protobuf.message.Message):
|
|
132
|
+
"""PushServerAppOutputs messages"""
|
|
133
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
134
|
+
RUN_ID_FIELD_NUMBER: builtins.int
|
|
135
|
+
CONTEXT_FIELD_NUMBER: builtins.int
|
|
136
|
+
run_id: builtins.int
|
|
137
|
+
@property
|
|
138
|
+
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
139
|
+
def __init__(self,
|
|
140
|
+
*,
|
|
141
|
+
run_id: builtins.int = ...,
|
|
142
|
+
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
143
|
+
) -> None: ...
|
|
144
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context"]) -> builtins.bool: ...
|
|
145
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","run_id",b"run_id"]) -> None: ...
|
|
146
|
+
global___PushServerAppOutputsRequest = PushServerAppOutputsRequest
|
|
147
|
+
|
|
148
|
+
class PushServerAppOutputsResponse(google.protobuf.message.Message):
|
|
149
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
150
|
+
def __init__(self,
|
|
151
|
+
) -> None: ...
|
|
152
|
+
global___PushServerAppOutputsResponse = PushServerAppOutputsResponse
|
flwr/proto/driver_pb2_grpc.py
CHANGED
|
@@ -46,6 +46,16 @@ class DriverStub(object):
|
|
|
46
46
|
request_serializer=flwr_dot_proto_dot_fab__pb2.GetFabRequest.SerializeToString,
|
|
47
47
|
response_deserializer=flwr_dot_proto_dot_fab__pb2.GetFabResponse.FromString,
|
|
48
48
|
)
|
|
49
|
+
self.PullServerAppInputs = channel.unary_unary(
|
|
50
|
+
'/flwr.proto.Driver/PullServerAppInputs',
|
|
51
|
+
request_serializer=flwr_dot_proto_dot_driver__pb2.PullServerAppInputsRequest.SerializeToString,
|
|
52
|
+
response_deserializer=flwr_dot_proto_dot_driver__pb2.PullServerAppInputsResponse.FromString,
|
|
53
|
+
)
|
|
54
|
+
self.PushServerAppOutputs = channel.unary_unary(
|
|
55
|
+
'/flwr.proto.Driver/PushServerAppOutputs',
|
|
56
|
+
request_serializer=flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsRequest.SerializeToString,
|
|
57
|
+
response_deserializer=flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsResponse.FromString,
|
|
58
|
+
)
|
|
49
59
|
|
|
50
60
|
|
|
51
61
|
class DriverServicer(object):
|
|
@@ -93,6 +103,20 @@ class DriverServicer(object):
|
|
|
93
103
|
context.set_details('Method not implemented!')
|
|
94
104
|
raise NotImplementedError('Method not implemented!')
|
|
95
105
|
|
|
106
|
+
def PullServerAppInputs(self, request, context):
|
|
107
|
+
"""Pull ServerApp inputs
|
|
108
|
+
"""
|
|
109
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
110
|
+
context.set_details('Method not implemented!')
|
|
111
|
+
raise NotImplementedError('Method not implemented!')
|
|
112
|
+
|
|
113
|
+
def PushServerAppOutputs(self, request, context):
|
|
114
|
+
"""Push ServerApp outputs
|
|
115
|
+
"""
|
|
116
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
117
|
+
context.set_details('Method not implemented!')
|
|
118
|
+
raise NotImplementedError('Method not implemented!')
|
|
119
|
+
|
|
96
120
|
|
|
97
121
|
def add_DriverServicer_to_server(servicer, server):
|
|
98
122
|
rpc_method_handlers = {
|
|
@@ -126,6 +150,16 @@ def add_DriverServicer_to_server(servicer, server):
|
|
|
126
150
|
request_deserializer=flwr_dot_proto_dot_fab__pb2.GetFabRequest.FromString,
|
|
127
151
|
response_serializer=flwr_dot_proto_dot_fab__pb2.GetFabResponse.SerializeToString,
|
|
128
152
|
),
|
|
153
|
+
'PullServerAppInputs': grpc.unary_unary_rpc_method_handler(
|
|
154
|
+
servicer.PullServerAppInputs,
|
|
155
|
+
request_deserializer=flwr_dot_proto_dot_driver__pb2.PullServerAppInputsRequest.FromString,
|
|
156
|
+
response_serializer=flwr_dot_proto_dot_driver__pb2.PullServerAppInputsResponse.SerializeToString,
|
|
157
|
+
),
|
|
158
|
+
'PushServerAppOutputs': grpc.unary_unary_rpc_method_handler(
|
|
159
|
+
servicer.PushServerAppOutputs,
|
|
160
|
+
request_deserializer=flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsRequest.FromString,
|
|
161
|
+
response_serializer=flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsResponse.SerializeToString,
|
|
162
|
+
),
|
|
129
163
|
}
|
|
130
164
|
generic_handler = grpc.method_handlers_generic_handler(
|
|
131
165
|
'flwr.proto.Driver', rpc_method_handlers)
|
|
@@ -237,3 +271,37 @@ class Driver(object):
|
|
|
237
271
|
flwr_dot_proto_dot_fab__pb2.GetFabResponse.FromString,
|
|
238
272
|
options, channel_credentials,
|
|
239
273
|
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
274
|
+
|
|
275
|
+
@staticmethod
|
|
276
|
+
def PullServerAppInputs(request,
|
|
277
|
+
target,
|
|
278
|
+
options=(),
|
|
279
|
+
channel_credentials=None,
|
|
280
|
+
call_credentials=None,
|
|
281
|
+
insecure=False,
|
|
282
|
+
compression=None,
|
|
283
|
+
wait_for_ready=None,
|
|
284
|
+
timeout=None,
|
|
285
|
+
metadata=None):
|
|
286
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.Driver/PullServerAppInputs',
|
|
287
|
+
flwr_dot_proto_dot_driver__pb2.PullServerAppInputsRequest.SerializeToString,
|
|
288
|
+
flwr_dot_proto_dot_driver__pb2.PullServerAppInputsResponse.FromString,
|
|
289
|
+
options, channel_credentials,
|
|
290
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
291
|
+
|
|
292
|
+
@staticmethod
|
|
293
|
+
def PushServerAppOutputs(request,
|
|
294
|
+
target,
|
|
295
|
+
options=(),
|
|
296
|
+
channel_credentials=None,
|
|
297
|
+
call_credentials=None,
|
|
298
|
+
insecure=False,
|
|
299
|
+
compression=None,
|
|
300
|
+
wait_for_ready=None,
|
|
301
|
+
timeout=None,
|
|
302
|
+
metadata=None):
|
|
303
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.Driver/PushServerAppOutputs',
|
|
304
|
+
flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsRequest.SerializeToString,
|
|
305
|
+
flwr_dot_proto_dot_driver__pb2.PushServerAppOutputsResponse.FromString,
|
|
306
|
+
options, channel_credentials,
|
|
307
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
flwr/proto/driver_pb2_grpc.pyi
CHANGED
|
@@ -40,6 +40,16 @@ class DriverStub:
|
|
|
40
40
|
flwr.proto.fab_pb2.GetFabResponse]
|
|
41
41
|
"""Get FAB"""
|
|
42
42
|
|
|
43
|
+
PullServerAppInputs: grpc.UnaryUnaryMultiCallable[
|
|
44
|
+
flwr.proto.driver_pb2.PullServerAppInputsRequest,
|
|
45
|
+
flwr.proto.driver_pb2.PullServerAppInputsResponse]
|
|
46
|
+
"""Pull ServerApp inputs"""
|
|
47
|
+
|
|
48
|
+
PushServerAppOutputs: grpc.UnaryUnaryMultiCallable[
|
|
49
|
+
flwr.proto.driver_pb2.PushServerAppOutputsRequest,
|
|
50
|
+
flwr.proto.driver_pb2.PushServerAppOutputsResponse]
|
|
51
|
+
"""Push ServerApp outputs"""
|
|
52
|
+
|
|
43
53
|
|
|
44
54
|
class DriverServicer(metaclass=abc.ABCMeta):
|
|
45
55
|
@abc.abstractmethod
|
|
@@ -90,5 +100,21 @@ class DriverServicer(metaclass=abc.ABCMeta):
|
|
|
90
100
|
"""Get FAB"""
|
|
91
101
|
pass
|
|
92
102
|
|
|
103
|
+
@abc.abstractmethod
|
|
104
|
+
def PullServerAppInputs(self,
|
|
105
|
+
request: flwr.proto.driver_pb2.PullServerAppInputsRequest,
|
|
106
|
+
context: grpc.ServicerContext,
|
|
107
|
+
) -> flwr.proto.driver_pb2.PullServerAppInputsResponse:
|
|
108
|
+
"""Pull ServerApp inputs"""
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
@abc.abstractmethod
|
|
112
|
+
def PushServerAppOutputs(self,
|
|
113
|
+
request: flwr.proto.driver_pb2.PushServerAppOutputsRequest,
|
|
114
|
+
context: grpc.ServicerContext,
|
|
115
|
+
) -> flwr.proto.driver_pb2.PushServerAppOutputsResponse:
|
|
116
|
+
"""Push ServerApp outputs"""
|
|
117
|
+
pass
|
|
118
|
+
|
|
93
119
|
|
|
94
120
|
def add_DriverServicer_to_server(servicer: DriverServicer, server: grpc.Server) -> None: ...
|
flwr/server/app.py
CHANGED
|
@@ -64,7 +64,7 @@ from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
|
|
|
64
64
|
)
|
|
65
65
|
from flwr.proto.grpcadapter_pb2_grpc import add_GrpcAdapterServicer_to_server
|
|
66
66
|
from flwr.superexec.app import load_executor
|
|
67
|
-
from flwr.superexec.exec_grpc import
|
|
67
|
+
from flwr.superexec.exec_grpc import run_exec_api_grpc
|
|
68
68
|
|
|
69
69
|
from .client_manager import ClientManager
|
|
70
70
|
from .history import History
|
|
@@ -329,8 +329,10 @@ def run_superlink() -> None:
|
|
|
329
329
|
raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
|
|
330
330
|
|
|
331
331
|
# Start Exec API
|
|
332
|
-
exec_server: grpc.Server =
|
|
332
|
+
exec_server: grpc.Server = run_exec_api_grpc(
|
|
333
333
|
address=exec_address,
|
|
334
|
+
state_factory=state_factory,
|
|
335
|
+
ffs_factory=ffs_factory,
|
|
334
336
|
executor=load_executor(args),
|
|
335
337
|
certificates=certificates,
|
|
336
338
|
config=parse_config_args(
|
flwr/server/run_serverapp.py
CHANGED
|
@@ -34,7 +34,6 @@ from flwr.common.config import (
|
|
|
34
34
|
from flwr.common.constant import DRIVER_API_DEFAULT_ADDRESS
|
|
35
35
|
from flwr.common.logger import log, update_console_handler, warn_deprecated_feature
|
|
36
36
|
from flwr.common.object_ref import load_app
|
|
37
|
-
from flwr.common.typing import UserConfig
|
|
38
37
|
from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
|
|
39
38
|
from flwr.proto.run_pb2 import ( # pylint: disable=E0611
|
|
40
39
|
CreateRunRequest,
|
|
@@ -46,13 +45,14 @@ from .driver.grpc_driver import GrpcDriver
|
|
|
46
45
|
from .server_app import LoadServerAppError, ServerApp
|
|
47
46
|
|
|
48
47
|
|
|
48
|
+
# pylint: disable-next=too-many-arguments,too-many-positional-arguments
|
|
49
49
|
def run(
|
|
50
50
|
driver: Driver,
|
|
51
|
+
context: Context,
|
|
51
52
|
server_app_dir: str,
|
|
52
|
-
server_app_run_config: UserConfig,
|
|
53
53
|
server_app_attr: Optional[str] = None,
|
|
54
54
|
loaded_server_app: Optional[ServerApp] = None,
|
|
55
|
-
) ->
|
|
55
|
+
) -> Context:
|
|
56
56
|
"""Run ServerApp with a given Driver."""
|
|
57
57
|
if not (server_app_attr is None) ^ (loaded_server_app is None):
|
|
58
58
|
raise ValueError(
|
|
@@ -78,15 +78,11 @@ def run(
|
|
|
78
78
|
|
|
79
79
|
server_app = _load()
|
|
80
80
|
|
|
81
|
-
# Initialize Context
|
|
82
|
-
context = Context(
|
|
83
|
-
node_id=0, node_config={}, state=RecordSet(), run_config=server_app_run_config
|
|
84
|
-
)
|
|
85
|
-
|
|
86
81
|
# Call ServerApp
|
|
87
82
|
server_app(driver=driver, context=context)
|
|
88
83
|
|
|
89
84
|
log(DEBUG, "ServerApp finished running.")
|
|
85
|
+
return context
|
|
90
86
|
|
|
91
87
|
|
|
92
88
|
# pylint: disable-next=too-many-branches,too-many-statements,too-many-locals
|
|
@@ -225,11 +221,19 @@ def run_server_app() -> None:
|
|
|
225
221
|
root_certificates,
|
|
226
222
|
)
|
|
227
223
|
|
|
224
|
+
# Initialize Context
|
|
225
|
+
context = Context(
|
|
226
|
+
node_id=0,
|
|
227
|
+
node_config={},
|
|
228
|
+
state=RecordSet(),
|
|
229
|
+
run_config=server_app_run_config,
|
|
230
|
+
)
|
|
231
|
+
|
|
228
232
|
# Run the ServerApp with the Driver
|
|
229
233
|
run(
|
|
230
234
|
driver=driver,
|
|
235
|
+
context=context,
|
|
231
236
|
server_app_dir=app_path,
|
|
232
|
-
server_app_run_config=server_app_run_config,
|
|
233
237
|
server_app_attr=server_app_attr,
|
|
234
238
|
)
|
|
235
239
|
|
|
@@ -34,8 +34,12 @@ from flwr.proto import driver_pb2_grpc # pylint: disable=E0611
|
|
|
34
34
|
from flwr.proto.driver_pb2 import ( # pylint: disable=E0611
|
|
35
35
|
GetNodesRequest,
|
|
36
36
|
GetNodesResponse,
|
|
37
|
+
PullServerAppInputsRequest,
|
|
38
|
+
PullServerAppInputsResponse,
|
|
37
39
|
PullTaskResRequest,
|
|
38
40
|
PullTaskResResponse,
|
|
41
|
+
PushServerAppOutputsRequest,
|
|
42
|
+
PushServerAppOutputsResponse,
|
|
39
43
|
PushTaskInsRequest,
|
|
40
44
|
PushTaskInsResponse,
|
|
41
45
|
)
|
|
@@ -200,6 +204,18 @@ class DriverServicer(driver_pb2_grpc.DriverServicer):
|
|
|
200
204
|
|
|
201
205
|
raise ValueError(f"Found no FAB with hash: {request.hash_str}")
|
|
202
206
|
|
|
207
|
+
def PullServerAppInputs(
|
|
208
|
+
self, request: PullServerAppInputsRequest, context: grpc.ServicerContext
|
|
209
|
+
) -> PullServerAppInputsResponse:
|
|
210
|
+
"""Pull ServerApp process inputs."""
|
|
211
|
+
raise NotImplementedError()
|
|
212
|
+
|
|
213
|
+
def PushServerAppOutputs(
|
|
214
|
+
self, request: PushServerAppOutputsRequest, context: grpc.ServicerContext
|
|
215
|
+
) -> PushServerAppOutputsResponse:
|
|
216
|
+
"""Push ServerApp process outputs."""
|
|
217
|
+
raise NotImplementedError()
|
|
218
|
+
|
|
203
219
|
|
|
204
220
|
def _raise_if(validation_error: bool, detail: str) -> None:
|
|
205
221
|
if validation_error:
|
|
@@ -22,7 +22,7 @@ from logging import ERROR, WARNING
|
|
|
22
22
|
from typing import Optional
|
|
23
23
|
from uuid import UUID, uuid4
|
|
24
24
|
|
|
25
|
-
from flwr.common import log, now
|
|
25
|
+
from flwr.common import Context, log, now
|
|
26
26
|
from flwr.common.constant import (
|
|
27
27
|
MESSAGE_TTL_TOLERANCE,
|
|
28
28
|
NODE_ID_NUM_BYTES,
|
|
@@ -65,6 +65,7 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
|
65
65
|
|
|
66
66
|
# Map run_id to RunRecord
|
|
67
67
|
self.run_ids: dict[int, RunRecord] = {}
|
|
68
|
+
self.contexts: dict[int, Context] = {}
|
|
68
69
|
self.task_ins_store: dict[UUID, TaskIns] = {}
|
|
69
70
|
self.task_res_store: dict[UUID, TaskRes] = {}
|
|
70
71
|
|
|
@@ -500,3 +501,13 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
|
500
501
|
self.node_ids[node_id] = (time.time() + ping_interval, ping_interval)
|
|
501
502
|
return True
|
|
502
503
|
return False
|
|
504
|
+
|
|
505
|
+
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
|
506
|
+
"""Get the context for the specified `run_id`."""
|
|
507
|
+
return self.contexts.get(run_id)
|
|
508
|
+
|
|
509
|
+
def set_serverapp_context(self, run_id: int, context: Context) -> None:
|
|
510
|
+
"""Set the context for the specified `run_id`."""
|
|
511
|
+
if run_id not in self.run_ids:
|
|
512
|
+
raise ValueError(f"Run {run_id} not found")
|
|
513
|
+
self.contexts[run_id] = context
|
|
@@ -19,6 +19,7 @@ import abc
|
|
|
19
19
|
from typing import Optional
|
|
20
20
|
from uuid import UUID
|
|
21
21
|
|
|
22
|
+
from flwr.common import Context
|
|
22
23
|
from flwr.common.typing import Run, RunStatus, UserConfig
|
|
23
24
|
from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
|
|
24
25
|
|
|
@@ -270,3 +271,31 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
|
270
271
|
is_acknowledged : bool
|
|
271
272
|
True if the ping is successfully acknowledged; otherwise, False.
|
|
272
273
|
"""
|
|
274
|
+
|
|
275
|
+
@abc.abstractmethod
|
|
276
|
+
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
|
277
|
+
"""Get the context for the specified `run_id`.
|
|
278
|
+
|
|
279
|
+
Parameters
|
|
280
|
+
----------
|
|
281
|
+
run_id : int
|
|
282
|
+
The identifier of the run for which to retrieve the context.
|
|
283
|
+
|
|
284
|
+
Returns
|
|
285
|
+
-------
|
|
286
|
+
Optional[Context]
|
|
287
|
+
The context associated with the specified `run_id`, or `None` if no context
|
|
288
|
+
exists for the given `run_id`.
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
@abc.abstractmethod
|
|
292
|
+
def set_serverapp_context(self, run_id: int, context: Context) -> None:
|
|
293
|
+
"""Set the context for the specified `run_id`.
|
|
294
|
+
|
|
295
|
+
Parameters
|
|
296
|
+
----------
|
|
297
|
+
run_id : int
|
|
298
|
+
The identifier of the run for which to set the context.
|
|
299
|
+
context : Context
|
|
300
|
+
The context to be associated with the specified `run_id`.
|
|
301
|
+
"""
|
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
import json
|
|
20
20
|
import re
|
|
21
21
|
import sqlite3
|
|
22
|
+
import threading
|
|
22
23
|
import time
|
|
23
24
|
from collections.abc import Sequence
|
|
24
25
|
from logging import DEBUG, ERROR, WARNING
|
|
25
26
|
from typing import Any, Optional, Union, cast
|
|
26
27
|
from uuid import UUID, uuid4
|
|
27
28
|
|
|
28
|
-
from flwr.common import log, now
|
|
29
|
+
from flwr.common import Context, log, now
|
|
29
30
|
from flwr.common.constant import (
|
|
30
31
|
MESSAGE_TTL_TOLERANCE,
|
|
31
32
|
NODE_ID_NUM_BYTES,
|
|
@@ -33,13 +34,19 @@ from flwr.common.constant import (
|
|
|
33
34
|
Status,
|
|
34
35
|
)
|
|
35
36
|
from flwr.common.typing import Run, RunStatus, UserConfig
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
from flwr.proto.
|
|
37
|
+
|
|
38
|
+
# pylint: disable=E0611
|
|
39
|
+
from flwr.proto.node_pb2 import Node
|
|
40
|
+
from flwr.proto.recordset_pb2 import RecordSet as ProtoRecordSet
|
|
41
|
+
from flwr.proto.task_pb2 import Task, TaskIns, TaskRes
|
|
42
|
+
|
|
43
|
+
# pylint: enable=E0611
|
|
39
44
|
from flwr.server.utils.validator import validate_task_ins_or_res
|
|
40
45
|
|
|
41
46
|
from .linkstate import LinkState
|
|
42
47
|
from .utils import (
|
|
48
|
+
context_from_bytes,
|
|
49
|
+
context_to_bytes,
|
|
43
50
|
convert_sint64_to_uint64,
|
|
44
51
|
convert_sint64_values_in_dict_to_uint64,
|
|
45
52
|
convert_uint64_to_sint64,
|
|
@@ -92,6 +99,14 @@ CREATE TABLE IF NOT EXISTS run(
|
|
|
92
99
|
);
|
|
93
100
|
"""
|
|
94
101
|
|
|
102
|
+
SQL_CREATE_TABLE_CONTEXT = """
|
|
103
|
+
CREATE TABLE IF NOT EXISTS context(
|
|
104
|
+
run_id INTEGER UNIQUE,
|
|
105
|
+
context BLOB,
|
|
106
|
+
FOREIGN KEY(run_id) REFERENCES run(run_id)
|
|
107
|
+
);
|
|
108
|
+
"""
|
|
109
|
+
|
|
95
110
|
SQL_CREATE_TABLE_TASK_INS = """
|
|
96
111
|
CREATE TABLE IF NOT EXISTS task_ins(
|
|
97
112
|
task_id TEXT UNIQUE,
|
|
@@ -152,6 +167,7 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
|
152
167
|
"""
|
|
153
168
|
self.database_path = database_path
|
|
154
169
|
self.conn: Optional[sqlite3.Connection] = None
|
|
170
|
+
self.lock = threading.RLock()
|
|
155
171
|
|
|
156
172
|
def initialize(self, log_queries: bool = False) -> list[tuple[str]]:
|
|
157
173
|
"""Create tables if they don't exist yet.
|
|
@@ -175,6 +191,7 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
|
175
191
|
|
|
176
192
|
# Create each table if not exists queries
|
|
177
193
|
cur.execute(SQL_CREATE_TABLE_RUN)
|
|
194
|
+
cur.execute(SQL_CREATE_TABLE_CONTEXT)
|
|
178
195
|
cur.execute(SQL_CREATE_TABLE_TASK_INS)
|
|
179
196
|
cur.execute(SQL_CREATE_TABLE_TASK_RES)
|
|
180
197
|
cur.execute(SQL_CREATE_TABLE_NODE)
|
|
@@ -970,6 +987,34 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
|
970
987
|
log(ERROR, "`node_id` does not exist.")
|
|
971
988
|
return False
|
|
972
989
|
|
|
990
|
+
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
|
991
|
+
"""Get the context for the specified `run_id`."""
|
|
992
|
+
# Retrieve context if any
|
|
993
|
+
query = "SELECT context FROM context WHERE run_id = ?;"
|
|
994
|
+
rows = self.query(query, (convert_uint64_to_sint64(run_id),))
|
|
995
|
+
context = context_from_bytes(rows[0]["context"]) if rows else None
|
|
996
|
+
return context
|
|
997
|
+
|
|
998
|
+
def set_serverapp_context(self, run_id: int, context: Context) -> None:
|
|
999
|
+
"""Set the context for the specified `run_id`."""
|
|
1000
|
+
# Convert context to bytes
|
|
1001
|
+
context_bytes = context_to_bytes(context)
|
|
1002
|
+
sint_run_id = convert_uint64_to_sint64(run_id)
|
|
1003
|
+
|
|
1004
|
+
# Check if any existing Context assigned to the run_id
|
|
1005
|
+
query = "SELECT COUNT(*) FROM context WHERE run_id = ?;"
|
|
1006
|
+
if self.query(query, (sint_run_id,))[0]["COUNT(*)"] > 0:
|
|
1007
|
+
# Update context
|
|
1008
|
+
query = "UPDATE context SET context = ? WHERE run_id = ?;"
|
|
1009
|
+
self.query(query, (context_bytes, sint_run_id))
|
|
1010
|
+
else:
|
|
1011
|
+
try:
|
|
1012
|
+
# Store context
|
|
1013
|
+
query = "INSERT INTO context (run_id, context) VALUES (?, ?);"
|
|
1014
|
+
self.query(query, (sint_run_id, context_bytes))
|
|
1015
|
+
except sqlite3.IntegrityError:
|
|
1016
|
+
raise ValueError(f"Run {run_id} not found") from None
|
|
1017
|
+
|
|
973
1018
|
def get_valid_task_ins(self, task_id: str) -> Optional[dict[str, Any]]:
|
|
974
1019
|
"""Check if the TaskIns exists and is valid (not expired).
|
|
975
1020
|
|
|
@@ -1054,7 +1099,7 @@ def task_res_to_dict(task_msg: TaskRes) -> dict[str, Any]:
|
|
|
1054
1099
|
|
|
1055
1100
|
def dict_to_task_ins(task_dict: dict[str, Any]) -> TaskIns:
|
|
1056
1101
|
"""Turn task_dict into protobuf message."""
|
|
1057
|
-
recordset =
|
|
1102
|
+
recordset = ProtoRecordSet()
|
|
1058
1103
|
recordset.ParseFromString(task_dict["recordset"])
|
|
1059
1104
|
|
|
1060
1105
|
result = TaskIns(
|
|
@@ -1084,7 +1129,7 @@ def dict_to_task_ins(task_dict: dict[str, Any]) -> TaskIns:
|
|
|
1084
1129
|
|
|
1085
1130
|
def dict_to_task_res(task_dict: dict[str, Any]) -> TaskRes:
|
|
1086
1131
|
"""Turn task_dict into protobuf message."""
|
|
1087
|
-
recordset =
|
|
1132
|
+
recordset = ProtoRecordSet()
|
|
1088
1133
|
recordset.ParseFromString(task_dict["recordset"])
|
|
1089
1134
|
|
|
1090
1135
|
result = TaskRes(
|
|
@@ -20,10 +20,11 @@ from logging import ERROR
|
|
|
20
20
|
from os import urandom
|
|
21
21
|
from uuid import uuid4
|
|
22
22
|
|
|
23
|
-
from flwr.common import log
|
|
23
|
+
from flwr.common import Context, log, serde
|
|
24
24
|
from flwr.common.constant import ErrorCode, Status, SubStatus
|
|
25
25
|
from flwr.common.typing import RunStatus
|
|
26
26
|
from flwr.proto.error_pb2 import Error # pylint: disable=E0611
|
|
27
|
+
from flwr.proto.message_pb2 import Context as ProtoContext # pylint: disable=E0611
|
|
27
28
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
28
29
|
from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611
|
|
29
30
|
|
|
@@ -135,6 +136,16 @@ def convert_sint64_values_in_dict_to_uint64(
|
|
|
135
136
|
data_dict[key] = convert_sint64_to_uint64(data_dict[key])
|
|
136
137
|
|
|
137
138
|
|
|
139
|
+
def context_to_bytes(context: Context) -> bytes:
|
|
140
|
+
"""Serialize `Context` to bytes."""
|
|
141
|
+
return serde.context_to_proto(context).SerializeToString()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def context_from_bytes(context_bytes: bytes) -> Context:
|
|
145
|
+
"""Deserialize `Context` from bytes."""
|
|
146
|
+
return serde.context_from_proto(ProtoContext.FromString(context_bytes))
|
|
147
|
+
|
|
148
|
+
|
|
138
149
|
def make_node_unavailable_taskres(ref_taskins: TaskIns) -> TaskRes:
|
|
139
150
|
"""Generate a TaskRes with a node unavailable error from a TaskIns."""
|
|
140
151
|
current_time = time.time()
|
|
@@ -29,7 +29,7 @@ from typing import Any, Optional
|
|
|
29
29
|
|
|
30
30
|
from flwr.cli.config_utils import load_and_validate
|
|
31
31
|
from flwr.client import ClientApp
|
|
32
|
-
from flwr.common import EventType, event, log, now
|
|
32
|
+
from flwr.common import Context, EventType, RecordSet, event, log, now
|
|
33
33
|
from flwr.common.config import get_fused_config_from_dir, parse_config_args
|
|
34
34
|
from flwr.common.constant import RUN_ID_NUM_BYTES, Status
|
|
35
35
|
from flwr.common.logger import (
|
|
@@ -40,7 +40,7 @@ from flwr.common.logger import (
|
|
|
40
40
|
)
|
|
41
41
|
from flwr.common.typing import Run, RunStatus, UserConfig
|
|
42
42
|
from flwr.server.driver import Driver, InMemoryDriver
|
|
43
|
-
from flwr.server.run_serverapp import run as
|
|
43
|
+
from flwr.server.run_serverapp import run as _run
|
|
44
44
|
from flwr.server.server_app import ServerApp
|
|
45
45
|
from flwr.server.superlink.fleet import vce
|
|
46
46
|
from flwr.server.superlink.fleet.vce.backend.backend import BackendConfig
|
|
@@ -333,11 +333,19 @@ def run_serverapp_th(
|
|
|
333
333
|
log(INFO, "Enabling GPU growth for Tensorflow on the server thread.")
|
|
334
334
|
enable_gpu_growth()
|
|
335
335
|
|
|
336
|
+
# Initialize Context
|
|
337
|
+
context = Context(
|
|
338
|
+
node_id=0,
|
|
339
|
+
node_config={},
|
|
340
|
+
state=RecordSet(),
|
|
341
|
+
run_config=_server_app_run_config,
|
|
342
|
+
)
|
|
343
|
+
|
|
336
344
|
# Run ServerApp
|
|
337
|
-
|
|
345
|
+
_run(
|
|
338
346
|
driver=_driver,
|
|
347
|
+
context=context,
|
|
339
348
|
server_app_dir=_server_app_dir,
|
|
340
|
-
server_app_run_config=_server_app_run_config,
|
|
341
349
|
server_app_attr=_server_app_attr,
|
|
342
350
|
loaded_server_app=_server_app,
|
|
343
351
|
)
|
flwr/superexec/app.py
CHANGED
|
@@ -16,21 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
import argparse
|
|
18
18
|
import sys
|
|
19
|
-
from logging import INFO
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
from typing import Optional
|
|
19
|
+
from logging import INFO
|
|
22
20
|
|
|
23
|
-
import
|
|
24
|
-
|
|
25
|
-
from flwr.common import EventType, event, log
|
|
26
|
-
from flwr.common.address import parse_address
|
|
27
|
-
from flwr.common.config import parse_config_args
|
|
28
|
-
from flwr.common.constant import EXEC_API_DEFAULT_ADDRESS
|
|
29
|
-
from flwr.common.exit_handlers import register_exit_handlers
|
|
30
|
-
from flwr.common.logger import warn_deprecated_feature
|
|
21
|
+
from flwr.common import log
|
|
31
22
|
from flwr.common.object_ref import load_app, validate
|
|
32
23
|
|
|
33
|
-
from .exec_grpc import run_superexec_api_grpc
|
|
34
24
|
from .executor import Executor
|
|
35
25
|
|
|
36
26
|
|
|
@@ -38,137 +28,12 @@ def run_superexec() -> None:
|
|
|
38
28
|
"""Run Flower SuperExec."""
|
|
39
29
|
log(INFO, "Starting Flower SuperExec")
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
sys.exit(
|
|
42
32
|
"Manually launching the SuperExec is deprecated. Since `flwr 1.13.0` "
|
|
43
33
|
"the executor service runs in the SuperLink. Launching it manually is not "
|
|
44
34
|
"recommended."
|
|
45
35
|
)
|
|
46
36
|
|
|
47
|
-
event(EventType.RUN_SUPEREXEC_ENTER)
|
|
48
|
-
|
|
49
|
-
args = _parse_args_run_superexec().parse_args()
|
|
50
|
-
|
|
51
|
-
# Parse IP address
|
|
52
|
-
parsed_address = parse_address(args.address)
|
|
53
|
-
if not parsed_address:
|
|
54
|
-
sys.exit(f"SuperExec IP address ({args.address}) cannot be parsed.")
|
|
55
|
-
host, port, is_v6 = parsed_address
|
|
56
|
-
address = f"[{host}]:{port}" if is_v6 else f"{host}:{port}"
|
|
57
|
-
|
|
58
|
-
# Obtain certificates
|
|
59
|
-
certificates = _try_obtain_certificates(args)
|
|
60
|
-
|
|
61
|
-
# Start SuperExec API
|
|
62
|
-
superexec_server: grpc.Server = run_superexec_api_grpc(
|
|
63
|
-
address=address,
|
|
64
|
-
executor=load_executor(args),
|
|
65
|
-
certificates=certificates,
|
|
66
|
-
config=parse_config_args(
|
|
67
|
-
[args.executor_config] if args.executor_config else args.executor_config
|
|
68
|
-
),
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
grpc_servers = [superexec_server]
|
|
72
|
-
|
|
73
|
-
# Graceful shutdown
|
|
74
|
-
register_exit_handlers(
|
|
75
|
-
event_type=EventType.RUN_SUPEREXEC_LEAVE,
|
|
76
|
-
grpc_servers=grpc_servers,
|
|
77
|
-
bckg_threads=None,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
superexec_server.wait_for_termination()
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def _parse_args_run_superexec() -> argparse.ArgumentParser:
|
|
84
|
-
"""Parse command line arguments for SuperExec."""
|
|
85
|
-
parser = argparse.ArgumentParser(
|
|
86
|
-
description="Start a Flower SuperExec",
|
|
87
|
-
)
|
|
88
|
-
parser.add_argument(
|
|
89
|
-
"--address",
|
|
90
|
-
help="SuperExec (gRPC) server address (IPv4, IPv6, or a domain name)",
|
|
91
|
-
default=EXEC_API_DEFAULT_ADDRESS,
|
|
92
|
-
)
|
|
93
|
-
parser.add_argument(
|
|
94
|
-
"--executor",
|
|
95
|
-
help="For example: `deployment:exec` or `project.package.module:wrapper.exec`.",
|
|
96
|
-
default="flwr.superexec.deployment:executor",
|
|
97
|
-
)
|
|
98
|
-
parser.add_argument(
|
|
99
|
-
"--executor-dir",
|
|
100
|
-
help="The directory for the executor.",
|
|
101
|
-
default=".",
|
|
102
|
-
)
|
|
103
|
-
parser.add_argument(
|
|
104
|
-
"--executor-config",
|
|
105
|
-
help="Key-value pairs for the executor config, separated by spaces. "
|
|
106
|
-
'For example:\n\n`--executor-config \'superlink="superlink:9091" '
|
|
107
|
-
'root-certificates="certificates/superlink-ca.crt"\'`',
|
|
108
|
-
)
|
|
109
|
-
parser.add_argument(
|
|
110
|
-
"--insecure",
|
|
111
|
-
action="store_true",
|
|
112
|
-
help="Run the SuperExec without HTTPS, regardless of whether certificate "
|
|
113
|
-
"paths are provided. By default, the server runs with HTTPS enabled. "
|
|
114
|
-
"Use this flag only if you understand the risks.",
|
|
115
|
-
)
|
|
116
|
-
parser.add_argument(
|
|
117
|
-
"--ssl-certfile",
|
|
118
|
-
help="SuperExec server SSL certificate file (as a path str) "
|
|
119
|
-
"to create a secure connection.",
|
|
120
|
-
type=str,
|
|
121
|
-
default=None,
|
|
122
|
-
)
|
|
123
|
-
parser.add_argument(
|
|
124
|
-
"--ssl-keyfile",
|
|
125
|
-
help="SuperExec server SSL private key file (as a path str) "
|
|
126
|
-
"to create a secure connection.",
|
|
127
|
-
type=str,
|
|
128
|
-
)
|
|
129
|
-
parser.add_argument(
|
|
130
|
-
"--ssl-ca-certfile",
|
|
131
|
-
help="SuperExec server SSL CA certificate file (as a path str) "
|
|
132
|
-
"to create a secure connection.",
|
|
133
|
-
type=str,
|
|
134
|
-
)
|
|
135
|
-
return parser
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def _try_obtain_certificates(
|
|
139
|
-
args: argparse.Namespace,
|
|
140
|
-
) -> Optional[tuple[bytes, bytes, bytes]]:
|
|
141
|
-
# Obtain certificates
|
|
142
|
-
if args.insecure:
|
|
143
|
-
log(WARN, "Option `--insecure` was set. Starting insecure HTTP server.")
|
|
144
|
-
return None
|
|
145
|
-
# Check if certificates are provided
|
|
146
|
-
if args.ssl_certfile and args.ssl_keyfile and args.ssl_ca_certfile:
|
|
147
|
-
if not Path(args.ssl_ca_certfile).is_file():
|
|
148
|
-
sys.exit("Path argument `--ssl-ca-certfile` does not point to a file.")
|
|
149
|
-
if not Path(args.ssl_certfile).is_file():
|
|
150
|
-
sys.exit("Path argument `--ssl-certfile` does not point to a file.")
|
|
151
|
-
if not Path(args.ssl_keyfile).is_file():
|
|
152
|
-
sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
|
|
153
|
-
certificates = (
|
|
154
|
-
Path(args.ssl_ca_certfile).read_bytes(), # CA certificate
|
|
155
|
-
Path(args.ssl_certfile).read_bytes(), # server certificate
|
|
156
|
-
Path(args.ssl_keyfile).read_bytes(), # server private key
|
|
157
|
-
)
|
|
158
|
-
return certificates
|
|
159
|
-
if args.ssl_certfile or args.ssl_keyfile or args.ssl_ca_certfile:
|
|
160
|
-
sys.exit(
|
|
161
|
-
"You need to provide valid file paths to `--ssl-certfile`, "
|
|
162
|
-
"`--ssl-keyfile`, and `—-ssl-ca-certfile` to create a secure "
|
|
163
|
-
"connection in SuperExec server (gRPC-rere)."
|
|
164
|
-
)
|
|
165
|
-
sys.exit(
|
|
166
|
-
"Certificates are required unless running in insecure mode. "
|
|
167
|
-
"Please provide certificate paths to `--ssl-certfile`, "
|
|
168
|
-
"`--ssl-keyfile`, and `—-ssl-ca-certfile` or run the server "
|
|
169
|
-
"in insecure mode using '--insecure' if you understand the risks."
|
|
170
|
-
)
|
|
171
|
-
|
|
172
37
|
|
|
173
38
|
def load_executor(
|
|
174
39
|
args: argparse.Namespace,
|
flwr/superexec/deployment.py
CHANGED
|
@@ -24,12 +24,11 @@ from typing_extensions import override
|
|
|
24
24
|
|
|
25
25
|
from flwr.cli.install import install_from_fab
|
|
26
26
|
from flwr.common.constant import DRIVER_API_DEFAULT_ADDRESS
|
|
27
|
-
from flwr.common.grpc import create_channel
|
|
28
27
|
from flwr.common.logger import log
|
|
29
|
-
from flwr.common.serde import fab_to_proto, user_config_to_proto
|
|
30
28
|
from flwr.common.typing import Fab, UserConfig
|
|
31
|
-
from flwr.
|
|
32
|
-
from flwr.
|
|
29
|
+
from flwr.server.superlink.ffs import Ffs
|
|
30
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
31
|
+
from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
|
|
33
32
|
|
|
34
33
|
from .executor import Executor, RunTracker
|
|
35
34
|
|
|
@@ -62,7 +61,30 @@ class DeploymentEngine(Executor):
|
|
|
62
61
|
self.root_certificates = root_certificates
|
|
63
62
|
self.root_certificates_bytes = Path(root_certificates).read_bytes()
|
|
64
63
|
self.flwr_dir = flwr_dir
|
|
65
|
-
self.
|
|
64
|
+
self.linkstate_factory: Optional[LinkStateFactory] = None
|
|
65
|
+
self.ffs_factory: Optional[FfsFactory] = None
|
|
66
|
+
|
|
67
|
+
@override
|
|
68
|
+
def initialize(
|
|
69
|
+
self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Initialize the executor with the necessary factories."""
|
|
72
|
+
self.linkstate_factory = linkstate_factory
|
|
73
|
+
self.ffs_factory = ffs_factory
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def linkstate(self) -> LinkState:
|
|
77
|
+
"""Return the LinkState."""
|
|
78
|
+
if self.linkstate_factory is None:
|
|
79
|
+
raise RuntimeError("Executor is not initialized.")
|
|
80
|
+
return self.linkstate_factory.state()
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def ffs(self) -> Ffs:
|
|
84
|
+
"""Return the Flower File Storage (FFS)."""
|
|
85
|
+
if self.ffs_factory is None:
|
|
86
|
+
raise RuntimeError("Executor is not initialized.")
|
|
87
|
+
return self.ffs_factory.ffs()
|
|
66
88
|
|
|
67
89
|
@override
|
|
68
90
|
def set_config(
|
|
@@ -101,32 +123,19 @@ class DeploymentEngine(Executor):
|
|
|
101
123
|
raise ValueError("The `flwr-dir` value should be of type `str`.")
|
|
102
124
|
self.flwr_dir = str(flwr_dir)
|
|
103
125
|
|
|
104
|
-
def _connect(self) -> None:
|
|
105
|
-
if self.stub is not None:
|
|
106
|
-
return
|
|
107
|
-
channel = create_channel(
|
|
108
|
-
server_address=self.superlink,
|
|
109
|
-
insecure=(self.root_certificates_bytes is None),
|
|
110
|
-
root_certificates=self.root_certificates_bytes,
|
|
111
|
-
)
|
|
112
|
-
self.stub = DriverStub(channel)
|
|
113
|
-
|
|
114
126
|
def _create_run(
|
|
115
127
|
self,
|
|
116
128
|
fab: Fab,
|
|
117
129
|
override_config: UserConfig,
|
|
118
130
|
) -> int:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
fab_hash = self.ffs.put(fab.content, {})
|
|
132
|
+
if fab_hash != fab.hash_str:
|
|
133
|
+
raise RuntimeError(
|
|
134
|
+
f"FAB ({fab.hash_str}) hash from request doesn't match contents"
|
|
135
|
+
)
|
|
123
136
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
override_config=user_config_to_proto(override_config),
|
|
127
|
-
)
|
|
128
|
-
res = self.stub.CreateRun(request=req)
|
|
129
|
-
return int(res.run_id)
|
|
137
|
+
run_id = self.linkstate.create_run(None, None, fab_hash, override_config)
|
|
138
|
+
return run_id
|
|
130
139
|
|
|
131
140
|
@override
|
|
132
141
|
def start_run(
|
flwr/superexec/exec_grpc.py
CHANGED
|
@@ -23,33 +23,40 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH
|
|
|
23
23
|
from flwr.common.logger import log
|
|
24
24
|
from flwr.common.typing import UserConfig
|
|
25
25
|
from flwr.proto.exec_pb2_grpc import add_ExecServicer_to_server
|
|
26
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
26
27
|
from flwr.server.superlink.fleet.grpc_bidi.grpc_server import generic_create_grpc_server
|
|
28
|
+
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
27
29
|
|
|
28
30
|
from .exec_servicer import ExecServicer
|
|
29
31
|
from .executor import Executor
|
|
30
32
|
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
# pylint: disable-next=too-many-arguments, too-many-positional-arguments
|
|
35
|
+
def run_exec_api_grpc(
|
|
33
36
|
address: str,
|
|
34
37
|
executor: Executor,
|
|
38
|
+
state_factory: LinkStateFactory,
|
|
39
|
+
ffs_factory: FfsFactory,
|
|
35
40
|
certificates: Optional[tuple[bytes, bytes, bytes]],
|
|
36
41
|
config: UserConfig,
|
|
37
42
|
) -> grpc.Server:
|
|
38
|
-
"""Run
|
|
43
|
+
"""Run Exec API (gRPC, request-response)."""
|
|
39
44
|
executor.set_config(config)
|
|
40
45
|
|
|
41
46
|
exec_servicer: grpc.Server = ExecServicer(
|
|
47
|
+
linkstate_factory=state_factory,
|
|
48
|
+
ffs_factory=ffs_factory,
|
|
42
49
|
executor=executor,
|
|
43
50
|
)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
servicer_and_add_fn=(exec_servicer,
|
|
51
|
+
exec_add_servicer_to_server_fn = add_ExecServicer_to_server
|
|
52
|
+
exec_grpc_server = generic_create_grpc_server(
|
|
53
|
+
servicer_and_add_fn=(exec_servicer, exec_add_servicer_to_server_fn),
|
|
47
54
|
server_address=address,
|
|
48
55
|
max_message_length=GRPC_MAX_MESSAGE_LENGTH,
|
|
49
56
|
certificates=certificates,
|
|
50
57
|
)
|
|
51
58
|
|
|
52
|
-
log(INFO, "
|
|
53
|
-
|
|
59
|
+
log(INFO, "Flower Deployment Engine: Starting Exec API on %s", address)
|
|
60
|
+
exec_grpc_server.start()
|
|
54
61
|
|
|
55
|
-
return
|
|
62
|
+
return exec_grpc_server
|
flwr/superexec/exec_servicer.py
CHANGED
|
@@ -34,6 +34,8 @@ from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
|
|
|
34
34
|
StreamLogsRequest,
|
|
35
35
|
StreamLogsResponse,
|
|
36
36
|
)
|
|
37
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
38
|
+
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
37
39
|
|
|
38
40
|
from .executor import Executor, RunTracker
|
|
39
41
|
|
|
@@ -43,8 +45,16 @@ SELECT_TIMEOUT = 1 # Timeout for selecting ready-to-read file descriptors (in s
|
|
|
43
45
|
class ExecServicer(exec_pb2_grpc.ExecServicer):
|
|
44
46
|
"""SuperExec API servicer."""
|
|
45
47
|
|
|
46
|
-
def __init__(
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
linkstate_factory: LinkStateFactory,
|
|
51
|
+
ffs_factory: FfsFactory,
|
|
52
|
+
executor: Executor,
|
|
53
|
+
) -> None:
|
|
54
|
+
self.linkstate_factory = linkstate_factory
|
|
55
|
+
self.ffs_factory = ffs_factory
|
|
47
56
|
self.executor = executor
|
|
57
|
+
self.executor.initialize(linkstate_factory, ffs_factory)
|
|
48
58
|
self.runs: dict[int, RunTracker] = {}
|
|
49
59
|
|
|
50
60
|
def StartRun(
|
flwr/superexec/executor.py
CHANGED
|
@@ -20,6 +20,8 @@ from subprocess import Popen
|
|
|
20
20
|
from typing import Optional
|
|
21
21
|
|
|
22
22
|
from flwr.common.typing import UserConfig
|
|
23
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
24
|
+
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
@dataclass
|
|
@@ -34,6 +36,23 @@ class RunTracker:
|
|
|
34
36
|
class Executor(ABC):
|
|
35
37
|
"""Execute and monitor a Flower run."""
|
|
36
38
|
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def initialize(
|
|
41
|
+
self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initialize the executor with the necessary factories.
|
|
44
|
+
|
|
45
|
+
This method sets up the executor by providing it with the factories required
|
|
46
|
+
to access the LinkState and the Flower File Storage (FFS) in the SuperLink.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
linkstate_factory : LinkStateFactory
|
|
51
|
+
The factory to create access to the LinkState.
|
|
52
|
+
ffs_factory : FfsFactory
|
|
53
|
+
The factory to create access to the Flower File Storage (FFS).
|
|
54
|
+
"""
|
|
55
|
+
|
|
37
56
|
@abstractmethod
|
|
38
57
|
def set_config(
|
|
39
58
|
self,
|
flwr/superexec/simulation.py
CHANGED
|
@@ -29,6 +29,8 @@ from flwr.common.config import unflatten_dict
|
|
|
29
29
|
from flwr.common.constant import RUN_ID_NUM_BYTES
|
|
30
30
|
from flwr.common.logger import log
|
|
31
31
|
from flwr.common.typing import UserConfig
|
|
32
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
33
|
+
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
32
34
|
from flwr.server.superlink.linkstate.utils import generate_rand_int_from_bytes
|
|
33
35
|
|
|
34
36
|
from .executor import Executor, RunTracker
|
|
@@ -70,6 +72,12 @@ class SimulationEngine(Executor):
|
|
|
70
72
|
self.num_supernodes = num_supernodes
|
|
71
73
|
self.verbose = verbose
|
|
72
74
|
|
|
75
|
+
@override
|
|
76
|
+
def initialize(
|
|
77
|
+
self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
|
|
78
|
+
) -> None:
|
|
79
|
+
"""Initialize the executor with the necessary factories."""
|
|
80
|
+
|
|
73
81
|
@override
|
|
74
82
|
def set_config(
|
|
75
83
|
self,
|
{flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/RECORD
RENAMED
|
@@ -92,7 +92,6 @@ flwr/client/mod/secure_aggregation/__init__.py,sha256=A7DzZ3uvXTUkuHBzrxJMWQQD4R
|
|
|
92
92
|
flwr/client/mod/secure_aggregation/secagg_mod.py,sha256=wI9tuIEvMUETz-wVIEbPYvh-1nK9CEylBLGoVpNhL94,1095
|
|
93
93
|
flwr/client/mod/secure_aggregation/secaggplus_mod.py,sha256=7cNXsY07ZA0M5_9VSc52F8JUoAoGaraNDA2rgaLvvFo,19680
|
|
94
94
|
flwr/client/mod/utils.py,sha256=dFcTHOjUuuiw34fcQlvyzytYD0sCv1w9x8fQX1Yo8Oc,1201
|
|
95
|
-
flwr/client/node_state_tests.py,sha256=28HzAxcxF-mhzPisJMCUczrLz1KfxtTkKZ5tvQgq-gM,2291
|
|
96
95
|
flwr/client/numpy_client.py,sha256=tqGyhIkeeZQGr65BR03B7TWgx4rW3FA7G2874D8z_VU,11167
|
|
97
96
|
flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3uRS-7Q,735
|
|
98
97
|
flwr/client/rest_client/connection.py,sha256=k-RqgUFqidACAGlMFPIUM8aawXI5h2LvKUri2OAK7Bg,12817
|
|
@@ -150,10 +149,10 @@ flwr/proto/control_pb2.py,sha256=yaUkwY2J9uo-fdUIB5aHwVSDOuGunxaUr4ZlggifA_M,143
|
|
|
150
149
|
flwr/proto/control_pb2.pyi,sha256=XbFvpZvvrS7QcH5AFXfpRGl4hQvhd3QdKO6x0oTlCCU,165
|
|
151
150
|
flwr/proto/control_pb2_grpc.py,sha256=FFE21nZvEILWpe1WCR5vAwgYEtpzrdG78-_SsU0gZ7w,5783
|
|
152
151
|
flwr/proto/control_pb2_grpc.pyi,sha256=9DU4sgkzJ497a4Nq6kitZWEG4g_5MO8MevichnO0oAg,1672
|
|
153
|
-
flwr/proto/driver_pb2.py,sha256=
|
|
154
|
-
flwr/proto/driver_pb2.pyi,sha256=
|
|
155
|
-
flwr/proto/driver_pb2_grpc.py,sha256=
|
|
156
|
-
flwr/proto/driver_pb2_grpc.pyi,sha256=
|
|
152
|
+
flwr/proto/driver_pb2.py,sha256=8WmaJ3F5iPuHeiFkfkf_9Pa86qgoUYLPaIL-9igdcIk,4528
|
|
153
|
+
flwr/proto/driver_pb2.pyi,sha256=Mq4xZ5Hn55CrUVLu4kvNZylKtF9AQ9NomOv1qJ3Py4Q,6636
|
|
154
|
+
flwr/proto/driver_pb2_grpc.py,sha256=KgJNfvIkTX4z3u9jU05z3GvyCx39cQ1r_OgiD3zoinw,13886
|
|
155
|
+
flwr/proto/driver_pb2_grpc.pyi,sha256=_aiUW3TsX1jPL7WqdUhiAPK_6bK8Cv5Flo_SntmlL44,3766
|
|
157
156
|
flwr/proto/error_pb2.py,sha256=LarjKL90LbwkXKlhzNrDssgl4DXcvIPve8NVCXHpsKA,1084
|
|
158
157
|
flwr/proto/error_pb2.pyi,sha256=ZNH4HhJTU_KfMXlyCeg8FwU-fcUYxTqEmoJPtWtHikc,734
|
|
159
158
|
flwr/proto/error_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
@@ -200,7 +199,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
|
|
|
200
199
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
|
201
200
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
202
201
|
flwr/server/__init__.py,sha256=cEg1oecBu4cKB69iJCqWEylC8b5XW47bl7rQiJsdTvM,1528
|
|
203
|
-
flwr/server/app.py,sha256=
|
|
202
|
+
flwr/server/app.py,sha256=p3uTuj4tIRK67d6FCyNIwEVKkfhZBIuuhZt86gDqmv8,28315
|
|
204
203
|
flwr/server/client_manager.py,sha256=7Ese0tgrH-i-ms363feYZJKwB8gWnXSmg_hYF2Bju4U,6227
|
|
205
204
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
|
206
205
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
|
@@ -214,7 +213,7 @@ flwr/server/driver/driver.py,sha256=KpLrWeF0zP9HBdo_mucPlNVj5eS0K8DDHRRY_58E1BM,
|
|
|
214
213
|
flwr/server/driver/grpc_driver.py,sha256=AhkqfXBSv8TnqBGxqj1nhkOxp6HVU0WaJq4YlqIz8Hw,9687
|
|
215
214
|
flwr/server/driver/inmemory_driver.py,sha256=7gw1zRgNvmy2FWCEOMs8udpc2HQsxURrIwbpKv5VyoE,6656
|
|
216
215
|
flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
|
|
217
|
-
flwr/server/run_serverapp.py,sha256=
|
|
216
|
+
flwr/server/run_serverapp.py,sha256=_i0kBRrSzeR4-DDswysoWYertdAq7-LfrSAJ2n-GB8Q,10530
|
|
218
217
|
flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
|
|
219
218
|
flwr/server/server_app.py,sha256=RsgS6PRS5Z74cMUAHzsm8r3LWddwn00MjRs6rlacHt8,6297
|
|
220
219
|
flwr/server/server_config.py,sha256=CZaHVAsMvGLjpWVcLPkiYxgJN4xfIyAiUrCI3fETKY4,1349
|
|
@@ -248,7 +247,7 @@ flwr/server/strategy/strategy.py,sha256=cXapkD5uDrt5C-RbmWDn9FLoap3Q41i7GKvbmfbC
|
|
|
248
247
|
flwr/server/superlink/__init__.py,sha256=8tHYCfodUlRD8PCP9fHgvu8cz5N31A2QoRVL0jDJ15E,707
|
|
249
248
|
flwr/server/superlink/driver/__init__.py,sha256=_JaRW-FdyikHc7souUrnk3mwTGViraEJCeUBY_M_ocs,712
|
|
250
249
|
flwr/server/superlink/driver/driver_grpc.py,sha256=melAgaV37Y0B9bZe5bRWQOobItZZ9DIzlcbVE8B01wo,2060
|
|
251
|
-
flwr/server/superlink/driver/driver_servicer.py,sha256
|
|
250
|
+
flwr/server/superlink/driver/driver_servicer.py,sha256=hA997-qPu9RxLFsiK-Jn4tDv7VZFHz1ayv5a4cOZGsA,7601
|
|
252
251
|
flwr/server/superlink/ffs/__init__.py,sha256=FAY-zShcfPmOxosok2QyT6hTNMNctG8cH9s_nIl8jkI,840
|
|
253
252
|
flwr/server/superlink/ffs/disk_ffs.py,sha256=yCN6CCzegnJIOaHr5nIu49wZQa4g5BByiSKshz50RKU,3296
|
|
254
253
|
flwr/server/superlink/ffs/ffs.py,sha256=qLI1UfosJugu2BKOJWqHIhafTm-YiuKqGf3OGWPH0NM,2395
|
|
@@ -274,11 +273,11 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0Q
|
|
|
274
273
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=7kB3re3mR53b7E6L6DPSioTSKD3YGtS3uJsPD7Hn2Fw,7155
|
|
275
274
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=VL6e_Jwf4uxA-X1EelxJZMv6Eji-_p2J9D0MdHG10a4,13029
|
|
276
275
|
flwr/server/superlink/linkstate/__init__.py,sha256=v-2JyJlCB3qyhMNwMjmcNVOq4rkooqFU0LHH8Zo1jls,1064
|
|
277
|
-
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=
|
|
278
|
-
flwr/server/superlink/linkstate/linkstate.py,sha256=
|
|
276
|
+
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=guqspi2WYyAXZKIxXCApuJZsuraNEVvb7aredtlXzRw,19327
|
|
277
|
+
flwr/server/superlink/linkstate/linkstate.py,sha256=A0LCOH0xpq9_mTPrO1LB0MDWKhfUcOSnkKeC3-AeFHU,10256
|
|
279
278
|
flwr/server/superlink/linkstate/linkstate_factory.py,sha256=ISSMjDlwuN7swxjOeYlTNpI_kuZ8PGkMcJnf1dbhUSE,2069
|
|
280
|
-
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=
|
|
281
|
-
flwr/server/superlink/linkstate/utils.py,sha256=
|
|
279
|
+
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=JhP6DtM0xBYtT0B0b1lwy96fY6i_C_Zm6Iq_t3VVQ5o,41245
|
|
280
|
+
flwr/server/superlink/linkstate/utils.py,sha256=ukrMlSv0mNFd0YSpyPDpq_ND90SBkwuKgw3FFux3lqs,6914
|
|
282
281
|
flwr/server/typing.py,sha256=5kaRLZuxTEse9A0g7aVna2VhYxU3wTq1f3d3mtw7kXs,1019
|
|
283
282
|
flwr/server/utils/__init__.py,sha256=pltsPHJoXmUIr3utjwwYxu7_ZAGy5u4MVHzv9iA5Un8,908
|
|
284
283
|
flwr/server/utils/tensorboard.py,sha256=gEBD8w_5uaIfp5aw5RYH66lYZpd_SfkObHQ7eDd9MUk,5466
|
|
@@ -295,16 +294,16 @@ flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQD
|
|
|
295
294
|
flwr/simulation/ray_transport/ray_actor.py,sha256=9-XBguAm5IFqm2ddPFsQtnuuFN6lzqdb00SnCxGUGBo,18996
|
|
296
295
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=2vjOKoom3B74C6XU-jC3N6DwYmsLdB-lmkHZ_Xrv96o,7367
|
|
297
296
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
|
298
|
-
flwr/simulation/run_simulation.py,sha256=
|
|
297
|
+
flwr/simulation/run_simulation.py,sha256=nVLoP5rzH3bmZQ-pW9Nka2m0M1pFIEFODtIY7nHY0jQ,23412
|
|
299
298
|
flwr/superexec/__init__.py,sha256=fcj366jh4RFby_vDwLroU4kepzqbnJgseZD_jUr_Mko,715
|
|
300
|
-
flwr/superexec/app.py,sha256=
|
|
301
|
-
flwr/superexec/deployment.py,sha256=
|
|
302
|
-
flwr/superexec/exec_grpc.py,sha256=
|
|
303
|
-
flwr/superexec/exec_servicer.py,sha256=
|
|
304
|
-
flwr/superexec/executor.py,sha256
|
|
305
|
-
flwr/superexec/simulation.py,sha256=
|
|
306
|
-
flwr_nightly-1.13.0.
|
|
307
|
-
flwr_nightly-1.13.0.
|
|
308
|
-
flwr_nightly-1.13.0.
|
|
309
|
-
flwr_nightly-1.13.0.
|
|
310
|
-
flwr_nightly-1.13.0.
|
|
299
|
+
flwr/superexec/app.py,sha256=Tt3GonnTwHrMmicwx9XaP-crP78-bf4DUWl-N5cG6zY,1841
|
|
300
|
+
flwr/superexec/deployment.py,sha256=3uAauE8mI4bHwVF4_Rp26mXy18QnnIRlQD_yDo_Xs00,6780
|
|
301
|
+
flwr/superexec/exec_grpc.py,sha256=OuhBAk7hiky9rjGceinLGIXqchtzGPQThZnwyYv6Ei0,2241
|
|
302
|
+
flwr/superexec/exec_servicer.py,sha256=9MdFODQkLK_942XwaqwwIi1OP0Tiv3Mh7smj4mbreBE,5124
|
|
303
|
+
flwr/superexec/executor.py,sha256=125FvdpjT_awBCREm_YkLMg0YgToarVg7Y3wPt5tXQA,3126
|
|
304
|
+
flwr/superexec/simulation.py,sha256=PGADPXcfFVOss4uwPvFq_6vrIlkxezHppnBPAYWUBuU,7739
|
|
305
|
+
flwr_nightly-1.13.0.dev20241024.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
306
|
+
flwr_nightly-1.13.0.dev20241024.dist-info/METADATA,sha256=qKxbod-8iSCiu3FrCRwd9YDAZTsOl6yfqP7Ty4HVf7A,15618
|
|
307
|
+
flwr_nightly-1.13.0.dev20241024.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
308
|
+
flwr_nightly-1.13.0.dev20241024.dist-info/entry_points.txt,sha256=FxJQ96pmcNF2OvkTH6XF-Ip2PNrHvykjArkvkjQC7Mk,486
|
|
309
|
+
flwr_nightly-1.13.0.dev20241024.dist-info/RECORD,,
|
flwr/client/node_state_tests.py
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Copyright 2023 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
|
-
"""Node state tests."""
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
from typing import cast
|
|
19
|
-
|
|
20
|
-
from flwr.client.run_info_store import DeprecatedRunInfoStore
|
|
21
|
-
from flwr.common import ConfigsRecord, Context
|
|
22
|
-
from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def _run_dummy_task(context: Context) -> Context:
|
|
26
|
-
counter_value: str = "1"
|
|
27
|
-
if "counter" in context.state.configs_records.keys():
|
|
28
|
-
counter_value = cast(str, context.state.configs_records["counter"]["count"])
|
|
29
|
-
counter_value += "1"
|
|
30
|
-
|
|
31
|
-
context.state.configs_records["counter"] = ConfigsRecord({"count": counter_value})
|
|
32
|
-
|
|
33
|
-
return context
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def test_multirun_in_node_state() -> None:
|
|
37
|
-
"""Test basic DeprecatedRunInfoStore logic."""
|
|
38
|
-
# Tasks to perform
|
|
39
|
-
tasks = [TaskIns(run_id=run_id) for run_id in [0, 1, 1, 2, 3, 2, 1, 5]]
|
|
40
|
-
# the "tasks" is to count how many times each run is executed
|
|
41
|
-
expected_values = {0: "1", 1: "1" * 3, 2: "1" * 2, 3: "1", 5: "1"}
|
|
42
|
-
|
|
43
|
-
node_info_store = DeprecatedRunInfoStore(node_id=0, node_config={})
|
|
44
|
-
|
|
45
|
-
for task in tasks:
|
|
46
|
-
run_id = task.run_id
|
|
47
|
-
|
|
48
|
-
# Register
|
|
49
|
-
node_info_store.register_context(run_id=run_id)
|
|
50
|
-
|
|
51
|
-
# Get run state
|
|
52
|
-
context = node_info_store.retrieve_context(run_id=run_id)
|
|
53
|
-
|
|
54
|
-
# Run "task"
|
|
55
|
-
updated_state = _run_dummy_task(context)
|
|
56
|
-
|
|
57
|
-
# Update run state
|
|
58
|
-
node_info_store.update_context(run_id=run_id, context=updated_state)
|
|
59
|
-
|
|
60
|
-
# Verify values
|
|
61
|
-
for run_id, run_info in node_info_store.run_infos.items():
|
|
62
|
-
assert (
|
|
63
|
-
run_info.context.state.configs_records["counter"]["count"]
|
|
64
|
-
== expected_values[run_id]
|
|
65
|
-
)
|
{flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.13.0.dev20241023.dist-info → flwr_nightly-1.13.0.dev20241024.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|