relay_server/utils/
pick.rs1#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
3pub enum PickResult {
4 #[default]
6 Keep,
7 Discard,
9}
10
11#[allow(
16 dead_code,
17 reason = "A utility which is frequently used and removed again"
18)]
19pub fn is_rolled_out(id: u64, rate: f32) -> PickResult {
20 match ((id % 100000) as f32 / 100000.0f32) < rate {
21 true => PickResult::Keep,
22 false => PickResult::Discard,
23 }
24}
25
26impl PickResult {
27 #[cfg(feature = "processing")]
29 pub fn is_keep(self) -> bool {
30 matches!(self, PickResult::Keep)
31 }
32}
33
34#[cfg(feature = "processing")]
38pub fn sample(rate: f32) -> PickResult {
39 match (rate >= 1.0) || (rate > 0.0 && rand::random::<f32>() < rate) {
40 true => PickResult::Keep,
41 false => PickResult::Discard,
42 }
43}
44
45#[cfg(test)]
46mod test {
47 use super::*;
48
49 #[test]
50 fn test_rollout() {
51 assert_eq!(is_rolled_out(1, 0.0), PickResult::Discard);
52 assert_eq!(is_rolled_out(1, 0.0001), PickResult::Keep); assert_eq!(is_rolled_out(1, 0.1), PickResult::Keep);
54 assert_eq!(is_rolled_out(1, 0.9), PickResult::Keep);
55 assert_eq!(is_rolled_out(1, 1.0), PickResult::Keep);
56
57 assert_eq!(is_rolled_out(0, 0.0), PickResult::Discard);
58 assert_eq!(is_rolled_out(0, 1.0), PickResult::Keep);
59 assert_eq!(is_rolled_out(100000, 0.0), PickResult::Discard);
60 assert_eq!(is_rolled_out(100000, 1.0), PickResult::Keep);
61 assert_eq!(is_rolled_out(100001, 0.0), PickResult::Discard);
62 assert_eq!(is_rolled_out(100001, 1.0), PickResult::Keep);
63
64 assert_eq!(is_rolled_out(42, -100.0), PickResult::Discard);
65 assert_eq!(is_rolled_out(42, 100.0), PickResult::Keep);
66 }
67
68 #[cfg(feature = "processing")]
69 #[test]
70 fn test_sample() {
71 assert_eq!(sample(1.0), PickResult::Keep);
72 assert_eq!(sample(0.0), PickResult::Discard);
73
74 let mut r: i64 = 0;
75 for _ in 0..10000 {
76 if sample(0.5).is_keep() {
77 r += 1;
78 } else {
79 r -= 1;
80 }
81 }
82 assert!(r.abs() < 500);
83 }
84}