1
- /// Returns `true` if `id` is rolled out with a rollout rate `rate`.
1
+ /// Result of a sampling operation, whether to keep or discard something.
2
+ #[ derive( Copy , Clone , Debug , Default , PartialEq , Eq ) ]
3
+ pub enum PickResult {
4
+ /// The item should be kept.
5
+ #[ default]
6
+ Keep ,
7
+ /// The item should be dropped.
8
+ Discard ,
9
+ }
10
+
11
+ /// Returns [`PickResult::Keep`] if `id` is rolled out with a rollout rate `rate`.
2
12
///
3
13
/// Deterministically makes a rollout decision for an id, usually organization id,
4
14
/// and rate.
5
- pub fn is_rolled_out ( id : u64 , rate : f32 ) -> bool {
6
- ( ( id % 100000 ) as f32 / 100000.0f32 ) < rate
15
+ pub fn is_rolled_out ( id : u64 , rate : f32 ) -> PickResult {
16
+ match ( ( id % 100000 ) as f32 / 100000.0f32 ) < rate {
17
+ true => PickResult :: Keep ,
18
+ false => PickResult :: Discard ,
19
+ }
7
20
}
8
21
9
- /// Returns `true` if the current item should be sampled.
22
+ impl PickResult {
23
+ /// Returns `true` if the sampling result is [`PickResult::Keep`].
24
+ pub fn is_keep ( self ) -> bool {
25
+ matches ! ( self , PickResult :: Keep )
26
+ }
27
+
28
+ /// Returns `true` if the sampling result is [`PickResult::Discard`].
29
+ pub fn is_discard ( self ) -> bool {
30
+ !self . is_keep ( )
31
+ }
32
+ }
33
+
34
+ /// Returns [`PickResult::Keep`] if the current item should be sampled.
10
35
///
11
36
/// The passed `rate` is expected to be `0 <= rate <= 1`.
12
- pub fn sample ( rate : f32 ) -> bool {
13
- ( rate >= 1.0 ) || ( rate > 0.0 && rand:: random :: < f32 > ( ) < rate)
37
+ pub fn sample ( rate : f32 ) -> PickResult {
38
+ match ( rate >= 1.0 ) || ( rate > 0.0 && rand:: random :: < f32 > ( ) < rate) {
39
+ true => PickResult :: Keep ,
40
+ false => PickResult :: Discard ,
41
+ }
14
42
}
15
43
16
44
#[ cfg( test) ]
@@ -19,31 +47,31 @@ mod test {
19
47
20
48
#[ test]
21
49
fn test_rollout ( ) {
22
- assert ! ( ! is_rolled_out( 1 , 0.0 ) ) ;
23
- assert ! ( is_rolled_out( 1 , 0.0001 ) ) ; // Id 1 should always be rolled out
24
- assert ! ( is_rolled_out( 1 , 0.1 ) ) ;
25
- assert ! ( is_rolled_out( 1 , 0.9 ) ) ;
26
- assert ! ( is_rolled_out( 1 , 1.0 ) ) ;
27
-
28
- assert ! ( ! is_rolled_out( 0 , 0.0 ) ) ;
29
- assert ! ( is_rolled_out( 0 , 1.0 ) ) ;
30
- assert ! ( ! is_rolled_out( 100000 , 0.0 ) ) ;
31
- assert ! ( is_rolled_out( 100000 , 1.0 ) ) ;
32
- assert ! ( ! is_rolled_out( 100001 , 0.0 ) ) ;
33
- assert ! ( is_rolled_out( 100001 , 1.0 ) ) ;
34
-
35
- assert ! ( ! is_rolled_out( 42 , -100.0 ) ) ;
36
- assert ! ( is_rolled_out( 42 , 100.0 ) ) ;
50
+ assert_eq ! ( is_rolled_out( 1 , 0.0 ) , PickResult :: Discard ) ;
51
+ assert_eq ! ( is_rolled_out( 1 , 0.0001 ) , PickResult :: Keep ) ; // Id 1 should always be rolled out
52
+ assert_eq ! ( is_rolled_out( 1 , 0.1 ) , PickResult :: Keep ) ;
53
+ assert_eq ! ( is_rolled_out( 1 , 0.9 ) , PickResult :: Keep ) ;
54
+ assert_eq ! ( is_rolled_out( 1 , 1.0 ) , PickResult :: Keep ) ;
55
+
56
+ assert_eq ! ( is_rolled_out( 0 , 0.0 ) , PickResult :: Discard ) ;
57
+ assert_eq ! ( is_rolled_out( 0 , 1.0 ) , PickResult :: Keep ) ;
58
+ assert_eq ! ( is_rolled_out( 100000 , 0.0 ) , PickResult :: Discard ) ;
59
+ assert_eq ! ( is_rolled_out( 100000 , 1.0 ) , PickResult :: Keep ) ;
60
+ assert_eq ! ( is_rolled_out( 100001 , 0.0 ) , PickResult :: Discard ) ;
61
+ assert_eq ! ( is_rolled_out( 100001 , 1.0 ) , PickResult :: Keep ) ;
62
+
63
+ assert_eq ! ( is_rolled_out( 42 , -100.0 ) , PickResult :: Discard ) ;
64
+ assert_eq ! ( is_rolled_out( 42 , 100.0 ) , PickResult :: Keep ) ;
37
65
}
38
66
39
67
#[ test]
40
68
fn test_sample ( ) {
41
- assert ! ( sample( 1.0 ) ) ;
42
- assert ! ( ! sample( 0.0 ) ) ;
69
+ assert_eq ! ( sample( 1.0 ) , PickResult :: Keep ) ;
70
+ assert_eq ! ( sample( 0.0 ) , PickResult :: Discard ) ;
43
71
44
72
let mut r: i64 = 0 ;
45
73
for _ in 0 ..10000 {
46
- if sample ( 0.5 ) {
74
+ if sample ( 0.5 ) . is_keep ( ) {
47
75
r += 1 ;
48
76
} else {
49
77
r -= 1 ;
0 commit comments