flwr-nightly 1.19.0.dev20250513__py3-none-any.whl → 1.19.0.dev20250514__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.
@@ -4,7 +4,9 @@ isort:skip_file
4
4
  """
5
5
  import abc
6
6
  import flwr.proto.fab_pb2
7
+ import flwr.proto.heartbeat_pb2
7
8
  import flwr.proto.log_pb2
9
+ import flwr.proto.message_pb2
8
10
  import flwr.proto.run_pb2
9
11
  import flwr.proto.serverappio_pb2
10
12
  import grpc
@@ -66,6 +68,21 @@ class ServerAppIoStub:
66
68
  flwr.proto.log_pb2.PushLogsResponse]
67
69
  """Push ServerApp logs"""
68
70
 
71
+ SendAppHeartbeat: grpc.UnaryUnaryMultiCallable[
72
+ flwr.proto.heartbeat_pb2.SendAppHeartbeatRequest,
73
+ flwr.proto.heartbeat_pb2.SendAppHeartbeatResponse]
74
+ """Heartbeat"""
75
+
76
+ PushObject: grpc.UnaryUnaryMultiCallable[
77
+ flwr.proto.message_pb2.PushObjectRequest,
78
+ flwr.proto.message_pb2.PushObjectResponse]
79
+ """Push Object"""
80
+
81
+ PullObject: grpc.UnaryUnaryMultiCallable[
82
+ flwr.proto.message_pb2.PullObjectRequest,
83
+ flwr.proto.message_pb2.PullObjectResponse]
84
+ """Pull Object"""
85
+
69
86
 
70
87
  class ServerAppIoServicer(metaclass=abc.ABCMeta):
71
88
  @abc.abstractmethod
@@ -156,5 +173,29 @@ class ServerAppIoServicer(metaclass=abc.ABCMeta):
156
173
  """Push ServerApp logs"""
157
174
  pass
158
175
 
176
+ @abc.abstractmethod
177
+ def SendAppHeartbeat(self,
178
+ request: flwr.proto.heartbeat_pb2.SendAppHeartbeatRequest,
179
+ context: grpc.ServicerContext,
180
+ ) -> flwr.proto.heartbeat_pb2.SendAppHeartbeatResponse:
181
+ """Heartbeat"""
182
+ pass
183
+
184
+ @abc.abstractmethod
185
+ def PushObject(self,
186
+ request: flwr.proto.message_pb2.PushObjectRequest,
187
+ context: grpc.ServicerContext,
188
+ ) -> flwr.proto.message_pb2.PushObjectResponse:
189
+ """Push Object"""
190
+ pass
191
+
192
+ @abc.abstractmethod
193
+ def PullObject(self,
194
+ request: flwr.proto.message_pb2.PullObjectRequest,
195
+ context: grpc.ServicerContext,
196
+ ) -> flwr.proto.message_pb2.PullObjectResponse:
197
+ """Pull Object"""
198
+ pass
199
+
159
200
 
160
201
  def add_ServerAppIoServicer_to_server(servicer: ServerAppIoServicer, server: grpc.Server) -> None: ...
@@ -12,27 +12,28 @@ from google.protobuf.internal import builder as _builder
12
12
  _sym_db = _symbol_database.Default()
13
13
 
14
14
 
15
+ from flwr.proto import heartbeat_pb2 as flwr_dot_proto_dot_heartbeat__pb2
15
16
  from flwr.proto import log_pb2 as flwr_dot_proto_dot_log__pb2
16
17
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__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\x1d\x66lwr/proto/simulationio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"\x1d\n\x1bPullSimulationInputsRequest\"\x80\x01\n\x1cPullSimulationInputsResponse\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\"T\n\x1cPushSimulationOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1f\n\x1dPushSimulationOutputsResponse2\xd4\x04\n\x0cSimulationIo\x12k\n\x14PullSimulationInputs\x12\'.flwr.proto.PullSimulationInputsRequest\x1a(.flwr.proto.PullSimulationInputsResponse\"\x00\x12n\n\x15PushSimulationOutputs\x12(.flwr.proto.PushSimulationOutputsRequest\x1a).flwr.proto.PushSimulationOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x12k\n\x14GetFederationOptions\x12\'.flwr.proto.GetFederationOptionsRequest\x1a(.flwr.proto.GetFederationOptionsResponse\"\x00\x12S\n\x0cGetRunStatus\x12\x1f.flwr.proto.GetRunStatusRequest\x1a .flwr.proto.GetRunStatusResponse\"\x00\x62\x06proto3')
22
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66lwr/proto/simulationio.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"\x1d\n\x1bPullSimulationInputsRequest\"\x80\x01\n\x1cPullSimulationInputsResponse\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\"T\n\x1cPushSimulationOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1f\n\x1dPushSimulationOutputsResponse2\xb5\x05\n\x0cSimulationIo\x12k\n\x14PullSimulationInputs\x12\'.flwr.proto.PullSimulationInputsRequest\x1a(.flwr.proto.PullSimulationInputsResponse\"\x00\x12n\n\x15PushSimulationOutputs\x12(.flwr.proto.PushSimulationOutputsRequest\x1a).flwr.proto.PushSimulationOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x12k\n\x14GetFederationOptions\x12\'.flwr.proto.GetFederationOptionsRequest\x1a(.flwr.proto.GetFederationOptionsResponse\"\x00\x12S\n\x0cGetRunStatus\x12\x1f.flwr.proto.GetRunStatusRequest\x1a .flwr.proto.GetRunStatusResponse\"\x00\x12_\n\x10SendAppHeartbeat\x12#.flwr.proto.SendAppHeartbeatRequest\x1a$.flwr.proto.SendAppHeartbeatResponse\"\x00\x62\x06proto3')
22
23
 
23
24
  _globals = globals()
24
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
25
26
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.simulationio_pb2', _globals)
26
27
  if _descriptor._USE_C_DESCRIPTORS == False:
27
28
  DESCRIPTOR._options = None
28
- _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_start=137
29
- _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_end=166
30
- _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_start=169
31
- _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_end=297
32
- _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_start=299
33
- _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_end=383
34
- _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_start=385
35
- _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_end=416
36
- _globals['_SIMULATIONIO']._serialized_start=419
37
- _globals['_SIMULATIONIO']._serialized_end=1015
29
+ _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_start=165
30
+ _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_end=194
31
+ _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_start=197
32
+ _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_end=325
33
+ _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_start=327
34
+ _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_end=411
35
+ _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_start=413
36
+ _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_end=444
37
+ _globals['_SIMULATIONIO']._serialized_start=447
38
+ _globals['_SIMULATIONIO']._serialized_end=1140
38
39
  # @@protoc_insertion_point(module_scope)
@@ -2,6 +2,7 @@
2
2
  """Client and server classes corresponding to protobuf-defined services."""
3
3
  import grpc
4
4
 
5
+ from flwr.proto import heartbeat_pb2 as flwr_dot_proto_dot_heartbeat__pb2
5
6
  from flwr.proto import log_pb2 as flwr_dot_proto_dot_log__pb2
6
7
  from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
7
8
  from flwr.proto import simulationio_pb2 as flwr_dot_proto_dot_simulationio__pb2
@@ -46,6 +47,11 @@ class SimulationIoStub(object):
46
47
  request_serializer=flwr_dot_proto_dot_run__pb2.GetRunStatusRequest.SerializeToString,
47
48
  response_deserializer=flwr_dot_proto_dot_run__pb2.GetRunStatusResponse.FromString,
48
49
  )
50
+ self.SendAppHeartbeat = channel.unary_unary(
51
+ '/flwr.proto.SimulationIo/SendAppHeartbeat',
52
+ request_serializer=flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatRequest.SerializeToString,
53
+ response_deserializer=flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatResponse.FromString,
54
+ )
49
55
 
50
56
 
51
57
  class SimulationIoServicer(object):
@@ -93,6 +99,13 @@ class SimulationIoServicer(object):
93
99
  context.set_details('Method not implemented!')
94
100
  raise NotImplementedError('Method not implemented!')
95
101
 
102
+ def SendAppHeartbeat(self, request, context):
103
+ """Heartbeat
104
+ """
105
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
106
+ context.set_details('Method not implemented!')
107
+ raise NotImplementedError('Method not implemented!')
108
+
96
109
 
97
110
  def add_SimulationIoServicer_to_server(servicer, server):
98
111
  rpc_method_handlers = {
@@ -126,6 +139,11 @@ def add_SimulationIoServicer_to_server(servicer, server):
126
139
  request_deserializer=flwr_dot_proto_dot_run__pb2.GetRunStatusRequest.FromString,
127
140
  response_serializer=flwr_dot_proto_dot_run__pb2.GetRunStatusResponse.SerializeToString,
128
141
  ),
142
+ 'SendAppHeartbeat': grpc.unary_unary_rpc_method_handler(
143
+ servicer.SendAppHeartbeat,
144
+ request_deserializer=flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatRequest.FromString,
145
+ response_serializer=flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatResponse.SerializeToString,
146
+ ),
129
147
  }
130
148
  generic_handler = grpc.method_handlers_generic_handler(
131
149
  'flwr.proto.SimulationIo', rpc_method_handlers)
@@ -237,3 +255,20 @@ class SimulationIo(object):
237
255
  flwr_dot_proto_dot_run__pb2.GetRunStatusResponse.FromString,
238
256
  options, channel_credentials,
239
257
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
258
+
259
+ @staticmethod
260
+ def SendAppHeartbeat(request,
261
+ target,
262
+ options=(),
263
+ channel_credentials=None,
264
+ call_credentials=None,
265
+ insecure=False,
266
+ compression=None,
267
+ wait_for_ready=None,
268
+ timeout=None,
269
+ metadata=None):
270
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/SendAppHeartbeat',
271
+ flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatRequest.SerializeToString,
272
+ flwr_dot_proto_dot_heartbeat__pb2.SendAppHeartbeatResponse.FromString,
273
+ options, channel_credentials,
274
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@@ -3,6 +3,7 @@
3
3
  isort:skip_file
4
4
  """
