pub const DATAFORTS_BLOB_BANDWIDTH_CLASS_SUPPORTED: &str =
"dataforts:blob-bandwidth-class-supported";
pub use crate::adapter::net::redex::BandwidthClass;
#[derive(Default)]
pub enum BandwidthClassSupportProbe {
#[default]
AlwaysSupported,
ForceForeground,
Dynamic(Box<dyn Fn() -> bool + Send + Sync>),
}
impl BandwidthClassSupportProbe {
pub fn check(&self) -> bool {
match self {
BandwidthClassSupportProbe::AlwaysSupported => true,
BandwidthClassSupportProbe::ForceForeground => false,
BandwidthClassSupportProbe::Dynamic(f) => f(),
}
}
}
impl std::fmt::Debug for BandwidthClassSupportProbe {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BandwidthClassSupportProbe::AlwaysSupported => {
f.write_str("BandwidthClassSupportProbe::AlwaysSupported")
}
BandwidthClassSupportProbe::ForceForeground => {
f.write_str("BandwidthClassSupportProbe::ForceForeground")
}
BandwidthClassSupportProbe::Dynamic(_) => {
f.write_str("BandwidthClassSupportProbe::Dynamic(..)")
}
}
}
}
pub fn bandwidth_class_downgrade(
class: BandwidthClass,
probe: &BandwidthClassSupportProbe,
) -> BandwidthClass {
if probe.check() {
class
} else {
BandwidthClass::Foreground
}
}
pub fn bandwidth_class_downgrade_with_telemetry(
class: BandwidthClass,
probe: &BandwidthClassSupportProbe,
downgrades_total: &std::sync::atomic::AtomicU64,
realtime_downgrades_total: &std::sync::atomic::AtomicU64,
) -> BandwidthClass {
use std::sync::atomic::Ordering;
if probe.check() {
return class;
}
if class != BandwidthClass::Foreground {
downgrades_total.fetch_add(1, Ordering::Relaxed);
if class == BandwidthClass::Realtime {
realtime_downgrades_total.fetch_add(1, Ordering::Relaxed);
}
}
BandwidthClass::Foreground
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_class_is_foreground() {
assert_eq!(BandwidthClass::default(), BandwidthClass::Foreground);
}
#[test]
fn capability_tag_matches_plan() {
assert_eq!(
DATAFORTS_BLOB_BANDWIDTH_CLASS_SUPPORTED,
"dataforts:blob-bandwidth-class-supported"
);
}
#[test]
fn support_probe_static_variants() {
assert!(BandwidthClassSupportProbe::AlwaysSupported.check());
assert!(!BandwidthClassSupportProbe::ForceForeground.check());
assert!(BandwidthClassSupportProbe::default().check());
}
#[test]
fn support_probe_dynamic_consults_closure() {
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
let flag = Arc::new(AtomicBool::new(false));
let f = flag.clone();
let probe =
BandwidthClassSupportProbe::Dynamic(Box::new(move || f.load(Ordering::Relaxed)));
assert!(!probe.check());
flag.store(true, Ordering::Relaxed);
assert!(probe.check());
}
#[test]
fn downgrade_with_telemetry_bumps_correct_counters() {
use std::sync::atomic::{AtomicU64, Ordering};
let total = AtomicU64::new(0);
let rt = AtomicU64::new(0);
let probe_no = BandwidthClassSupportProbe::ForceForeground;
assert_eq!(
bandwidth_class_downgrade_with_telemetry(
BandwidthClass::Realtime,
&probe_no,
&total,
&rt,
),
BandwidthClass::Foreground
);
assert_eq!(total.load(Ordering::Relaxed), 1);
assert_eq!(rt.load(Ordering::Relaxed), 1);
assert_eq!(
bandwidth_class_downgrade_with_telemetry(
BandwidthClass::Background,
&probe_no,
&total,
&rt,
),
BandwidthClass::Foreground
);
assert_eq!(total.load(Ordering::Relaxed), 2);
assert_eq!(rt.load(Ordering::Relaxed), 1);
assert_eq!(
bandwidth_class_downgrade_with_telemetry(
BandwidthClass::Foreground,
&probe_no,
&total,
&rt,
),
BandwidthClass::Foreground
);
assert_eq!(total.load(Ordering::Relaxed), 2);
assert_eq!(rt.load(Ordering::Relaxed), 1);
let probe_yes = BandwidthClassSupportProbe::AlwaysSupported;
assert_eq!(
bandwidth_class_downgrade_with_telemetry(
BandwidthClass::Realtime,
&probe_yes,
&total,
&rt,
),
BandwidthClass::Realtime
);
assert_eq!(total.load(Ordering::Relaxed), 2);
assert_eq!(rt.load(Ordering::Relaxed), 1);
}
#[test]
fn downgrade_collapses_to_foreground_on_reject() {
let probe_yes = BandwidthClassSupportProbe::AlwaysSupported;
let probe_no = BandwidthClassSupportProbe::ForceForeground;
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Background, &probe_yes),
BandwidthClass::Background
);
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Realtime, &probe_yes),
BandwidthClass::Realtime
);
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Background, &probe_no),
BandwidthClass::Foreground
);
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Realtime, &probe_no),
BandwidthClass::Foreground
);
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Foreground, &probe_yes),
BandwidthClass::Foreground
);
assert_eq!(
bandwidth_class_downgrade(BandwidthClass::Foreground, &probe_no),
BandwidthClass::Foreground
);
}
}