Skip to main content

rings_core/measure/
quality.rs

1use super::Measure;
2use super::MeasureCounter;
3use crate::dht::Did;
4
5/// Local peer-quality class derived from recent reliability evidence.
6pub type PeerQuality = rings_measure::ReliabilityClass;
7
8/// Failure limits used to classify recent local reliability evidence.
9pub type PeerQualityThresholds = rings_measure::ReliabilityThresholds;
10
11/// Recent local logical transport outcomes.
12pub type PeerQualityEvidence = rings_measure::ReliabilityEvidence;
13
14/// Projected local measurement for one Rings peer.
15///
16/// Reliability remains advisory DHT ordering evidence. Credit is a separate
17/// local resource-priority relation and is never a Chord membership proof.
18#[derive(Debug, Clone, Copy, PartialEq)]
19pub struct PeerMeasurement {
20    /// Peer DID described by this projection.
21    pub did: Did,
22    /// Recent logical transport evidence.
23    pub evidence: PeerQualityEvidence,
24    /// Persistent useful-byte totals when the implementation supports credits.
25    pub credit: Option<rings_measure::CreditRecord>,
26    /// Local aMule-compatible resource-priority multiplier.
27    pub credit_score: rings_measure::CreditScore,
28    /// Advisory reliability class derived at query time.
29    pub quality: PeerQuality,
30}
31
32/// One bounded page of local peer measurements in DID order.
33#[derive(Debug, Clone, PartialEq, Default)]
34pub struct PeerMeasurementPage {
35    /// Successfully projected measurements in the scanned page.
36    pub measurements: Vec<PeerMeasurement>,
37    /// Exclusive DID cursor for the next page, absent at the end.
38    pub next_cursor: Option<Did>,
39}
40
41impl PeerMeasurement {
42    /// Convert a pure generic ledger projection into the Rings DTO boundary.
43    pub fn from_projected(projected: rings_measure::PeerMeasurement<Did>) -> Self {
44        Self {
45            did: projected.peer,
46            evidence: projected.reliability,
47            credit: Some(projected.credit),
48            credit_score: projected.credit_score,
49            quality: projected.reliability_class,
50        }
51    }
52}
53
54/// Read policy-free evidence from a counter-only compatibility implementation.
55///
56/// Classification remains the caller's responsibility; this avoids encoding
57/// the absence of a policy as sentinel failure thresholds.
58pub async fn peer_evidence_from_counters<M>(measure: &M, did: Did) -> Option<PeerQualityEvidence>
59where M: Measure + ?Sized {
60    let evidence = PeerQualityEvidence {
61        connected: measure.get_count(did, MeasureCounter::Connect).await,
62        disconnected: measure.get_count(did, MeasureCounter::Disconnected).await,
63        sent: measure.get_count(did, MeasureCounter::Sent).await,
64        failed_to_send: measure.get_count(did, MeasureCounter::FailedToSend).await,
65        received: measure.get_count(did, MeasureCounter::Received).await,
66        failed_to_receive: measure
67            .get_count(did, MeasureCounter::FailedToReceive)
68            .await,
69    };
70    (!evidence.is_unobserved()).then_some(evidence)
71}
72
73/// Stably order DHT candidates by advisory reliability.
74///
75/// Invariant: the output is a stable permutation of the input candidate set.
76pub fn order_peers_by_quality(
77    candidates: impl IntoIterator<Item = (Did, PeerQuality)>,
78) -> Vec<Did> {
79    rings_measure::order_peers_by_reliability(candidates)
80}