5
5
  import abc
6
+ import flwr.proto.heartbeat_pb2
6
7
  import flwr.proto.log_pb2
7
8
  import flwr.proto.run_pb2
8
9
  import flwr.proto.simulationio_pb2
@@ -40,6 +41,11 @@ class SimulationIoStub:
40
41
  flwr.proto.run_pb2.GetRunStatusResponse]
41
42
  """Get Run Status"""
42
43
 
44
+ SendAppHeartbeat: grpc.UnaryUnaryMultiCallable[
45
+ flwr.proto.heartbeat_pb2.SendAppHeartbeatRequest,
46
+ flwr.proto.heartbeat_pb2.SendAppHeartbeatResponse]
47
+ """Heartbeat"""
48
+
43
49
 
44
50
  class SimulationIoServicer(metaclass=abc.ABCMeta):
45
51
  @abc.abstractmethod
@@ -90,5 +96,13 @@ class SimulationIoServicer(metaclass=abc.ABCMeta):
90
96
  """Get Run Status"""
91
97
  pass
92
98
 
99
+ @abc.abstractmethod
100
+ def SendAppHeartbeat(self,
101
+ request: flwr.proto.heartbeat_pb2.SendAppHeartbeatRequest,
102
+ context: grpc.ServicerContext,
103
+ ) -> flwr.proto.heartbeat_pb2.SendAppHeartbeatResponse:
104
+ """Heartbeat"""
105
+ pass
106
+
93
107
 
