nvflare.fuel.f3.streaming.transfer_outcome module

Normalized aggregate terminal outcome for DownloadService transactions.

TransactionDoneStatus.FINISHED only means a transaction reached its receiver count: a receiver that FAILED still counts toward num_receivers, and the transaction_done_cb carries no per-receiver outcomes. The Client API payload lifecycle (docs/design/client_api_execution_modes.md, “Terminal transfer outcome”) requires the distinction between “every expected receiver succeeded” and “the transaction merely terminated”. This module provides that distinction additively: TransactionDoneStatus values and the transaction_done_cb contract are unchanged.

Receiver truth wins over known termination mechanics: a transaction whose expected receivers all succeeded resolves COMPLETED even if it was terminated by routine cleanup (delete_transaction) or a late timeout. Everything else fails closed — including a FINISHED transaction with no objects (a mid-assembly race must not certify success) and any unknown/future termination status (validated before receiver truth is considered).

Outcome status values reuse the TransferProgressState terminal vocabulary (completed / failed / aborted) rather than introducing another status set.

Semantics with the full payload layer (receiver-confirmed completion, per-receiver budgets, awaitable transfer facade): - per-receiver statuses are receiver-confirmed where the receiver supports it (a served

EOF is provisional until the receiver confirms its finalization succeeded); legacy receivers remain producer-served — both skews and the runtime kill-switch degrade to producer-served semantics (download_service.py, receiver-confirmed completion);

  • expected receiver identities and per-receiver acquire/idle budgets bound the outcome’s resolution time (a stalled or never-pulling receiver is finalized FAILED without waiting the whole-transaction TTL); min_receivers surfaces the optional k-of-N quorum via quorum_met while completed stays the strict all-receivers certificate;

  • the outcome covers the refs present at termination; adding objects to a transaction after receivers already finished the earlier ones is not supported.

class DownloadStatus[source]

Bases: object

Constants for object download status.

FAILED = 'failed'
SUCCESS = 'success'
class RefOutcome(ref_id: str, receiver_statuses: Mapping[str, str])[source]

Bases: object

Per-object terminal outcome.

receiver_statuses maps receiver FQCN to a DownloadStatus value (success / failed) – receiver-confirmed where the receiver supports it, producer-served for legacy peers or when the receiver-confirm kill-switch is off, and budget-FAILED for receivers that exhausted their acquire/idle budget. It is deep-frozen at construction (a MappingProxyType over a private copy): the same instance is recorded in the service outcome table and handed to outcome_cb consumers, so a callback must not be able to mutate the recorded per-receiver truth. If outcomes ever cross a process boundary, the serializer must materialize it (dict(…)).

receiver_statuses: Mapping[str, str]
ref_id: str
class TransactionDoneStatus[source]

Bases: object

Constants for transaction completion status.

DELETED = 'deleted'
FINISHED = 'finished'
TIMEOUT = 'timeout'
class TransferOutcome(tx_id: str, status: str, reason: str, done_status: str, num_receivers: int, refs: Tuple[RefOutcome, ...], timestamp: float, min_receivers: int | None = None, receiver_ids: Tuple[str, ...] | None = None)[source]

Bases: object

Aggregate terminal outcome of one download transaction.

status is a TransferProgressState terminal value: COMPLETED only when every expected receiver of every ref succeeded; FAILED on any receiver failure, missing receiver, no objects, timeout, or unknown receiver count; ABORTED on explicit deletion before full success. done_status carries the raw TransactionDoneStatus for callers that need the untranslated termination cause.

property completed: bool
done_status: str
expired(now: float, ttl: float) bool[source]
min_receivers: int | None = None
num_receivers: int
property quorum_met: bool

True if every ref reached at least min_receivers confirmed successes.

The k-of-N surface for fan-out workflows (min_responses-style policies): completed stays the strict all-receivers certificate; a workflow that accepts partial fan-out checks quorum_met (or thresholds refs itself). Falls back to completed when no min_receivers was declared; fails closed with no refs.

reason: str
receiver_ids: Tuple[str, ...] | None = None
refs: Tuple[RefOutcome, ...]
status: str
timestamp: float
tx_id: str
class TransferOutcomeReason[source]

Bases: object

Constants explaining how a TransferOutcome status was determined.

ALL_RECEIVERS_SUCCEEDED = 'all_receivers_succeeded'
COMPUTATION_FAILED = 'computation_failed'
DELETED = 'deleted'
NO_OBJECTS = 'no_objects'
RECEIVER_FAILED = 'receiver_failed'
TIMEOUT = 'timeout'
UNKNOWN_DONE_STATUS = 'unknown_done_status'
UNKNOWN_RECEIVER_COUNT = 'unknown_receiver_count'
compute_transfer_outcome(tx_id: str, done_status: str, num_receivers: int, refs: Sequence[RefOutcome], timestamp: float | None = None, min_receivers: int | None = None, receiver_ids=None) TransferOutcome[source]

Compute the aggregate terminal outcome for a terminated transaction.

The termination status is validated first: an unknown/future done_status fails closed even if every receiver succeeded. For known statuses, receiver truth wins: if every expected receiver of every ref succeeded, the outcome is COMPLETED regardless of how the transaction terminated (FINISHED, or routine cleanup via DELETED, or a late TIMEOUT). Otherwise the outcome fails closed based on the termination cause.

Parameters:
  • tx_id – ID of the terminated transaction.

  • done_status – the TransactionDoneStatus value the transaction terminated with.

  • num_receivers – the transaction’s expected receiver count (0 means unknown).

  • refs – per-ref receiver statuses snapshotted at termination.

  • timestamp – termination time; defaults to now.

Returns: a TransferOutcome.

terminal_state_for_done_status(done_status: str) str | None[source]

Map a TransactionDoneStatus value to the TransferProgressState terminal vocabulary.