flip.flower.progress
Flower round-progress emission — the Flower twin of the NVFLARE round relay.
Emits the typed round facts (FLLogEvent) that back the hub’s round-aware
activity feed. Facts only: the hub composes display text at serve time, so
wording changes never require rebuilding FL images.
Every helper is best-effort — a telemetry failure is logged and must never
break the strategy loop (matching flip.flower.metrics). Only the fl-server
should import from this module; fl-clients hold no hub credentials.
flip.flower.strategy.FlipFedAvg wires these into the FedAvg hooks; app
templates should subclass it rather than calling these directly.
Classes
Per-run reply bookkeeping: who was dispatched, who answered, who fell out. |
Functions
|
Name the single client that was dispatched a task but never returned a healthy reply. |
|
Report that the server dispatched the global model for a round. |
|
Report one received client reply; returns whether the reply was healthy. |
|
Report that a round's replies were aggregated. |
Module Contents
- flip.flower.progress.resolve_absent_site(dispatched_nodes: set[int], responded_nodes: set[int], site_by_node: dict[int, str]) str | None
Name the single client that was dispatched a task but never returned a healthy reply.
Flower stamps a placeholder
src_node_idon the error reply it synthesises for an unreachable node, so a dead client cannot be recognised from its own reply. It can be recognised by elimination: the strategy knows which nodes it dispatched to, which answered, and (from earlier healthy replies) each node’s site name.Returns None when the absence is ambiguous (several nodes silent at once) or the absent node never identified itself — guessing would put a real trust’s name on another trust’s failure.
- Parameters:
dispatched_nodes – Node ids the round’s tasks were sent to.
responded_nodes – Node ids that returned a healthy reply this round.
site_by_node – Node id to site name, learned from healthy replies.
- Returns:
The absent client’s site name, or None when unidentifiable.
- Return type:
str | None
- class flip.flower.progress.RoundTelemetry
Per-run reply bookkeeping: who was dispatched, who answered, who fell out.
Extracted from
FlipFedAvg(which needsflwrto import) so CI can pin the two invariants that make crashed-client attribution safe:absent clients are named only from sites learned off healthy replies (accumulated across the whole run) — never guessed from the placeholder identity on a synthesised error reply;
each phase keeps its own dispatch roster — a train strategy’s evaluate arm may sample a different cohort, and resolving evaluate absences against the train roster would put one trust’s name on another trust’s failure.
- site_by_node: dict[int, str]
- _dispatched_by_phase: dict[Phase, set[int]]
- record_dispatch(phase: Phase, node_ids: set[int]) None
Record the node ids a phase’s tasks were just sent to (replaces the phase’s previous roster — each round samples afresh).
- Parameters:
phase – Which strategy phase dispatched.
node_ids – The
dst_node_idof every dispatched message.
- dispatched_count(phase: Phase) int | None
How many clients the phase’s current round was dispatched to.
- Parameters:
phase – Which strategy phase to count.
- Returns:
The roster size, or None when the phase never dispatched.
- Return type:
int | None
- forward_replies(replies: list[flwr.common.message.Message], phase: Phase, server_round: int, model_id: str, flip: flip.FLIP) int
Forward every reply’s metrics, exception and round event to the hub.
Learns each healthy reply’s site, then names the one client the phase dispatched to that never returned a healthy reply (see
resolve_absent_site) so its error is attributed to the right trust. fl-clients never reach the Central Hub directly — every forward happens here, server-side.- Parameters:
replies – The round’s reply Messages.
phase – The strategy phase these replies belong to.
server_round – Flower’s 1-based round number.
model_id – The FLIP model ID for the run.
flip – The FLIP instance used to reach the Central Hub.
- Returns:
How many replies were healthy.
- Return type:
int
- flip.flower.progress.report_round_started(flip: flip.FLIP, model_id: str, server_round: int, total_rounds: int | None) None
Report that the server dispatched the global model for a round.
- Parameters:
flip – The FLIP instance used to reach the Central Hub.
model_id – The FLIP model ID for the run.
server_round – Flower’s 1-based round number (already the wire contract).
total_rounds – The run’s round total, when known.
- flip.flower.progress.report_client_result(msg: flwr.common.message.Message, server_round: int, model_id: str, flip: flip.FLIP) bool
Report one received client reply; returns whether the reply was healthy.
The boolean feeds the strategy’s returned-count, so a telemetry failure on a healthy reply still counts it as returned.
- Parameters:
msg – A Flower reply Message from a client.
server_round – Flower’s 1-based round number.
model_id – The FLIP model ID for the run.
flip – The FLIP instance used to reach the Central Hub.
- Returns:
True when the reply is healthy (no error), regardless of whether the telemetry post succeeded.
- Return type:
bool
- flip.flower.progress.report_round_aggregated(flip: flip.FLIP, model_id: str, server_round: int, returned: int | None, expected: int | None) None
Report that a round’s replies were aggregated.
- Parameters:
flip – The FLIP instance used to reach the Central Hub.
model_id – The FLIP model ID for the run.
server_round – Flower’s 1-based round number.
returned – Healthy replies received this round, when known.
expected – Clients the round was dispatched to, when known.