Query Reliability

Distributed queries need two separate reliability decisions:

  • which replica should answer each requested range
  • whether the combined response is complete or partial

Scepter keeps those decisions explicit.

Replica Resolution

ReplicaResolver groups candidates by target range, removes unavailable replicas, chooses the strongest primary, and keeps ordered fallbacks.

use scepter::{
    ReplicaCandidate, ReplicaQuality, ReplicaResolver, ReplicaState,
};

let resolved = ReplicaResolver::with_max_fallbacks(1).resolve(vec![
    ReplicaCandidate::new(
        b"a".to_vec()..b"m".to_vec(),
        "leaf-a",
        ReplicaQuality::new(0, 60, 60, 60, true, ReplicaState::Available),
    ),
    ReplicaCandidate::new(
        b"a".to_vec()..b"m".to_vec(),
        "leaf-b",
        ReplicaQuality::new(0, 60, 55, 60, true, ReplicaState::Recovering),
    ),
]);

assert_eq!(resolved[0].primary, "leaf-a");
assert_eq!(resolved[0].fallbacks, vec!["leaf-b"]);

Query Health

QueryHealth records child completion and degradation metadata. Issue-only responses can be complete by count while still partial by quality.

use scepter::{IssueKind, QueryHealth};

let mut health = QueryHealth::with_expected_children(2);
health.record_completed();
health.push_issue("zone-west", IssueKind::PrunedZone, "soft deadline elapsed");

assert!(health.is_partial());
assert_eq!(health.completeness(), 0.5);