flwr-nightly 1.19.0.dev20250611__py3-none-any.whl → 1.19.0.dev20250613__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.
Files changed (43) hide show
  1. flwr/cli/ls.py +12 -33
  2. flwr/cli/utils.py +18 -1
  3. flwr/client/grpc_rere_client/connection.py +47 -29
  4. flwr/client/grpc_rere_client/grpc_adapter.py +8 -0
  5. flwr/client/rest_client/connection.py +70 -51
  6. flwr/common/constant.py +4 -0
  7. flwr/common/inflatable.py +24 -0
  8. flwr/common/serde.py +2 -0
  9. flwr/common/typing.py +2 -0
  10. flwr/proto/fleet_pb2.py +12 -16
  11. flwr/proto/fleet_pb2.pyi +4 -19
  12. flwr/proto/fleet_pb2_grpc.py +34 -0
  13. flwr/proto/fleet_pb2_grpc.pyi +13 -0
  14. flwr/proto/message_pb2.py +15 -9
  15. flwr/proto/message_pb2.pyi +41 -0
  16. flwr/proto/run_pb2.py +24 -24
  17. flwr/proto/run_pb2.pyi +4 -1
  18. flwr/proto/serverappio_pb2.py +22 -26
  19. flwr/proto/serverappio_pb2.pyi +4 -19
  20. flwr/proto/serverappio_pb2_grpc.py +34 -0
  21. flwr/proto/serverappio_pb2_grpc.pyi +13 -0
  22. flwr/server/app.py +1 -0
  23. flwr/server/grid/grpc_grid.py +20 -9
  24. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +25 -0
  25. flwr/server/superlink/fleet/message_handler/message_handler.py +33 -2
  26. flwr/server/superlink/fleet/rest_rere/rest_api.py +26 -2
  27. flwr/server/superlink/linkstate/in_memory_linkstate.py +20 -3
  28. flwr/server/superlink/linkstate/linkstate.py +6 -2
  29. flwr/server/superlink/linkstate/sqlite_linkstate.py +19 -7
  30. flwr/server/superlink/serverappio/serverappio_servicer.py +65 -29
  31. flwr/server/superlink/simulation/simulationio_servicer.py +2 -1
  32. flwr/server/superlink/utils.py +23 -10
  33. flwr/supercore/object_store/in_memory_object_store.py +160 -33
  34. flwr/supercore/object_store/object_store.py +54 -7
  35. flwr/superexec/deployment.py +6 -2
  36. flwr/superexec/exec_grpc.py +3 -0
  37. flwr/superexec/exec_servicer.py +125 -22
  38. flwr/superexec/executor.py +4 -0
  39. flwr/superexec/simulation.py +7 -1
  40. {flwr_nightly-1.19.0.dev20250611.dist-info → flwr_nightly-1.19.0.dev20250613.dist-info}/METADATA +1 -1
  41. {flwr_nightly-1.19.0.dev20250611.dist-info → flwr_nightly-1.19.0.dev20250613.dist-info}/RECORD +43 -43
  42. {flwr_nightly-1.19.0.dev20250611.dist-info → flwr_nightly-1.19.0.dev20250613.dist-info}/WHEEL +0 -0
  43. {flwr_nightly-1.19.0.dev20250611.dist-info → flwr_nightly-1.19.0.dev20250613.dist-info}/entry_points.txt +0 -0
flwr/cli/ls.py CHANGED
@@ -130,23 +130,16 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
130
130
  # Display information about a specific run ID
131
131
  if run_id is not None:
132
132
  typer.echo(f"🔍 Displaying information for run ID {run_id}...")
133
- restore_output()
134
- _display_one_run(stub, run_id, output_format)
133
+ formatted_runs = _display_one_run(stub, run_id)
135
134
  # By default, list all runs
136
135
  else:
137
136
  typer.echo("📄 Listing all runs...")
