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 pub fn is_keep(self) -> bool {
29 matches!(self, PickResult::Keep)
30 }
31
32 #[cfg(feature = "processing")]
34 pub fn is_discard(self) -> bool {
35 !self.is_keep()
36 }
37}
38
39pub fn sample(rate: f32) -> PickResult {
43 match (rate >= 1.0) || (rate > 0.0 && rand::random::<f32>() < rate) {
44 true => PickResult::Keep,
45 false => PickResult::Discard,
46 }
47}
48
49#[cfg(test)]
50mod test {
51 use super::*;
52
53 #[test]
54 fn test_rollout() {
55 assert_eq!(is_rolled_out(1, 0.0), PickResult::Discard);
56 assert_eq!(is_rolled_out(1, 0.0001), PickResult::Keep); assert_eq!(is_rolled_out(1, 0.1), PickResult::Keep);
58 assert_eq!(is_rolled_out(1, 0.9), PickResult::Keep);
59 assert_eq!(is_rolled_out(1, 1.0), PickResult::Keep);
60
61 assert_eq!(is_rolled_out(0, 0.0), PickResult::Discard);
62 assert_eq!(is_rolled_out(0, 1.0), PickResult::Keep);
63 assert_eq!(is_rolled_out(100000, 0.0), PickResult::Discard);
64 assert_eq!(is_rolled_out(100000, 1.0), PickResult::Keep);
65 assert_eq!(is_rolled_out(100001, 0.0), PickResult::Discard);
66 assert_eq!(is_rolled_out(100001, 1.0), PickResult::Keep);
67
68 assert_eq!(is_rolled_out(42, -100.0), PickResult::Discard);
69 assert_eq!(is_rolled_out(42, 100.0), PickResult::Keep);
70 }
71
72 #[test]
73 fn test_sample() {
74 assert_eq!(sample(1.0), PickResult::Keep);
75 assert_eq!(sample(0.0), PickResult::Discard);
76
77 let mut r: i64 = 0;
78 for _ in 0..10000 {
79 if sample(0.5).is_keep() {
80 r += 1;
81 } else {
82 r -= 1;
83 }
84 }
85 assert!(r.abs() < 500);
86 }
87}