94
108
  def add_SimulationIoServicer_to_server(servicer: SimulationIoServicer, server: grpc.Server) -> None: ...
@@ -38,6 +38,7 @@ from flwr.common.constant import (
38
38
  SubStatus,
39
39
  )
40
40
  from flwr.common.exit import ExitCode, flwr_exit
41
+ from flwr.common.heartbeat import HeartbeatSender, get_grpc_app_heartbeat_fn
41
42
  from flwr.common.logger import (
42
43
  log,
43
44
  mirror_output_to_queue,
@@ -117,6 +118,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
117
118
  success = True
118
119
  hash_run_id = None
119
120
  run_status = None
121
+ heartbeat_sender = None
120
122
  while True:
121
123
 
122
124
  try:
@@ -182,6 +184,16 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
182
184
  event_details={"run-id-hash": hash_run_id},
183
185
  )
184
186
 
187
+ # Set up heartbeat sender
188
+ heartbeat_fn = get_grpc_app_heartbeat_fn(
189
+ grid._stub,
190
+ run.run_id,
191
+ failure_message="Heartbeat failed unexpectedly. The SuperLink could "
192
+ "not find the provided run ID, or the run status is invalid.",
193
+ )
194
+ heartbeat_sender = HeartbeatSender(heartbeat_fn)
195
+ heartbeat_sender.start()
196
+
185
197
  # Load and run the ServerApp with the Grid
186
198
  updated_context = run_(
187
199
  grid=grid,
@@ -213,6 +225,11 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
213
225
  success = False
214
226
 
215
227
  finally:
228
+ # Stop heartbeat sender
229
+ if heartbeat_sender:
230
+ heartbeat_sender.stop()
231
+ heartbeat_sender = None
232
+
216
233
  # Stop log uploader for this run and upload final logs
217
234
  if log_uploader:
218
235
  stop_log_uploader(log_queue, log_uploader)
@@ -226,6 +243,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
226
243
  run_id=run.run_id, run_status=run_status_proto
227
244
  )
228
245
  )
246
+
229
247
  event(
230
248
  EventType.FLWR_SERVERAPP_RUN_LEAVE,
231
249
  event_details={"run-id-hash": hash_run_id, "success": success},
@@ -40,6 +40,10 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
40
40
  )
41
41
  from flwr.proto.grpcadapter_pb2 import MessageContainer # pylint: disable=E0611
42
42
  from flwr.proto.heartbeat_pb2 import SendNodeHeartbeatRequest # pylint: disable=E0611
43
+ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
44
+ PullObjectRequest,
45
+ PushObjectRequest,
46
+ )
43
47
  from flwr.proto.run_pb2 import GetRunRequest # pylint: disable=E0611
44
48
 
45
49
  from ..grpc_rere.fleet_servicer import FleetServicer
@@ -93,4 +97,8 @@ class GrpcAdapterServicer(grpcadapter_pb2_grpc.GrpcAdapterServicer, FleetService
93
97
  return _handle(request, context, PullMessagesRequest, self.PullMessages)
94
98
  if request.grpc_message_name == PushMessagesRequest.__qualname__:
95
99
  return _handle(request, context, PushMessagesRequest, self.PushMessages)
100
+ if request.grpc_message_name == PushObjectRequest.__qualname__:
101
+ return _handle(request, context, PushObjectRequest, self.PushObject)
102
+ if request.grpc_message_name == PullObjectRequest.__qualname__:
103
+ return _handle(request, context, PullObjectRequest, self.PullObject)
96
104
  raise ValueError(f"Invalid grpc_message_name: {request.grpc_message_name}")
@@ -20,6 +20,7 @@ from logging import DEBUG, INFO
20
20
  import grpc
21
21
  from google.protobuf.json_format import MessageToDict
22
22
 
23
+ from flwr.common.inflatable import check_body_len_consistency
23
24
  from flwr.common.logger import log
24
25
  from flwr.common.typing import InvalidRunStatusException
25
26
  from flwr.proto import fleet_pb2_grpc # pylint: disable=E0611
@@ -38,6 +39,12 @@ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
38
39
  SendNodeHeartbeatRequest,
39
40
  SendNodeHeartbeatResponse,
40
41
  )
42
+ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
43
+ PullObjectRequest,
44
+ PullObjectResponse,
45
+ PushObjectRequest,
46
+ PushObjectResponse,
47
+ )
41
48
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
42
49
  from flwr.server.superlink.ffs.ffs_factory import FfsFactory
43
50
  from flwr.server.superlink.fleet.message_handler import message_handler
@@ -158,3 +165,31 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
158
165
  abort_grpc_context(e.message, context)
159
166
 
160
167
  return res
168
+
169
+ def PushObject(
170
+ self, request: PushObjectRequest, context: grpc.ServicerContext
171
+ ) -> PushObjectResponse:
172
+ """Push an object to the ObjectStore."""
173
+ log(
174
+ DEBUG,
175
+ "[ServerAppIoServicer.PushObject] Push Object with object_id=%s",
176
+ request.object_id,
177
+ )
178
+
179
+ if not check_body_len_consistency(request.object_content):
180
+ # Cancel insertion in ObjectStore
181
+ context.abort(grpc.StatusCode.PERMISSION_DENIED, "Unexpected object length")
182
+
183
+ return PushObjectResponse()
184
+
185
+ def PullObject(
186
+ self, request: PullObjectRequest, context: grpc.ServicerContext
187
+ ) -> PullObjectResponse:
188
+ """Pull an object from the ObjectStore."""
189
+ log(
190
+ DEBUG,
191
+ "[ServerAppIoServicer.PullObject] Pull Object with object_id=%s",
192
+ request.object_id,
193
+ )
194
+
195
+ return PullObjectResponse()
@@ -24,6 +24,7 @@ import grpc
24
24
 