138
- restore_output()
139
- _list_runs(stub, output_format)
140
-
141
- except ValueError as err:
142
- if suppress_output:
143
- redirect_output(captured_output)
144
- typer.secho(
145
- f"❌ {err}",
146
- fg=typer.colors.RED,
147
- bold=True,
148
- )
149
- raise typer.Exit(code=1) from err
137
+ formatted_runs = _list_runs(stub)
138
+ restore_output()
139
+ if output_format == CliOutputFormat.JSON:
140
+ Console().print_json(_to_json(formatted_runs))
141
+ else:
142
+ Console().print(_to_table(formatted_runs))
150
143
  finally:
151
144
  if channel:
152
145
  channel.close()
@@ -300,37 +293,23 @@ def _to_json(run_list: list[_RunListType]) -> str:
300
293
  return json.dumps({"success": True, "runs": runs_list})
301
294
 
302
295
 
303
- def _list_runs(
304
- stub: ExecStub,
305
- output_format: str = CliOutputFormat.DEFAULT,
306
- ) -> None:
296
+ def _list_runs(stub: ExecStub) -> list[_RunListType]:
307
297
  """List all runs."""
308
298
  with flwr_cli_grpc_exc_handler():
309
299
  res: ListRunsResponse = stub.ListRuns(ListRunsRequest())
310
300
  run_dict = {run_id: run_from_proto(proto) for run_id, proto in res.run_dict.items()}
311
301
 
312
- formatted_runs = _format_runs(run_dict, res.now)
313
- if output_format == CliOutputFormat.JSON:
314
- Console().print_json(_to_json(formatted_runs))
315
- else:
316
- Console().print(_to_table(formatted_runs))
302
+ return _format_runs(run_dict, res.now)
317
303
 
318
304
 
319
- def _display_one_run(
320
- stub: ExecStub,
321
- run_id: int,
322
- output_format: str = CliOutputFormat.DEFAULT,
323
- ) -> None:
305
+ def _display_one_run(stub: ExecStub, run_id: int) -> list[_RunListType]:
324
306
  """Display information about a specific run."""
325
307
  with flwr_cli_grpc_exc_handler():
326
308
  res: ListRunsResponse = stub.ListRuns(ListRunsRequest(run_id=run_id))
327
309
  if not res.run_dict:
310
+ # This won't be reached as an gRPC error is raised if run_id is invalid
328
311
  raise ValueError(f"Run ID {run_id} not found")
329
312
 
330
313
  run_dict = {run_id: run_from_proto(proto) for run_id, proto in res.run_dict.items()}
331
314
 
332
- formatted_runs = _format_runs(run_dict, res.now)
333
- if output_format == CliOutputFormat.JSON:
334
- Console().print_json(_to_json(formatted_runs))
335
- else:
336
- Console().print(_to_table(formatted_runs))
315
+ return _format_runs(run_dict, res.now)
flwr/cli/utils.py CHANGED
@@ -28,7 +28,12 @@ import typer
28
28
 
29
29
  from flwr.cli.cli_user_auth_interceptor import CliUserAuthInterceptor
30
30
  from flwr.common.auth_plugin import CliAuthPlugin
31
- from flwr.common.constant import AUTH_TYPE_JSON_KEY, CREDENTIALS_DIR, FLWR_DIR
31
+ from flwr.common.constant import (
32
+ AUTH_TYPE_JSON_KEY,
33
+ CREDENTIALS_DIR,
34
+ FLWR_DIR,
35
+ RUN_ID_NOT_FOUND_MESSAGE,
36
+ )
32
37
  from flwr.common.grpc import (
33
38
  GRPC_MAX_MESSAGE_LENGTH,
34
39
  create_channel,
@@ -320,5 +325,17 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
320
325
  fg=typer.colors.RED,
321
326
  bold=True,
322
327
  )
328
+ # pylint: disable=E1101
329
+ typer.secho(e.details(), fg=typer.colors.RED, bold=True)
330
+ raise typer.Exit(code=1) from None
331
+ if (
332
+ e.code() == grpc.StatusCode.NOT_FOUND
333
+ and e.details() == RUN_ID_NOT_FOUND_MESSAGE
334
+ ):
335
+ typer.secho(
336
+ "❌ Run ID not found.",
337
+ fg=typer.colors.RED,
338
+ bold=True,
339
+ )
323
340
  raise typer.Exit(code=1) from None
324
341
  raise
