flwr-nightly 1.19.0.dev20250511__py3-none-any.whl → 1.19.0.dev20250512__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flwr/common/constant.py +1 -0
- flwr/server/superlink/linkstate/in_memory_linkstate.py +84 -4
- flwr/server/superlink/linkstate/linkstate.py +23 -0
- flwr/server/superlink/linkstate/sqlite_linkstate.py +98 -8
- {flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/METADATA +1 -1
- {flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/RECORD +8 -8
- {flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/entry_points.txt +0 -0
flwr/common/constant.py
CHANGED
@@ -25,12 +25,15 @@ from uuid import UUID, uuid4
|
|
25
25
|
|
26
26
|
from flwr.common import Context, Message, log, now
|
27
27
|
from flwr.common.constant import (
|
28
|
+
HEARTBEAT_MAX_INTERVAL,
|
28
29
|
HEARTBEAT_PATIENCE,
|
29
30
|
MESSAGE_TTL_TOLERANCE,
|
30
31
|
NODE_ID_NUM_BYTES,
|
32
|
+
RUN_FAILURE_DETAILS_NO_HEARTBEAT,
|
31
33
|
RUN_ID_NUM_BYTES,
|
32
34
|
SUPERLINK_NODE_ID,
|
33
35
|
Status,
|
36
|
+
SubStatus,
|
34
37
|
)
|
35
38
|
from flwr.common.record import ConfigRecord
|
36
39
|
from flwr.common.typing import Run, RunStatus, UserConfig
|
@@ -52,8 +55,11 @@ class RunRecord: # pylint: disable=R0902
|
|
52
55
|
"""The record of a specific run, including its status and timestamps."""
|
53
56
|
|
54
57
|
run: Run
|
58
|
+
active_until: float = 0.0
|
59
|
+
heartbeat_interval: float = 0.0
|
55
60
|
logs: list[tuple[float, str]] = field(default_factory=list)
|
56
61
|
log_lock: threading.Lock = field(default_factory=threading.Lock)
|
62
|
+
lock: threading.RLock = field(default_factory=threading.RLock)
|
57
63
|
|
58
64
|
|
59
65
|
class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
@@ -461,8 +467,29 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
461
467
|
with self.lock:
|
462
468
|
return set(self.run_ids.keys())
|
463
469
|
|
470
|
+
def _check_and_tag_inactive_run(self, run_ids: set[int]) -> None:
|
471
|
+
"""Check if any runs are no longer active.
|
472
|
+
|
473
|
+
Marks runs with status 'starting' or 'running' as failed
|
474
|
+
if they have not sent a heartbeat before `active_until`.
|
475
|
+
"""
|
476
|
+
current = now()
|
477
|
+
for record in [self.run_ids[run_id] for run_id in run_ids]:
|
478
|
+
with record.lock:
|
479
|
+
if record.run.status.status in (Status.STARTING, Status.RUNNING):
|
480
|
+
if record.active_until < current.timestamp():
|
481
|
+
record.run.status = RunStatus(
|
482
|
+
status=Status.FINISHED,
|
483
|
+
sub_status=SubStatus.FAILED,
|
484
|
+
details=RUN_FAILURE_DETAILS_NO_HEARTBEAT,
|
485
|
+
)
|
486
|
+
record.run.finished_at = now().isoformat()
|
487
|
+
|
464
488
|
def get_run(self, run_id: int) -> Optional[Run]:
|
465
489
|
"""Retrieve information about the run with the specified `run_id`."""
|
490
|
+
# Check if runs are still active
|
491
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
492
|
+
|
466
493
|
with self.lock:
|
467
494
|
if run_id not in self.run_ids:
|
468
495
|
log(ERROR, "`run_id` is invalid")
|
@@ -471,6 +498,9 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
471
498
|
|
472
499
|
def get_run_status(self, run_ids: set[int]) -> dict[int, RunStatus]:
|
473
500
|
"""Retrieve the statuses for the specified runs."""
|
501
|
+
# Check if runs are still active
|
502
|
+
self._check_and_tag_inactive_run(run_ids=run_ids)
|
503
|
+
|
474
504
|
with self.lock:
|
475
505
|
return {
|
476
506
|
run_id: self.run_ids[run_id].run.status
|
@@ -480,12 +510,16 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
480
510
|
|
481
511
|
def update_run_status(self, run_id: int, new_status: RunStatus) -> bool:
|
482
512
|
"""Update the status of the run with the specified `run_id`."""
|
513
|
+
# Check if runs are still active
|
514
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
515
|
+
|
483
516
|
with self.lock:
|
484
517
|
# Check if the run_id exists
|
485
518
|
if run_id not in self.run_ids:
|
486
519
|
log(ERROR, "`run_id` is invalid")
|
487
520
|
return False
|
488
521
|
|
522
|
+
with self.run_ids[run_id].lock:
|
489
523
|
# Check if the status transition is valid
|
490
524
|
current_status = self.run_ids[run_id].run.status
|
491
525
|
if not is_valid_transition(current_status, new_status):
|
@@ -507,14 +541,23 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
507
541
|
)
|
508
542
|
return False
|
509
543
|
|
510
|
-
#
|
544
|
+
# Initialize heartbeat_interval and active_until
|
545
|
+
# when switching to starting or running
|
546
|
+
current = now()
|
511
547
|
run_record = self.run_ids[run_id]
|
548
|
+
if new_status.status in (Status.STARTING, Status.RUNNING):
|
549
|
+
run_record.heartbeat_interval = HEARTBEAT_MAX_INTERVAL
|
550
|
+
run_record.active_until = (
|
551
|
+
current.timestamp() + run_record.heartbeat_interval
|
552
|
+
)
|
553
|
+
|
554
|
+
# Update the run status
|
512
555
|
if new_status.status == Status.STARTING:
|
513
|
-
run_record.run.starting_at =
|
556
|
+
run_record.run.starting_at = current.isoformat()
|
514
557
|
elif new_status.status == Status.RUNNING:
|
515
|
-
run_record.run.running_at =
|
558
|
+
run_record.run.running_at = current.isoformat()
|
516
559
|
elif new_status.status == Status.FINISHED:
|
517
|
-
run_record.run.finished_at =
|
560
|
+
run_record.run.finished_at = current.isoformat()
|
518
561
|
run_record.run.status = new_status
|
519
562
|
return True
|
520
563
|
|
@@ -558,6 +601,43 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
558
601
|
return True
|
559
602
|
return False
|
560
603
|
|
604
|
+
def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
|
605
|
+
"""Acknowledge a heartbeat received from a ServerApp for a given run.
|
606
|
+
|
607
|
+
A run with status `"running"` is considered alive as long as it sends heartbeats
|
608
|
+
within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
|
609
|
+
HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
|
610
|
+
marked as `"completed:failed"`.
|
611
|
+
"""
|
612
|
+
with self.lock:
|
613
|
+
# Search for the run
|
614
|
+
record = self.run_ids.get(run_id)
|
615
|
+
|
616
|
+
# Check if the run_id exists
|
617
|
+
if record is None:
|
618
|
+
log(ERROR, "`run_id` is invalid")
|
619
|
+
return False
|
620
|
+
|
621
|
+
with record.lock:
|
622
|
+
# Check if runs are still active
|
623
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
624
|
+
|
625
|
+
# Check if the run is of status "running"/"starting"
|
626
|
+
current_status = record.run.status
|
627
|
+
if current_status.status not in (Status.RUNNING, Status.STARTING):
|
628
|
+
log(
|
629
|
+
ERROR,
|
630
|
+
'Cannot acknowledge heartbeat for run with status "%s"',
|
631
|
+
current_status.status,
|
632
|
+
)
|
633
|
+
return False
|
634
|
+
|
635
|
+
# Update the `active_until` and `heartbeat_interval` for the given run
|
636
|
+
current = now().timestamp()
|
637
|
+
record.active_until = current + HEARTBEAT_PATIENCE * heartbeat_interval
|
638
|
+
record.heartbeat_interval = heartbeat_interval
|
639
|
+
return True
|
640
|
+
|
561
641
|
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
562
642
|
"""Get the context for the specified `run_id`."""
|
563
643
|
return self.contexts.get(run_id)
|
@@ -292,6 +292,29 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
292
292
|
True if the heartbeat is successfully acknowledged; otherwise, False.
|
293
293
|
"""
|
294
294
|
|
295
|
+
@abc.abstractmethod
|
296
|
+
def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
|
297
|
+
"""Acknowledge a heartbeat received from a ServerApp for a given run.
|
298
|
+
|
299
|
+
A run with status `"running"` is considered alive as long as it sends heartbeats
|
300
|
+
within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
|
301
|
+
HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
|
302
|
+
marked as `"completed:failed"`.
|
303
|
+
|
304
|
+
Parameters
|
305
|
+
----------
|
306
|
+
run_id : int
|
307
|
+
The `run_id` from which the heartbeat was received.
|
308
|
+
heartbeat_interval : float
|
309
|
+
The interval (in seconds) from the current timestamp within which the next
|
310
|
+
heartbeat from the ServerApp for this run must be received.
|
311
|
+
|
312
|
+
Returns
|
313
|
+
-------
|
314
|
+
is_acknowledged : bool
|
315
|
+
True if the heartbeat is successfully acknowledged; otherwise, False.
|
316
|
+
"""
|
317
|
+
|
295
318
|
@abc.abstractmethod
|
296
319
|
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
297
320
|
"""Get the context for the specified `run_id`.
|
@@ -28,12 +28,15 @@ from uuid import UUID, uuid4
|
|
28
28
|
|
29
29
|
from flwr.common import Context, Message, Metadata, log, now
|
30
30
|
from flwr.common.constant import (
|
31
|
+
HEARTBEAT_MAX_INTERVAL,
|
31
32
|
HEARTBEAT_PATIENCE,
|
32
33
|
MESSAGE_TTL_TOLERANCE,
|
33
34
|
NODE_ID_NUM_BYTES,
|
35
|
+
RUN_FAILURE_DETAILS_NO_HEARTBEAT,
|
34
36
|
RUN_ID_NUM_BYTES,
|
35
37
|
SUPERLINK_NODE_ID,
|
36
38
|
Status,
|
39
|
+
SubStatus,
|
37
40
|
)
|
38
41
|
from flwr.common.message import make_message
|
39
42
|
from flwr.common.record import ConfigRecord
|
@@ -92,6 +95,8 @@ CREATE INDEX IF NOT EXISTS idx_online_until ON node (online_until);
|
|
92
95
|
SQL_CREATE_TABLE_RUN = """
|
93
96
|
CREATE TABLE IF NOT EXISTS run(
|
94
97
|
run_id INTEGER UNIQUE,
|
98
|
+
active_until REAL,
|
99
|
+
heartbeat_interval REAL,
|
95
100
|
fab_id TEXT,
|
96
101
|
fab_version TEXT,
|
97
102
|
fab_hash TEXT,
|
@@ -742,20 +747,21 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
742
747
|
if self.query(query, (sint64_run_id,))[0]["COUNT(*)"] == 0:
|
743
748
|
query = (
|
744
749
|
"INSERT INTO run "
|
745
|
-
"(run_id,
|
746
|
-
"
|
747
|
-
"sub_status, details)
|
750
|
+
"(run_id, active_until, heartbeat_interval, fab_id, fab_version, "
|
751
|
+
"fab_hash, override_config, federation_options, pending_at, "
|
752
|
+
"starting_at, running_at, finished_at, sub_status, details) "
|
753
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
|
748
754
|
)
|
749
755
|
override_config_json = json.dumps(override_config)
|
750
756
|
data = [
|
751
757
|
sint64_run_id,
|
758
|
+
0, # The `active_until` is not used until the run is started
|
759
|
+
0, # This `heartbeat_interval` is not used until the run is started
|
752
760
|
fab_id,
|
753
761
|
fab_version,
|
754
762
|
fab_hash,
|
755
763
|
override_config_json,
|
756
764
|
configrecord_to_bytes(federation_options),
|
757
|
-
]
|
758
|
-
data += [
|
759
765
|
now().isoformat(),
|
760
766
|
"",
|
761
767
|
"",
|
@@ -796,8 +802,33 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
796
802
|
rows = self.query(query)
|
797
803
|
return {convert_sint64_to_uint64(row["run_id"]) for row in rows}
|
798
804
|
|
805
|
+
def _check_and_tag_inactive_run(self, run_ids: set[int]) -> None:
|
806
|
+
"""Check if any runs are no longer active.
|
807
|
+
|
808
|
+
Marks runs with status 'starting' or 'running' as failed
|
809
|
+
if they have not sent a heartbeat before `active_until`.
|
810
|
+
"""
|
811
|
+
sint_run_ids = [convert_uint64_to_sint64(run_id) for run_id in run_ids]
|
812
|
+
query = "UPDATE run SET finished_at = ?, sub_status = ?, details = ? "
|
813
|
+
query += "WHERE starting_at != '' AND finished_at = '' AND active_until < ?"
|
814
|
+
query += f" AND run_id IN ({','.join(['?'] * len(run_ids))});"
|
815
|
+
current = now()
|
816
|
+
self.query(
|
817
|
+
query,
|
818
|
+
(
|
819
|
+
current.isoformat(),
|
820
|
+
SubStatus.FAILED,
|
821
|
+
RUN_FAILURE_DETAILS_NO_HEARTBEAT,
|
822
|
+
current.timestamp(),
|
823
|
+
*sint_run_ids,
|
824
|
+
),
|
825
|
+
)
|
826
|
+
|
799
827
|
def get_run(self, run_id: int) -> Optional[Run]:
|
800
828
|
"""Retrieve information about the run with the specified `run_id`."""
|
829
|
+
# Check if runs are still active
|
830
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
831
|
+
|
801
832
|
# Convert the uint64 value to sint64 for SQLite
|
802
833
|
sint64_run_id = convert_uint64_to_sint64(run_id)
|
803
834
|
query = "SELECT * FROM run WHERE run_id = ?;"
|
@@ -825,6 +856,9 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
825
856
|
|
826
857
|
def get_run_status(self, run_ids: set[int]) -> dict[int, RunStatus]:
|
827
858
|
"""Retrieve the statuses for the specified runs."""
|
859
|
+
# Check if runs are still active
|
860
|
+
self._check_and_tag_inactive_run(run_ids=run_ids)
|
861
|
+
|
828
862
|
# Convert the uint64 value to sint64 for SQLite
|
829
863
|
sint64_run_ids = (convert_uint64_to_sint64(run_id) for run_id in set(run_ids))
|
830
864
|
query = f"SELECT * FROM run WHERE run_id IN ({','.join(['?'] * len(run_ids))});"
|
@@ -842,6 +876,9 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
842
876
|
|
843
877
|
def update_run_status(self, run_id: int, new_status: RunStatus) -> bool:
|
844
878
|
"""Update the status of the run with the specified `run_id`."""
|
879
|
+
# Check if runs are still active
|
880
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
881
|
+
|
845
882
|
# Convert the uint64 value to sint64 for SQLite
|
846
883
|
sint64_run_id = convert_uint64_to_sint64(run_id)
|
847
884
|
query = "SELECT * FROM run WHERE run_id = ?;"
|
@@ -879,9 +916,22 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
879
916
|
return False
|
880
917
|
|
881
918
|
# Update the status
|
882
|
-
query = "UPDATE run SET %s= ?, sub_status = ?, details =
|
919
|
+
query = "UPDATE run SET %s= ?, sub_status = ?, details = ?, "
|
920
|
+
query += "active_until = ?, heartbeat_interval = ? "
|
883
921
|
query += "WHERE run_id = ?;"
|
884
922
|
|
923
|
+
# Prepare data for query
|
924
|
+
# Initialize heartbeat_interval and active_until
|
925
|
+
# when switching to starting or running
|
926
|
+
current = now()
|
927
|
+
if new_status.status in (Status.STARTING, Status.RUNNING):
|
928
|
+
heartbeat_interval = HEARTBEAT_MAX_INTERVAL
|
929
|
+
active_until = current.timestamp() + heartbeat_interval
|
930
|
+
else:
|
931
|
+
heartbeat_interval = 0
|
932
|
+
active_until = 0
|
933
|
+
|
934
|
+
# Determine the timestamp field based on the new status
|
885
935
|
timestamp_fld = ""
|
886
936
|
if new_status.status == Status.STARTING:
|
887
937
|
timestamp_fld = "starting_at"
|
@@ -891,10 +941,12 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
891
941
|
timestamp_fld = "finished_at"
|
892
942
|
|
893
943
|
data = (
|
894
|
-
|
944
|
+
current.isoformat(),
|
895
945
|
new_status.sub_status,
|
896
946
|
new_status.details,
|
897
|
-
|
947
|
+
active_until,
|
948
|
+
heartbeat_interval,
|
949
|
+
convert_uint64_to_sint64(run_id),
|
898
950
|
)
|
899
951
|
self.query(query % timestamp_fld, data)
|
900
952
|
return True
|
@@ -957,6 +1009,44 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
957
1009
|
)
|
958
1010
|
return True
|
959
1011
|
|
1012
|
+
def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
|
1013
|
+
"""Acknowledge a heartbeat received from a ServerApp for a given run.
|
1014
|
+
|
1015
|
+
A run with status `"running"` is considered alive as long as it sends heartbeats
|
1016
|
+
within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
|
1017
|
+
HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
|
1018
|
+
marked as `"completed:failed"`.
|
1019
|
+
"""
|
1020
|
+
# Check if runs are still active
|
1021
|
+
self._check_and_tag_inactive_run(run_ids={run_id})
|
1022
|
+
|
1023
|
+
# Search for the run
|
1024
|
+
sint_run_id = convert_uint64_to_sint64(run_id)
|
1025
|
+
query = "SELECT * FROM run WHERE run_id = ?;"
|
1026
|
+
rows = self.query(query, (sint_run_id,))
|
1027
|
+
|
1028
|
+
if not rows:
|
1029
|
+
log(ERROR, "`run_id` is invalid")
|
1030
|
+
return False
|
1031
|
+
|
1032
|
+
# Check if the run is of status "running"/"starting"
|
1033
|
+
row = rows[0]
|
1034
|
+
status = determine_run_status(row)
|
1035
|
+
if status not in (Status.RUNNING, Status.STARTING):
|
1036
|
+
log(
|
1037
|
+
ERROR,
|
1038
|
+
'Cannot acknowledge heartbeat for run with status "%s"',
|
1039
|
+
status,
|
1040
|
+
)
|
1041
|
+
return False
|
1042
|
+
|
1043
|
+
# Update the `active_until` and `heartbeat_interval` for the given run
|
1044
|
+
active_until = now().timestamp() + HEARTBEAT_PATIENCE * heartbeat_interval
|
1045
|
+
query = "UPDATE run SET active_until = ?, heartbeat_interval = ? "
|
1046
|
+
query += "WHERE run_id = ?"
|
1047
|
+
self.query(query, (active_until, heartbeat_interval, sint_run_id))
|
1048
|
+
return True
|
1049
|
+
|
960
1050
|
def get_serverapp_context(self, run_id: int) -> Optional[Context]:
|
961
1051
|
"""Get the context for the specified `run_id`."""
|
962
1052
|
# Retrieve context if any
|
{flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: flwr-nightly
|
3
|
-
Version: 1.19.0.
|
3
|
+
Version: 1.19.0.dev20250512
|
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
|
{flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/RECORD
RENAMED
@@ -115,7 +115,7 @@ flwr/common/args.py,sha256=-aX_jVnSaDrJR2KZ8Wq0Y3dQHII4R4MJtJOIXzVUA0c,5417
|
|
115
115
|
flwr/common/auth_plugin/__init__.py,sha256=m271m9YjK2QfKDOuIIhcTvGmv1GWh1PL97QB05NTSHs,887
|
116
116
|
flwr/common/auth_plugin/auth_plugin.py,sha256=GaXw4IiU2DkVNkp5S9ue821sbkU9zWSu6HSVZetEdjs,3938
|
117
117
|
flwr/common/config.py,sha256=glcZDjco-amw1YfQcYTFJ4S1pt9APoexT-mf1QscuHs,13960
|
118
|
-
flwr/common/constant.py,sha256=
|
118
|
+
flwr/common/constant.py,sha256=Q8N-up1TvL_vllV_QA8mQlKjqVJ6Kdoze3iem6nSF9E,7375
|
119
119
|
flwr/common/context.py,sha256=Be8obQR_OvEDy1OmshuUKxGRQ7Qx89mf5F4xlhkR10s,2407
|
120
120
|
flwr/common/date.py,sha256=1ZT2cRSpC2DJqprOVTLXYCR_O2_OZR0zXO_brJ3LqWc,1554
|
121
121
|
flwr/common/differential_privacy.py,sha256=FdlpdpPl_H_2HJa8CQM1iCUGBBQ5Dc8CzxmHERM-EoE,6148
|
@@ -293,10 +293,10 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=-wDHjgAy5mrfEgXj0GxkJI
|
|
293
293
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=Hx9hxL7lju1_VJoAwkhBOGerZ3628u0P1zgkPhGWRPY,7154
|
294
294
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=m7WUiHRl-jTqzjH3cqNCj3RXe3ohT6V6I0JIR6zWZj8,12780
|
295
295
|
flwr/server/superlink/linkstate/__init__.py,sha256=OtsgvDTnZLU3k0sUbkHbqoVwW6ql2FDmb6uT6DbNkZo,1064
|
296
|
-
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=
|
297
|
-
flwr/server/superlink/linkstate/linkstate.py,sha256=
|
296
|
+
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=vvoOWjYlmOlbakH7AzpMh0jB70Qxx7UTlAGqjcA8ctM,25926
|
297
|
+
flwr/server/superlink/linkstate/linkstate.py,sha256=j6nW351t07VrBhFqjO34z8tf2PuKOE9aCX9SqpW96pQ,13100
|
298
298
|
flwr/server/superlink/linkstate/linkstate_factory.py,sha256=8RlosqSpKOoD_vhUUQPY0jtE3A84GeF96Z7sWNkRRcA,2069
|
299
|
-
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=
|
299
|
+
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=E43YO88vdnG9GW6Rwh9Fb7oWGgEABS9RXDRg3OR3T4Q,43573
|
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
|
@@ -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.
|
337
|
-
flwr_nightly-1.19.0.
|
338
|
-
flwr_nightly-1.19.0.
|
339
|
-
flwr_nightly-1.19.0.
|
336
|
+
flwr_nightly-1.19.0.dev20250512.dist-info/METADATA,sha256=Sc_-zl1MmehvY10Jr4aE7QBaKxEY_ZXfqbsGdnCAEAc,15910
|
337
|
+
flwr_nightly-1.19.0.dev20250512.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
338
|
+
flwr_nightly-1.19.0.dev20250512.dist-info/entry_points.txt,sha256=2-1L-GNKhwGw2_7_RoH55vHw2SIHjdAQy3HAVAWl9PY,374
|
339
|
+
flwr_nightly-1.19.0.dev20250512.dist-info/RECORD,,
|
{flwr_nightly-1.19.0.dev20250511.dist-info → flwr_nightly-1.19.0.dev20250512.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|