25
25
  from flwr.common import ConfigRecord, Message
26
26
  from flwr.common.constant import SUPERLINK_NODE_ID, Status
27
+ from flwr.common.inflatable import check_body_len_consistency
27
28
  from flwr.common.logger import log
28
29
  from flwr.common.serde import (
29
30
  context_from_proto,
@@ -40,10 +41,20 @@ from flwr.common.serde import (
40
41
  from flwr.common.typing import Fab, RunStatus
41
42
  from flwr.proto import serverappio_pb2_grpc # pylint: disable=E0611
42
43
  from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
44
+ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
45
+ SendAppHeartbeatRequest,
46
+ SendAppHeartbeatResponse,
47
+ )
43
48
  from flwr.proto.log_pb2 import ( # pylint: disable=E0611
44
49
  PushLogsRequest,
45
50
  PushLogsResponse,
46
51
  )
52
+ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
53
+ PullObjectRequest,
54
+ PullObjectResponse,
55
+ PushObjectRequest,
56
+ PushObjectResponse,
57
+ )
47
58
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
48
59
  from flwr.proto.run_pb2 import ( # pylint: disable=E0611
49
60
  CreateRunRequest,
@@ -362,6 +373,45 @@ class ServerAppIoServicer(serverappio_pb2_grpc.ServerAppIoServicer):
362
373
  }
363
374
  return GetRunStatusResponse(run_status_dict=run_status_dict)
364
375
 
376
+ def SendAppHeartbeat(
377
+ self, request: SendAppHeartbeatRequest, context: grpc.ServicerContext
378
+ ) -> SendAppHeartbeatResponse:
379
+ """Handle a heartbeat from the ServerApp."""
380
+ log(DEBUG, "ServerAppIoServicer.SendAppHeartbeat")
381
+
382
+ # Init state
383
+ state = self.state_factory.state()
384
+
385
+ # Acknowledge the heartbeat
386
+ # The app heartbeat can only be acknowledged if the run is in
387
+ # starting or running status.
388
+ success = state.acknowledge_app_heartbeat(
389
+ run_id=request.run_id,
390
+ heartbeat_interval=request.heartbeat_interval,
391
+ )
392
+
393
+ return SendAppHeartbeatResponse(success=success)
394
+
395
+ def PushObject(
396
+ self, request: PushObjectRequest, context: grpc.ServicerContext
397
+ ) -> PushObjectResponse:
398
+ """Push an object to the ObjectStore."""
399
+ log(DEBUG, "ServerAppIoServicer.PushObject")
400
+
401
+ if not check_body_len_consistency(request.object_content):
402
+ # Cancel insertion in ObjectStore
403
+ context.abort(grpc.StatusCode.PERMISSION_DENIED, "Unexpected object length")
404
+
405
+ return PushObjectResponse()
406
+
407
+ def PullObject(
408
+ self, request: PullObjectRequest, context: grpc.ServicerContext
409
+ ) -> PullObjectResponse:
410
+ """Pull an object from the ObjectStore."""
411
+ log(DEBUG, "ServerAppIoServicer.PullObject")
412
+
413
+ return PullObjectResponse()
414
+
365
415
 
366
416
  def _raise_if(validation_error: bool, request_name: str, detail: str) -> None:
367
417
  """Raise a `ValueError` with a detailed message if a validation error occurs."""
@@ -34,6 +34,10 @@ from flwr.common.serde import (
34
34
  )
35
35
  from flwr.common.typing import Fab, RunStatus
36
36
  from flwr.proto import simulationio_pb2_grpc