@@ -31,7 +31,11 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH
31
31
  from flwr.common.constant import HEARTBEAT_CALL_TIMEOUT, HEARTBEAT_DEFAULT_INTERVAL
32
32
  from flwr.common.grpc import create_channel, on_channel_state_change
33
33
  from flwr.common.heartbeat import HeartbeatSender
34
- from flwr.common.inflatable import get_all_nested_objects
34
+ from flwr.common.inflatable import (
35
+ get_all_nested_objects,
36
+ get_object_tree,
37
+ no_object_id_recompute,
38
+ )
35
39
  from flwr.common.inflatable_grpc_utils import (
36
40
  make_pull_object_fn_grpc,
37
41
  make_push_object_fn_grpc,
@@ -63,7 +67,9 @@ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
63
67
  SendNodeHeartbeatRequest,
64
68
  SendNodeHeartbeatResponse,
65
69
  )
66
- from flwr.proto.message_pb2 import ObjectIDs # pylint: disable=E0611
70
+ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
71
+ ConfirmMessageReceivedRequest,
72
+ )
67
73
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
68
74
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
69
75
 
@@ -270,14 +276,23 @@ def grpc_request_response( # pylint: disable=R0913,R0914,R0915,R0917
270
276
 
271
277
  if message_proto:
272
278
  msg_id = message_proto.metadata.message_id
279
+ run_id = message_proto.metadata.run_id
273
280
  all_object_contents = pull_objects(
274
281
  list(response.objects_to_pull[msg_id].object_ids) + [msg_id],
275
282
  pull_object_fn=make_pull_object_fn_grpc(
276
283
  pull_object_grpc=stub.PullObject,
277
284
  node=node,
278
- run_id=message_proto.metadata.run_id,
285
+ run_id=run_id,
279
286
  ),
280
287
  )
288
+
289
+ # Confirm that the message has been received
290
+ stub.ConfirmMessageReceived(
291
+ ConfirmMessageReceivedRequest(
292
+ node=node, run_id=run_id, message_object_id=msg_id
293
+ )
294
+ )
295
+
281
296
  in_message = cast(
282
297
  Message, inflate_object_from_contents(msg_id, all_object_contents)
283
298
  )
@@ -312,33 +327,36 @@ def grpc_request_response( # pylint: disable=R0913,R0914,R0915,R0917
312
327
  log(ERROR, "Invalid out message")
313
328
  return
314
329
 
315
- # Get all nested objects
316
- all_objects = get_all_nested_objects(message)
317
- all_object_ids = list(all_objects.keys())
318
- msg_id = all_object_ids[-1] # Last object is the message itself
319
- descendant_ids = all_object_ids[:-1] # All but the last object are descendants
320
-
321
- # Serialize Message
322
- message_proto = message_to_proto(message=remove_content_from_message(message))
323
- request = PushMessagesRequest(
324
- node=node,
325
- messages_list=[message_proto],
326
- msg_to_descendant_mapping={msg_id: ObjectIDs(object_ids=descendant_ids)},
327
- )
328
- response: PushMessagesResponse = stub.PushMessages(request=request)
329
-
330
- if response.objects_to_push:
331
- objs_to_push = set(response.objects_to_push[message.object_id].object_ids)
332
- push_objects(
333
- all_objects,
334
- push_object_fn=make_push_object_fn_grpc(
335
- push_object_grpc=stub.PushObject,
336
- node=node,
337
- run_id=message.metadata.run_id,
338
- ),
339
- object_ids_to_push=objs_to_push,
330
+ with no_object_id_recompute():
331
+ # Get all nested objects
332
+ all_objects = get_all_nested_objects(message)
333
+ object_tree = get_object_tree(message)
334
+
335
+ # Serialize Message
336
+ message_proto = message_to_proto(
337
+ message=remove_content_from_message(message)
338
+ )
339
+ request = PushMessagesRequest(
340
+ node=node,
341
+ messages_list=[message_proto],
342
+ message_object_trees=[object_tree],
340
343
  )
341
- log(DEBUG, "Pushed %s objects to servicer.", len(objs_to_push))
344
+ response: PushMessagesResponse = stub.PushMessages(request=request)
345
+
346
+ if response.objects_to_push:
347
+ objs_to_push = set(
348
+ response.objects_to_push[message.object_id].object_ids
349
+ )
350
+ push_objects(
351
+ all_objects,
352
+ push_object_fn=make_push_object_fn_grpc(
353
+ push_object_grpc=stub.PushObject,
354
+ node=node,
355
+ run_id=message.metadata.run_id,
356
+ ),
357
+ object_ids_to_push=objs_to_push,
358
+ )
359
+ log(DEBUG, "Pushed %s objects to servicer.", len(objs_to_push))
342
360
 
343
361
  # Cleanup
344
362
  metadata = None
@@ -50,6 +50,8 @@ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
50
50
  SendNodeHeartbeatResponse,
51
51
  )
52
52
  from flwr.proto.message_pb2 import ( # pylint: disable=E0611
53
+ ConfirmMessageReceivedRequest,
54
+ ConfirmMessageReceivedResponse,
53
55
  PullObjectRequest,
54
56
  PullObjectResponse,
55
57
  PushObjectRequest,
@@ -169,3 +171,9 @@ class GrpcAdapter:
169
171
  ) -> PullObjectResponse:
170
172
  """."""
171
173
  return self._send_and_receive(request, PullObjectResponse, **kwargs)
174
+
175
+ def ConfirmMessageReceived( # pylint: disable=C0103
176
+ self, request: ConfirmMessageReceivedRequest, **kwargs: Any
177
+ ) -> ConfirmMessageReceivedResponse:
178
+ """."""
179
+ return self._send_and_receive(request, ConfirmMessageReceivedResponse, **kwargs)
@@ -30,7 +30,11 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH
30
30
  from flwr.common.constant import HEARTBEAT_DEFAULT_INTERVAL
31
31
  from flwr.common.exit import ExitCode, flwr_exit
32
32
  from flwr.common.heartbeat import HeartbeatSender
33
- from flwr.common.inflatable import get_all_nested_objects
33
+ from flwr.common.inflatable import (
34
+ get_all_nested_objects,
35
+ get_object_tree,
36
+ no_object_id_recompute,
37
+ )
34
38
  from flwr.common.inflatable_rest_utils import (
35
39
  make_pull_object_fn_rest,
36
40
  make_push_object_fn_rest,
@@ -60,8 +64,9 @@ from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
60
64
  SendNodeHeartbeatRequest,
61
65
  SendNodeHeartbeatResponse,
62
66
  )
63
- from flwr.proto.message_pb2 import ObjectIDs # pylint: disable=E0611
64
67
  from flwr.proto.message_pb2 import ( # pylint: disable=E0611
68
+ ConfirmMessageReceivedRequest,
69
+ ConfirmMessageReceivedResponse,
65
70
  PullObjectRequest,
66
71
  PullObjectResponse,
67
72
  PushObjectRequest,
@@ -85,6 +90,7 @@ PATH_PUSH_OBJECT: str = "/api/v0/fleet/push-object"
85
90
  PATH_SEND_NODE_HEARTBEAT: str = "api/v0/fleet/send-node-heartbeat"
86
91
  PATH_GET_RUN: str = "/api/v0/fleet/get-run"
87
92
  PATH_GET_FAB: str = "/api/v0/fleet/get-fab"
93
+ PATH_CONFIRM_MESSAGE_RECEIVED: str = "/api/v0/fleet/confirm-message-received"
88
94
 
89
95
  T = TypeVar("T", bound=GrpcMessage)
90
96
 
@@ -320,6 +326,7 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
320
326
  if message_proto:
321
327
  log(INFO, "[Node] POST /%s: success", PATH_PULL_MESSAGES)
322
328
  msg_id = message_proto.metadata.message_id
329
+ run_id = message_proto.metadata.run_id
323
330
 
324
331
  def fn(request: PullObjectRequest) -> PullObjectResponse:
325
332
  res = _request(
@@ -335,8 +342,17 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
335
342
  pull_object_fn=make_pull_object_fn_rest(
336
343
  pull_object_rest=fn,
337
344
  node=node,
338
- run_id=message_proto.metadata.run_id,
345
+ run_id=run_id,
346
+ ),
347
+ )
348
+
349
+ # Confirm that the message has been received
350
+ _request(
351
+ req=ConfirmMessageReceivedRequest(
352
+ node=node, run_id=run_id, message_object_id=msg_id
339
353
  ),
354
+ res_type=ConfirmMessageReceivedResponse,
355
+ api_path=PATH_CONFIRM_MESSAGE_RECEIVED,
340
356
  )
341
357
  except ValueError as e:
342
358
  log(
@@ -377,59 +393,62 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
377
393
  log(ERROR, "Invalid out message")
378
394
  return
379
395
 
380
- # Get all nested objects
381
- all_objects = get_all_nested_objects(message)
382
- all_object_ids = list(all_objects.keys())
383
- msg_id = all_object_ids[-1] # Last object is the message itself
384
- descendant_ids = all_object_ids[:-1] # All but the last object are descendants
385
-
386
- # Serialize Message
387
- message_proto = message_to_proto(message=remove_content_from_message(message))
388
- req = PushMessagesRequest(
389
- node=node,
390
- messages_list=[message_proto],
391
- msg_to_descendant_mapping={msg_id: ObjectIDs(object_ids=descendant_ids)},
392
- )
396
+ with no_object_id_recompute():
397
+ # Get all nested objects
398
+ all_objects = get_all_nested_objects(message)
399
+ object_tree = get_object_tree(message)
393
400
 
394
- # Send the request
395
- res = _request(req, PushMessagesResponse, PATH_PUSH_MESSAGES)
396
- if res:
397
- log(
398
- INFO,
399
- "[Node] POST /%s: success, created result %s",
400
- PATH_PUSH_MESSAGES,
401
- res.results, # pylint: disable=no-member
401
+ # Serialize Message
402
+ message_proto = message_to_proto(
403
+ message=remove_content_from_message(message)
404
+ )
405
+ req = PushMessagesRequest(
406
+ node=node,
407
+ messages_list=[message_proto],
408
+ message_object_trees=[object_tree],
402
409
  )
403
410
 
404
- if res and res.objects_to_push:
405
- objs_to_push = set(res.objects_to_push[message.object_id].object_ids)
406
-
407
- def fn(request: PushObjectRequest) -> PushObjectResponse:
408
- res = _request(
409
- req=request, res_type=PushObjectResponse, api_path=PATH_PUSH_OBJECT
410
- )
411
- if res is None:
412
- raise ValueError("PushObjectResponse is None.")
413
- return res
414
-
415
- try:
416
- push_objects(
417
- all_objects,
418
- push_object_fn=make_push_object_fn_rest(
419
- push_object_rest=fn,
420
- node=node,
421
- run_id=message_proto.metadata.run_id,
422
- ),
423
- object_ids_to_push=objs_to_push,
424
- )
425
- log(DEBUG, "Pushed %s objects to servicer.", len(objs_to_push))
426
- except ValueError as e:
411
+ # Send the request
412
+ res = _request(req, PushMessagesResponse, PATH_PUSH_MESSAGES)
413
+ if res:
427
414
  log(
428
- ERROR,
429
- "Pushing objects failed. Potential irrecoverable error: %s",
430
- str(e),
415
+ INFO,
416
+ "[Node] POST /%s: success, created result %s",
417
+ PATH_PUSH_MESSAGES,
418
+ res.results, # pylint: disable=no-member
431
419
  )
432
- log(ERROR, str(e))
420
+
421
+ if res and res.objects_to_push:
422
+ objs_to_push = set(res.objects_to_push[message.object_id].object_ids)
423
+
424
+ def fn(request: PushObjectRequest) -> PushObjectResponse:
425
+ res = _request(
426
+ req=request,
427
+ res_type=PushObjectResponse,
428
+ api_path=PATH_PUSH_OBJECT,
429
+ )
430
+ if res is None:
431
+ raise ValueError("PushObjectResponse is None.")
432
+ return res
433
+
434
+ try:
435
+ push_objects(
436
+ all_objects,
437
+ push_object_fn=make_push_object_fn_rest(
438
+ push_object_rest=fn,
439
+ node=node,
440
+ run_id=message_proto.metadata.run_id,
441
+ ),
442
+ object_ids_to_push=objs_to_push,
443
+ )
444
+ log(DEBUG, "Pushed %s objects to servicer.", len(objs_to_push))
445
+ except ValueError as e:
446
+ log(
447
+ ERROR,
448
+ "Pushing objects failed. Potential irrecoverable error: %s",
449
+ str(e),
450
+ )
451
+ log(ERROR, str(e))
433
452
 
434
453
  # Cleanup
435
454
  metadata = None
flwr/common/constant.py CHANGED
@@ -150,6 +150,10 @@ PULL_INITIAL_BACKOFF = 1 # Initial backoff time for pulling objects
150
150
  PULL_BACKOFF_CAP = 10 # Maximum backoff time for pulling objects
151
151
 
152
152
 
153
+ # ExecServicer constants
154
+ RUN_ID_NOT_FOUND_MESSAGE = "Run ID not found"
155
+
156
+
153
157
  class MessageType:
154
158
  """Message type."""
155
159
 
flwr/common/inflatable.py CHANGED
@@ -23,6 +23,8 @@ from collections.abc import Iterator
23
23
  from contextlib import contextmanager
24
24
  from typing import TypeVar, cast
25
25
 
26
+ from flwr.proto.message_pb2 import ObjectTree # pylint: disable=E0611
27
+
26
28
  from .constant import HEAD_BODY_DIVIDER, HEAD_VALUE_DIVIDER
27
29
 
28
30
 
@@ -264,3 +266,25 @@ def get_all_nested_objects(obj: InflatableObject) -> dict[str, InflatableObject]
264
266
  ret[obj.object_id] = obj
265
267
 
266
268
  return ret
269
+
270
+
271
+ def get_object_tree(obj: InflatableObject) -> ObjectTree:
272
+ """Get a tree representation of the InflatableObject."""
273
+ tree_children = []
274
+ if children := obj.children:
275
+ for child in children.values():
276
+ tree_children.append(get_object_tree(child))
277
+ return ObjectTree(object_id=obj.object_id, children=tree_children)
278
+
279
+
280
+ def iterate_object_tree(
281
+ tree: ObjectTree,
282
+ ) -> Iterator[ObjectTree]:
283
+ """Iterate over the object tree and yield object IDs.
284
+
285
+ This function performs a post-order traversal of the tree, yielding the object ID of
286
+ each node after all its children have been yielded.
287
+ """
288
+ for child in tree.children:
289
+ yield from iterate_object_tree(child)
290
+ yield tree
flwr/common/serde.py CHANGED
@@ -630,6 +630,7 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
630
630
  running_at=run.running_at,
631
631
  finished_at=run.finished_at,
632
632
  status=run_status_to_proto(run.status),
633
+ flwr_aid=run.flwr_aid,
633
634
  )
634
635
  return proto
635
636
 
@@ -647,6 +648,7 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
647
648
  running_at=run_proto.running_at,
648
649
  finished_at=run_proto.finished_at,
649
650
  status=run_status_from_proto(run_proto.status),
651
+ flwr_aid=run_proto.flwr_aid,
650
652
  )
651
653
  return run
652
654
 
flwr/common/typing.py CHANGED
@@ -230,6 +230,7 @@ class Run: # pylint: disable=too-many-instance-attributes
230
230
  running_at: str
231
231
  finished_at: str
232
232
  status: RunStatus
233
+ flwr_aid: str
233
234
 
234
235
  @classmethod
235
236
  def create_empty(cls, run_id: int) -> "Run":
@@ -245,6 +246,7 @@ class Run: # pylint: disable=too-many-instance-attributes
245
246
  running_at="",
246
247
  finished_at="",
247
248
  status=RunStatus(status="", sub_status="", details=""),
249
+ flwr_aid="",
248
250
  )
249
251
 
250
252
 
flwr/proto/fleet_pb2.py CHANGED
@@ -19,7 +19,7 @@ from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
19
19
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
20
20
 
21
21
 
22
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"/\n\x11\x43reateNodeRequest\x12\x1a\n\x12heartbeat_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\x87\x02\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12L\n\x0fobjects_to_pull\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PullMessagesResponse.ObjectsToPullEntry\x1aK\n\x12ObjectsToPullEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x97\x02\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12^\n\x19msg_to_descendant_mapping\x18\x03 \x03(\x0b\x32;.flwr.proto.PushMessagesRequest.MsgToDescendantMappingEntry\x1aT\n\x1bMsgToDescendantMappingEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\xcb\x02\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12L\n\x0fobjects_to_push\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PushMessagesResponse.ObjectsToPushEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1aK\n\x12ObjectsToPushEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xd7\x05\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x62\x06proto3')
22
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"/\n\x11\x43reateNodeRequest\x12\x1a\n\x12heartbeat_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\x87\x02\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12L\n\x0fobjects_to_pull\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PullMessagesResponse.ObjectsToPullEntry\x1aK\n\x12ObjectsToPullEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x97\x01\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\xcb\x02\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12L\n\x0fobjects_to_push\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PushMessagesResponse.ObjectsToPushEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1aK\n\x12ObjectsToPushEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xca\x06\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x12q\n\x16\x43onfirmMessageReceived\x12).flwr.proto.ConfirmMessageReceivedRequest\x1a*.flwr.proto.ConfirmMessageReceivedResponse\"\x00\x62\x06proto3')
23
23
 
24
24
  _globals = globals()
25
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -28,8 +28,6 @@ if _descriptor._USE_C_DESCRIPTORS == False:
28
28
  DESCRIPTOR._options = None
29
29
  _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._options = None
30
30
  _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_options = b'8\001'
31
- _globals['_PUSHMESSAGESREQUEST_MSGTODESCENDANTMAPPINGENTRY']._options = None
32
- _globals['_PUSHMESSAGESREQUEST_MSGTODESCENDANTMAPPINGENTRY']._serialized_options = b'8\001'
33
31
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._options = None
34
32
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
35
33
  _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._options = None
@@ -49,17 +47,15 @@ if _descriptor._USE_C_DESCRIPTORS == False:
49
47
  _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_start=602
50
48
  _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_end=677
51
49
  _globals['_PUSHMESSAGESREQUEST']._serialized_start=680
52
- _globals['_PUSHMESSAGESREQUEST']._serialized_end=959
53
- _globals['_PUSHMESSAGESREQUEST_MSGTODESCENDANTMAPPINGENTRY']._serialized_start=875
54
- _globals['_PUSHMESSAGESREQUEST_MSGTODESCENDANTMAPPINGENTRY']._serialized_end=959
55
- _globals['_PUSHMESSAGESRESPONSE']._serialized_start=962
56
- _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1293
57
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1170
58
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1216
59
- _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_start=1218
60
- _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_end=1293
61
- _globals['_RECONNECT']._serialized_start=1295
62
- _globals['_RECONNECT']._serialized_end=1325
63
- _globals['_FLEET']._serialized_start=1328
64
- _globals['_FLEET']._serialized_end=2055
50
+ _globals['_PUSHMESSAGESREQUEST']._serialized_end=831
51
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_start=834
52
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1165
53
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1042
54
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1088
55
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_start=1090
56
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_end=1165
57
+ _globals['_RECONNECT']._serialized_start=1167
58
+ _globals['_RECONNECT']._serialized_end=1197
59
+ _globals['_FLEET']._serialized_start=1200
60
+ _globals['_FLEET']._serialized_end=2042
65
61
  # @@protoc_insertion_point(module_scope)
flwr/proto/fleet_pb2.pyi CHANGED
@@ -115,38 +115,23 @@ global___PullMessagesResponse = PullMessagesResponse
115
115
  class PushMessagesRequest(google.protobuf.message.Message):
116
116
  """PushMessages messages"""
117
117
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
118
- class MsgToDescendantMappingEntry(google.protobuf.message.Message):
119
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
120
- KEY_FIELD_NUMBER: builtins.int
121
- VALUE_FIELD_NUMBER: builtins.int
122
- key: typing.Text
123
- @property
124
- def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
125
- def __init__(self,
126
- *,
127
- key: typing.Text = ...,
128
- value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
129
- ) -> None: ...
130
- def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
131
- def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
132
-
133
118
  NODE_FIELD_NUMBER: builtins.int
134
119
  MESSAGES_LIST_FIELD_NUMBER: builtins.int
135
- MSG_TO_DESCENDANT_MAPPING_FIELD_NUMBER: builtins.int
120
+ MESSAGE_OBJECT_TREES_FIELD_NUMBER: builtins.int
136
121
  @property
137
122
  def node(self) -> flwr.proto.node_pb2.Node: ...
138
123
  @property
139
124
  def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
140
125
  @property
141
- def msg_to_descendant_mapping(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
126
+ def message_object_trees(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.ObjectTree]: ...
142
127
  def __init__(self,
143
128
  *,
144
129
  node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
145
130
  messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
146
- msg_to_descendant_mapping: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
131
+ message_object_trees: typing.Optional[typing.Iterable[flwr.proto.message_pb2.ObjectTree]] = ...,
147
132
  ) -> None: ...
148
133
  def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
149
- def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","msg_to_descendant_mapping",b"msg_to_descendant_mapping","node",b"node"]) -> None: ...
134
+ def ClearField(self, field_name: typing_extensions.Literal["message_object_trees",b"message_object_trees","messages_list",b"messages_list","node",b"node"]) -> None: ...
150
135
  global___PushMessagesRequest = PushMessagesRequest
151
136
 
152
137
  class PushMessagesResponse(google.protobuf.message.Message):
@@ -63,6 +63,11 @@ class FleetStub(object):
63
63
  request_serializer=flwr_dot_proto_dot_message__pb2.PullObjectRequest.SerializeToString,
64
64
  response_deserializer=flwr_dot_proto_dot_message__pb2.PullObjectResponse.FromString,
65
65
  )
66
+ self.ConfirmMessageReceived = channel.unary_unary(
67
+ '/flwr.proto.Fleet/ConfirmMessageReceived',
68
+ request_serializer=flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedRequest.SerializeToString,
69
+ response_deserializer=flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedResponse.FromString,
70
+ )
66
71
 
67
72
 
68
73
  class FleetServicer(object):
@@ -131,6 +136,13 @@ class FleetServicer(object):
131
136
  context.set_details('Method not implemented!')
132
137
  raise NotImplementedError('Method not implemented!')
133
138
 
139
+ def ConfirmMessageReceived(self, request, context):
140
+ """Confirm Message Received
141
+ """
142
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
143
+ context.set_details('Method not implemented!')
144
+ raise NotImplementedError('Method not implemented!')
145
+
134
146
 
135
147
  def add_FleetServicer_to_server(servicer, server):
136
148
  rpc_method_handlers = {
@@ -179,6 +191,11 @@ def add_FleetServicer_to_server(servicer, server):
179
191
  request_deserializer=flwr_dot_proto_dot_message__pb2.PullObjectRequest.FromString,
180
192
  response_serializer=flwr_dot_proto_dot_message__pb2.PullObjectResponse.SerializeToString,
181
193
  ),
194
+ 'ConfirmMessageReceived': grpc.unary_unary_rpc_method_handler(
195
+ servicer.ConfirmMessageReceived,
196
+ request_deserializer=flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedRequest.FromString,
197
+ response_serializer=flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedResponse.SerializeToString,
198
+ ),
182
199
  }
183
200
  generic_handler = grpc.method_handlers_generic_handler(
184
201
  'flwr.proto.Fleet', rpc_method_handlers)
@@ -341,3 +358,20 @@ class Fleet(object):
341
358
  flwr_dot_proto_dot_message__pb2.PullObjectResponse.FromString,
342
359
  options, channel_credentials,
343
360
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
361
+
362
+ @staticmethod
363
+ def ConfirmMessageReceived(request,
364
+ target,
365
+ options=(),
366
+ channel_credentials=None,
367
+ call_credentials=None,
368
+ insecure=False,
369
+ compression=None,
370
+ wait_for_ready=None,
371
+ timeout=None,
372
+ metadata=None):
373
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.Fleet/ConfirmMessageReceived',
374
+ flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedRequest.SerializeToString,
375
+ flwr_dot_proto_dot_message__pb2.ConfirmMessageReceivedResponse.FromString,
376
+ options, channel_credentials,
377
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)