Skip to content

Commit e77d783

Browse files
author
sebo
committed
feat: user key not change for multiple percetage roullout evaluation
1 parent 55ec570 commit e77d783

File tree

4 files changed

+39
-22
lines changed

4 files changed

+39
-22
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ headers = "0.3"
3232
http = "0.2"
3333
lazy_static = "1.4"
3434
minstant = "0.1"
35-
parking_lot = "0.12"
35+
parking_lot = { version = "0.12", features = ["serde"] }
3636
rand = "0.8"
3737
regex = "1.5.6"
3838
semver = "1.0"

src/evalutate.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
88
use serde_json::Value;
99
use sha1::Digest;
1010
use std::string::String;
11-
use std::time::{SystemTime, UNIX_EPOCH};
1211
use std::{collections::HashMap, str::FromStr};
1312
use tracing::{info, warn};
1413

@@ -67,16 +66,15 @@ pub struct Distribution {
6766
impl Distribution {
6867
pub fn find_index(&self, eval_param: &EvalParams) -> Result<usize, FPError> {
6968
let user = eval_param.user;
69+
7070
let hash_key = match &self.bucket_by {
71-
None => match &user.key {
72-
Some(key) => key.to_owned(),
73-
None => temporal_rollout_key(),
74-
},
71+
None => user.key(),
7572
Some(custom_key) => match user.get(custom_key) {
7673
None if eval_param.is_detail => {
7774
return Err(FPError::EvalDetailError(format!(
7875
"User with key:{:?} does not have attribute named: [{}]",
79-
user.key, custom_key
76+
user.key(),
77+
custom_key
8078
)));
8179
}
8280
None => return Err(FPError::EvalError),
@@ -108,14 +106,6 @@ impl Distribution {
108106
}
109107
}
110108

111-
fn temporal_rollout_key() -> String {
112-
let start = SystemTime::now();
113-
let since_the_epoch = start
114-
.duration_since(UNIX_EPOCH)
115-
.expect("Time went before epoch");
116-
format!("{}", since_the_epoch.as_micros())
117-
}
118-
119109
fn salt_hash(key: &str, salt: &str, bucket_size: u64) -> u32 {
120110
let size = 4;
121111
let mut hasher = sha1::Sha1::new();

src/user.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
use std::collections::HashMap;
2-
1+
use parking_lot::RwLock;
32
use serde::{Deserialize, Serialize};
3+
use std::collections::HashMap;
4+
use std::time::{SystemTime, UNIX_EPOCH};
45

5-
#[derive(Default, Debug, Deserialize, Serialize)]
6+
#[derive(Default, Debug, Serialize, Deserialize)]
67
pub struct FPUser {
7-
pub key: Option<String>,
8+
key: RwLock<Option<String>>,
89
attrs: HashMap<String, String>,
910
}
1011

1112
impl FPUser {
1213
pub fn new() -> Self {
13-
let key = None;
14+
let key = RwLock::new(None);
1415
FPUser {
1516
key,
1617
..Default::default()
1718
}
1819
}
1920

2021
pub fn stable_rollout(mut self, key: String) -> Self {
21-
self.key = Some(key);
22+
self.key = RwLock::new(Some(key));
2223
self
2324
}
2425

@@ -39,6 +40,30 @@ impl FPUser {
3940
pub fn get_all(&self) -> &HashMap<String, String> {
4041
&self.attrs
4142
}
43+
44+
pub fn key(&self) -> String {
45+
let key = {
46+
let key = self.key.read();
47+
(*key).clone()
48+
};
49+
match key {
50+
Some(key) => key,
51+
None => {
52+
let mut guard = self.key.write();
53+
let key = generate_key();
54+
*guard = Some(key.clone());
55+
key
56+
}
57+
}
58+
}
59+
}
60+
61+
fn generate_key() -> String {
62+
let start = SystemTime::now();
63+
let since_the_epoch = start
64+
.duration_since(UNIX_EPOCH)
65+
.expect("Time went before epoch");
66+
format!("{}", since_the_epoch.as_micros())
4267
}
4368

4469
#[cfg(test)]
@@ -48,10 +73,11 @@ mod tests {
4873
#[test]
4974
fn test_user_with() {
5075
let u = FPUser::new().with("name", "bob").with("phone", "123");
51-
assert_eq!(u.key, None);
5276
assert_eq!(u.get("name"), Some(&"bob".to_owned()));
5377
assert_eq!(u.get("phone"), Some(&"123".to_owned()));
5478
assert_eq!(u.get_all().len(), 2);
79+
// test generated key not change
80+
assert_eq!(u.key(), u.key());
5581
}
5682

5783
#[test]

0 commit comments

Comments
 (0)