37
+ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
38
+ SendAppHeartbeatRequest,
39
+ SendAppHeartbeatResponse,
40
+ )
37
41
  from flwr.proto.log_pb2 import ( # pylint: disable=E0611
38
42
  PushLogsRequest,
39
43
  PushLogsResponse,
@@ -184,3 +188,22 @@ class SimulationIoServicer(simulationio_pb2_grpc.SimulationIoServicer):
184
188
  return GetFederationOptionsResponse(
185
189
  federation_options=config_record_to_proto(federation_options)
186
190
  )
191
+
192
+ def SendAppHeartbeat(
193
+ self, request: SendAppHeartbeatRequest, context: grpc.ServicerContext
194
+ ) -> SendAppHeartbeatResponse:
195
+ """Handle a heartbeat from the ServerApp in simulation."""
196
+ log(DEBUG, "SimultionIoServicer.SendAppHeartbeat")
197
+
198
+ # Init state
199
+ state = self.state_factory.state()
200
+
201
+ # Acknowledge the heartbeat
202
+ # The app heartbeat can only be acknowledged if the run is in
203
+ # starting or running status.
204
+ success = state.acknowledge_app_heartbeat(
205
+ run_id=request.run_id,
206
+ heartbeat_interval=request.heartbeat_interval,
207
+ )
208
+
209
+ return SendAppHeartbeatResponse(success=success)
flwr/simulation/app.py CHANGED
@@ -39,6 +39,7 @@ from flwr.common.constant import (
39
39
  SubStatus,
40
40
  )
41
41
  from flwr.common.exit import ExitCode, flwr_exit
42
+ from flwr.common.heartbeat import HeartbeatSender, get_grpc_app_heartbeat_fn
42
43
  from flwr.common.logger import (
43
44
  log,
44
45
  mirror_output_to_queue,
@@ -120,6 +121,7 @@ def run_simulation_process( # pylint: disable=R0914, disable=W0212, disable=R09
120
121
  # Resolve directory where FABs are installed
121
122
  flwr_dir = get_flwr_dir(flwr_dir_)
122
123
  log_uploader = None
124
+ heartbeat_sender = None
123
125
 
124
126
  while True:
125
127
 
@@ -210,6 +212,16 @@ def run_simulation_process( # pylint: disable=R0914, disable=W0212, disable=R09
210
212
  },
211
213
  )
212
214
 
215
+ # Set up heartbeat sender
216
+ heartbeat_fn = get_grpc_app_heartbeat_fn(
217
+ conn._stub,
218
+ run.run_id,
219
+ failure_message="Heartbeat failed unexpectedly. The SuperLink could "
220
+ "not find the provided run ID, or the run status is invalid.",
221
+ )
222
+ heartbeat_sender = HeartbeatSender(heartbeat_fn)
223
+ heartbeat_sender.start()
224
+
213
225
  # Launch the simulation
214
226
  updated_context = _run_simulation(
215
227
  server_app_attr=server_app_attr,
@@ -240,6 +252,11 @@ def run_simulation_process( # pylint: disable=R0914, disable=W0212, disable=R09
240
252
  run_status = RunStatus(Status.FINISHED, SubStatus.FAILED, str(ex))
241
253
 
242
254
  finally:
255
+ # Stop heartbeat sender
256
+ if heartbeat_sender:
257
+ heartbeat_sender.stop()
258
+ heartbeat_sender = None
259
+
243
260
  # Stop log uploader for this run and upload final logs
244
261
  if log_uploader:
245
262
  stop_log_uploader(log_queue, log_uploader)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.19.0.dev20250513
3
+ Version: 1.19.0.dev20250514
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -87,7 +87,7 @@ flwr/client/grpc_client/connection.py,sha256=xAyvcTVr7bkwUfR5P3D_LKlZYiyySpt5sEw
87
87
  flwr/client/grpc_rere_client/__init__.py,sha256=i7iS0Lt8B7q0E2L72e4F_YrKm6ClRKnd71PNA6PW2O0,752
88
88
  flwr/client/grpc_rere_client/client_interceptor.py,sha256=zFaVHw6AxeNO-7eCKKb-RxrPa7zbM5Z-2-1Efc4adQY,2451
89
89
  flwr/client/grpc_rere_client/connection.py,sha256=Ukvvf0VGwYfcYIESpD49cw_TpvPke0dp7bGHbsnbmd0,12035
90
- flwr/client/grpc_rere_client/grpc_adapter.py,sha256=iFmNZIlM6bpUe3yp35EcFMKBhy6S5zupd7Yi_NwlZ_4,5745
90
+ flwr/client/grpc_rere_client/grpc_adapter.py,sha256=JvMZ7vCFTaTEo6AzKYh3zDmeQAU7VSjdysbC6t3ufWg,6351
91
91
  flwr/client/message_handler/__init__.py,sha256=0lyljDVqre3WljiZbPcwCCf8GiIaSVI_yo_ylEyPwSE,719
92
92
  flwr/client/message_handler/message_handler.py,sha256=-vZKGg2gP81182LFXDmiZtajLlIfZjV6FyMS43qQVwU,6532
93
93
  flwr/client/mod/__init__.py,sha256=AtV4Y5UGuYqJdTg7bJ--KtfOZUYLGDPMy616LvtP5W4,1151
@@ -128,8 +128,8 @@ flwr/common/exit/exit.py,sha256=mJgbqMlVlwAgYtq-Vedj53wO4VxcDcy_P-GzqGK-1GQ,3452
128
128
  flwr/common/exit/exit_code.py,sha256=PNEnCrZfOILjfDAFu5m-2YWEJBrk97xglq4zCUlqV7E,3470
129
129
  flwr/common/exit_handlers.py,sha256=MEk5_savTLphn-6lW57UQlos-XrFA39XEBn-OF1vXXg,3174
130
130
  flwr/common/grpc.py,sha256=manTaHaPiyYngUq1ErZvvV2B2GxlXUUUGRy3jc3TBIQ,9798
131
- flwr/common/heartbeat.py,sha256=nU0SNlL0A6t736ku7D7z7UUB1vXaX9QIn2fsJJPWeBU,4125
132
- flwr/common/inflatable.py,sha256=o3PQejN8GNm_xlHKJLB1h2wQzOXKkDfaiy6z5o142pA,3681
131
+ flwr/common/heartbeat.py,sha256=SyEpNDnmJ0lni0cWO67rcoJVKasCLmkNHm3dKLeNrLU,5749
132
+ flwr/common/inflatable.py,sha256=tErMOhZnkj3VGRe7ihZINBdAWnlkvsycPgwmYLF4AtQ,4419
133
133
  flwr/common/logger.py,sha256=JbRf6E2vQxXzpDBq1T8IDUJo_usu3gjWEBPQ6uKcmdg,13049
134
134
  flwr/common/message.py,sha256=znr205Erq2hkxwFbvNNCsQTRS2UKv_Qsyu0sFNEhEAw,23721
135
135
  flwr/common/object_ref.py,sha256=p3SfTeqo3Aj16SkB-vsnNn01zswOPdGNBitcbRnqmUk,9134
@@ -175,24 +175,24 @@ flwr/proto/fab_pb2.py,sha256=2Nu0WaWxDZ8TbutMtctjdcGM7OtXiyP4kmCgg5o7Jjw,1627
175
175
  flwr/proto/fab_pb2.pyi,sha256=AMXpiDK0fo3nZWjxsC2E4otSaVjyQbU7iiWKrsSZavs,2395
176
176
  flwr/proto/fab_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
177
177
  flwr/proto/fab_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
178
- flwr/proto/fleet_pb2.py,sha256=3URNlCJZcJm0bh-YeG-r9dTNgo9kc2JAn-zhsKr6l7U,4592
178
+ flwr/proto/fleet_pb2.py,sha256=FB-FnqNi0f5A8t8vycG_frOx9l9EzN3jtmwiDPcKuP0,4792
179
179
  flwr/proto/fleet_pb2.pyi,sha256=ugXXUx2K6mbeWqOxBzoa2B1Uc2d2d03T2z8wS56vLD0,6777
180
- flwr/proto/fleet_pb2_grpc.py,sha256=eJHJX3K33js5jQ0jYPHSWRkBFDX2dSEuqiXZSQ3YfoE,12527
181
- flwr/proto/fleet_pb2_grpc.pyi,sha256=K-wyX8k7zs6isiEIzxFTNYAydekb9ptJHzzp-PuTeQ0,3366
180
+ flwr/proto/fleet_pb2_grpc.py,sha256=pYQwwZ8KUZFmbYaJKJ8YJ06QCilhLqI_9vc0bBFXrNI,15779
181
+ flwr/proto/fleet_pb2_grpc.pyi,sha256=F--4QaDeoCHFuyOB506wHoMlQ4fPHvf8MoiVei_9jr8,4214
182
182
  flwr/proto/grpcadapter_pb2.py,sha256=PJ8DtfeV29g_y4Z3aNZlSZocLqSxeLmTsYCdOZDYCiE,1843
183
183
  flwr/proto/grpcadapter_pb2.pyi,sha256=AR77gDsF6f8zqSIQp3877DUd7S8lP95lFak5Ir_WPkw,1716
184
184
  flwr/proto/grpcadapter_pb2_grpc.py,sha256=rRNuNES5nBugUZWfeA8oAy8dMHgzqU_PF1srTseo3b8,2634
185
185
  flwr/proto/grpcadapter_pb2_grpc.pyi,sha256=AgA9Qo_lnANb9SNuPzbZGAxupau-xcqYawZz6vqf-24,735
186
- flwr/proto/heartbeat_pb2.py,sha256=gC2lGgio5Fn1U7fbb64JuQ1wM8cK7e2I05x9BtAuAuo,1482
187
- flwr/proto/heartbeat_pb2.pyi,sha256=5VP-zdZUJRva-F4JydpDmMZ5VyE1CipR0l8Gk0Kj2cU,1534
186
+ flwr/proto/heartbeat_pb2.py,sha256=2GMFmdf_4UFHxI-FzOzPfuk4DDx4pUztul-uBl8_7q0,1916
187
+ flwr/proto/heartbeat_pb2.pyi,sha256=yVtS-CfRJns6_nz0jTJNVw-gTyeHPkxThbaV4L-7uYA,2621
188
188
  flwr/proto/heartbeat_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
189
189
  flwr/proto/heartbeat_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
190
190
  flwr/proto/log_pb2.py,sha256=iKaS3MVn1BS4xHu8uGPFCOi1KWtvVx-H9V4jCUIJghs,1393
191
191
  flwr/proto/log_pb2.pyi,sha256=ipuhgo40sAHTcRzCsGI1HwIstr5q0THPNk_cf62YyME,1448
192
192
  flwr/proto/log_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
193
193
  flwr/proto/log_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
194
- flwr/proto/message_pb2.py,sha256=ob77p0WOtDYAvKhVoGOSPriGtVuSSfMw9WR7G7FkAJk,3198
195
- flwr/proto/message_pb2.pyi,sha256=DPUti2q_VJpRsy6Fzc5OPVm8j3Ko4OgN8IuEiFV4KOo,5759
194
+ flwr/proto/message_pb2.py,sha256=m0RTI5J69FEOFeKJsdyb0fUfaY-5x7s8_omBI-BRAtw,3909
195
+ flwr/proto/message_pb2.pyi,sha256=zFxk7VQL7iACanaIluVGF1mzImzHvpggRt4aWOIJb4c,7502
196
196
  flwr/proto/message_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
197
197
  flwr/proto/message_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
198
198
  flwr/proto/node_pb2.py,sha256=BzZfAWIX7lV62bZr9f7x16lUZcpg-EImxnwxQXgCbYg,1045
@@ -207,14 +207,14 @@ flwr/proto/run_pb2.py,sha256=9ArAxGT-SgOaIZG-WN6tb-rpka1jLTkaJpDAA39JXeY,5745
207
207
  flwr/proto/run_pb2.pyi,sha256=NEz0uJmTpbSGGuYWPVoSog7tS-XjBkaJNdB2l_io2SI,11740
208
208
  flwr/proto/run_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
209
209
  flwr/proto/run_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
210
- flwr/proto/serverappio_pb2.py,sha256=WijK7rejbb7h6GVK0pTf81Ey5Ltf7A_S7aKlUJWlny4,4908
210
+ flwr/proto/serverappio_pb2.py,sha256=iaE3twmUl6P0EiMmgECbZ9wpUwOKG_RdO6s66OoicVE,5331
211
211
  flwr/proto/serverappio_pb2.pyi,sha256=8Q81UXbBCArSXnma6-rXUE_vKneCowZjY4W4JmLaH0c,6450
212
- flwr/proto/serverappio_pb2_grpc.py,sha256=gwc2TbZShtSnR6RYu8d-3UtS6KecwnThYpO2JA4YZ6M,19130
213
- flwr/proto/serverappio_pb2_grpc.pyi,sha256=_pxplIFYZcuLTs9oA1RcZrCFEsh-33f4yBfhp8UL6f0,5268
214
- flwr/proto/simulationio_pb2.py,sha256=GOOmivAJPLQ6mPXrfKS8CyYeE6Kk-Q5mInLz5pyZSsU,3117
212
+ flwr/proto/serverappio_pb2_grpc.py,sha256=e0X_tVI6Qtr47BhH7U8nKK04kI_1xPwxaM-gg4x69KM,24171
213
+ flwr/proto/serverappio_pb2_grpc.pyi,sha256=1QegiFP3aofVNPuunE6hr_MClr40UzBWo_TEX5IUjlQ,6597
214
+ flwr/proto/simulationio_pb2.py,sha256=sAJX72z-IttVGxyU3PFnG8AFuA-pV7itvBoxz-hOudE,3342
215
215
  flwr/proto/simulationio_pb2.pyi,sha256=oXx8_FLBe5B54wduZj-f89kub73XxNtQbThuW8YfPAs,2660
216
- flwr/proto/simulationio_pb2_grpc.py,sha256=9I3yAfJaeMuG-qH_5Ge45eFOftsIOmL9b8E_xHmcvKw,11232
217
- flwr/proto/simulationio_pb2_grpc.pyi,sha256=YHvKtyo7UdbBgdhoN0ndzZeB5vIC3JuR5PAJLrl-OKM,3206
216
+ flwr/proto/simulationio_pb2_grpc.py,sha256=HuGbhOwV_A5GTbvmd5XTm6lSm9fWUgKcxq9OKhgmBT0,12999
217
+ flwr/proto/simulationio_pb2_grpc.pyi,sha256=KaGjpR6nH9XLM6oAPjgX-HrGbJU0dAnk9GpNjMkiR54,3687
218
218
  flwr/proto/transport_pb2.py,sha256=P-jX_tUyk_8xFe-vIUUSfZlHGtk2Ou3A8eXdBKkp5AY,9824
219
219
  flwr/proto/transport_pb2.pyi,sha256=ipHQ03eFBqsxtAuAVefZ2lVr04BZ4YifJCS2eauNmy8,21627
220
220
  flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPcosk,2598
@@ -241,7 +241,7 @@ flwr/server/server.py,sha256=39m4FSN2T-uVA-no9nstN0eWW0co-IUUAIMmpd3V7Jc,17893
241
241
  flwr/server/server_app.py,sha256=8uagoZX-3CY3tazPqkIV9jY-cN0YrRRrDmVe23o0AV0,9515
242
242
  flwr/server/server_config.py,sha256=e_6ddh0riwOJsdNn2BFev344uMWfDk9n7dyjNpPgm1w,1349
243
243
  flwr/server/serverapp/__init__.py,sha256=xcC0T_MQSMS9cicUzUUpMNCOsF2d8Oh_8jvnoBLuZvo,800
244
- flwr/server/serverapp/app.py,sha256=6qdcXfkieNUS_ot16zntJHaJ570IiiyxtcdCGSOGiSs,8623
244
+ flwr/server/serverapp/app.py,sha256=500dSi6C8IrvvHaCsGk9HB6O8GWRV07BUeetik47Jr0,9305
245
245
  flwr/server/serverapp_components.py,sha256=dfSqmrsVy3arKXpl3ZIBQWdV8rehfIms8aJooyzdmEM,2118
246
246
  flwr/server/strategy/__init__.py,sha256=HhsSWMWaC7oCb2g7Kqn1MBKdrfvgi8VxACy9ZL706Q0,2836
247
247
  flwr/server/strategy/aggregate.py,sha256=smlKKy-uFUuuFR12vlclucnwSQWRz78R79-Km4RWqbw,13978
@@ -274,14 +274,14 @@ flwr/server/superlink/ffs/ffs.py,sha256=6w7wy71i7tbuJwqEgdeCa49JejXMEof3jujURN_R
274
274
  flwr/server/superlink/ffs/ffs_factory.py,sha256=pK-g3LMelvWTV6N9Cd-j-_-FdcGbRFTKNsWaqmlBDSk,1490
275
275
  flwr/server/superlink/fleet/__init__.py,sha256=Uiwr33yfW_eL-pEfj80c_JUhIKRkCPsN1JSs2v4aglU,711
276
276
  flwr/server/superlink/fleet/grpc_adapter/__init__.py,sha256=fUu1V63YrzjxAOZnBJx99WjuD4Mro7dJIFH-1V4NLV8,742
277
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=78oXtJ1wsi2eNj_tk2rUbBxWi04PX_n9uz-2iIkG7mQ,4299
277
+ flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=Jdhesi4FUBFsdAnslzB4XaJQzERyCS2F8zeNnvBz9Wo,4715
278
278
  flwr/server/superlink/fleet/grpc_bidi/__init__.py,sha256=dOM49q1b9MrtUr5jldjEnQ38NhcUyYs-zC3gsJb1TtI,735
279
279
  flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py,sha256=UKEp-3YBaTvNt7vKZW7KLgK5xsAiO7jxU-omG7CaO_s,6021
280
280
  flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py,sha256=KouR9PUcrPmMtoLooF4O9SRAwIvfiroo8mPmqUc2EZc,6485
281
281
  flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=iSf0mbBAlig7G6subQwBSVjcUCgSihONKdZ1RmQPTOk,4887
282
282
  flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=OsS-6GgCIzMMZDVu5Y-OKjynHVUrpdc_5OrtuB-IbU0,5174
283
283
  flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=ahDJJ1e-lDxBpeBMgPk7YZt2wB38_QltcpOC0gLbpFs,758
284
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=lwGYN_BZzth106HmWOS57MJEqDwa7mn5Kct7Vn-veOw,5758
284
+ flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=mUEEMqwkI3b5e7hYckRtMaYgARtRDPyrcCDv14-w6t4,6901
285
285
  flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=DrHubsaLgJCwCeeJPYogQTiP0xYqjxwnT9rh7OP7BoU,6984
286
286
  flwr/server/superlink/fleet/message_handler/__init__.py,sha256=fHsRV0KvJ8HtgSA4_YBsEzuhJLjO8p6xx4aCY2oE1p4,731
287
287
  flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=56LC_cPa_pZT1715WTCN0d7MmvdRXlyO7g_hb9zdJrA,5427
@@ -300,10 +300,10 @@ flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=E43YO88vdnG9GW6Rwh9Fb
300
300
  flwr/server/superlink/linkstate/utils.py,sha256=AJs9jTAEK7JnjF2AODXnOfy0pKAKpe6oUWPCanAP57s,15382
301
301
  flwr/server/superlink/serverappio/__init__.py,sha256=Fy4zJuoccZe5mZSEIpOmQvU6YeXFBa1M4eZuXXmJcn8,717
302
302
  flwr/server/superlink/serverappio/serverappio_grpc.py,sha256=opJ6SYwIAbu4NWEo3K-VxFO-tMSFmE4H3i2HwHIVRzw,2173
303
- flwr/server/superlink/serverappio/serverappio_servicer.py,sha256=olLC0PvFY09hRWSZyJvJo-ituSDX45fvEVGaTlKufu8,13122
303
+ flwr/server/superlink/serverappio/serverappio_servicer.py,sha256=27ETy6-dW23Y6aH-7PpfmSX-0MJZC4qEWkQjdnEmrLU,14869
304
304
  flwr/server/superlink/simulation/__init__.py,sha256=Ry8DrNaZCMcQXvUc4FoCN2m3dvUQgWjasfp015o3Ec4,718
305
305
  flwr/server/superlink/simulation/simulationio_grpc.py,sha256=0l0F-UjYEk6W7HZmI28PbJQLFxSi_vBHRkdchgdaSMQ,2224
306
- flwr/server/superlink/simulation/simulationio_servicer.py,sha256=tynWgDoEzygbKcneGJ0fSaaea47ZvoONmhFBX6Kjwyw,6905
306
+ flwr/server/superlink/simulation/simulationio_servicer.py,sha256=aJezU8RSJswcmWm7Eoy0BqsU13jrcfuFwX3ljm-cORM,7719
307
307
  flwr/server/superlink/utils.py,sha256=BpKJ8IQBzJ8nLfTD5plBA_Y9re5hIS2gQ_40fc-zno8,2137
308
308
  flwr/server/typing.py,sha256=LvO6gq7H6TAWhA9JFx0WyqHxU7FycyvhSsLjBLPgpts,1011
309
309
  flwr/server/utils/__init__.py,sha256=U4gM84-uUFddarODDQkO6SjNUuGhFcsHJZMjSEbezkU,884
@@ -316,7 +316,7 @@ flwr/server/workflow/secure_aggregation/__init__.py,sha256=vGkycLb65CxdaMkKsANxQ
316
316
  flwr/server/workflow/secure_aggregation/secagg_workflow.py,sha256=b_pKk7gmbahwyj0ftOOLXvu-AMtRHEc82N9PJTEO8dc,5839
317
317
  flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=DkayCsnlAya6Y2PZsueLgoUCMRtV-GbnW08RfWx_SXM,29460
318
318
  flwr/simulation/__init__.py,sha256=Gg6OsP1Z-ixc3-xxzvl7j7rz2Fijy9rzyEPpxgAQCeM,1556
319
- flwr/simulation/app.py,sha256=Srq-QE2dTgI8uLZCw5anU3XQZ0B_ClGi47SH1-8tZj8,9756
319
+ flwr/simulation/app.py,sha256=Uy3lPwAvfZECkWPLcC0oDXTwY14e4ou8itIcBltjmWE,10437
320
320
  flwr/simulation/legacy_app.py,sha256=nMISQqW0otJL1-2Kfd94O6BLlGS2IEmEPKTM2WGKrIs,15861
321
321
  flwr/simulation/ray_transport/__init__.py,sha256=ogd-0AMv2U-wBZ1r3sHWaDIOIrVqr88Xi6C8o4Dviy0,734
322
322
  flwr/simulation/ray_transport/ray_actor.py,sha256=JN3xTqFIr5Z750k92CcA_uavzOHhSWDwE2WCaecvpks,19147
@@ -333,7 +333,7 @@ flwr/superexec/exec_servicer.py,sha256=Z0YYfs6eNPhqn8rY0x_R04XgR2mKFpggt07IH0EhU
333
333
  flwr/superexec/exec_user_auth_interceptor.py,sha256=iqygALkOMBUu_s_R9G0mFThZA7HTUzuXCLgxLCefiwI,4440
334
334
  flwr/superexec/executor.py,sha256=M5ucqSE53jfRtuCNf59WFLqQvA1Mln4741TySeZE7qQ,3112
335
335
  flwr/superexec/simulation.py,sha256=j6YwUvBN7EQ09ID7MYOCVZ70PGbuyBy8f9bXU0EszEM,4088
336
- flwr_nightly-1.19.0.dev20250513.dist-info/METADATA,sha256=4dlTZbixbfPDUcDbK3OBZ3JwaIFV553qWtAcY4d6zpQ,15910
337
- flwr_nightly-1.19.0.dev20250513.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
338
- flwr_nightly-1.19.0.dev20250513.dist-info/entry_points.txt,sha256=2-1L-GNKhwGw2_7_RoH55vHw2SIHjdAQy3HAVAWl9PY,374
339
- flwr_nightly-1.19.0.dev20250513.dist-info/RECORD,,
336
+ flwr_nightly-1.19.0.dev20250514.dist-info/METADATA,sha256=02DeFDEsLHgKnvSEsx79uOLCXPASmJkup3b-g2hzftQ,15910
337
+ flwr_nightly-1.19.0.dev20250514.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
338
+ flwr_nightly-1.19.0.dev20250514.dist-info/entry_points.txt,sha256=2-1L-GNKhwGw2_7_RoH55vHw2SIHjdAQy3HAVAWl9PY,374
339
+ flwr_nightly-1.19.0.dev20250514.dist-info/RECORD,,