-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: re-work http id list syncing (#62)
* chore: re-work http id list syncing * chore: add more tests around id list syncing * chore: add ability to shutdown id list adapter * chore: locking id lists in spec store * chore: refactor idlist update listener trait * chore: checking id list in evaluator * chore: make id list optional
- Loading branch information
1 parent
6a6e4cd
commit 3e95abb
Showing
12 changed files
with
575 additions
and
275 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use serde::Serialize; | ||
|
||
use crate::{ | ||
id_lists_adapter::{IdListMetadata, IdListUpdate}, | ||
unwrap_or_noop, | ||
}; | ||
use std::collections::HashSet; | ||
|
||
#[derive(Clone, Serialize)] | ||
pub struct IdList { | ||
pub metadata: IdListMetadata, | ||
|
||
#[serde(skip_serializing)] | ||
pub ids: HashSet<String>, | ||
} | ||
|
||
impl IdList { | ||
pub fn new(metadata: IdListMetadata) -> Self { | ||
let mut local_metadata = metadata; | ||
local_metadata.size = 0; | ||
|
||
Self { | ||
metadata: local_metadata, | ||
ids: HashSet::new(), | ||
} | ||
} | ||
|
||
pub fn apply_update(&mut self, update: &IdListUpdate) { | ||
let changed = &update.new_metadata; | ||
let current = &self.metadata; | ||
|
||
if changed.file_id != current.file_id && changed.creation_time >= current.creation_time { | ||
self.reset(); | ||
} | ||
|
||
let changeset_data = unwrap_or_noop!(&update.raw_changeset); | ||
|
||
for change in changeset_data.lines() { | ||
let trimmed = change.trim(); | ||
if trimmed.len() <= 1 { | ||
continue; | ||
} | ||
|
||
let op = change.chars().next(); | ||
let id = &change[1..]; | ||
|
||
match op { | ||
Some('+') => { | ||
self.ids.insert(id.to_string()); | ||
} | ||
Some('-') => { | ||
self.ids.remove(id); | ||
} | ||
_ => continue, | ||
} | ||
} | ||
|
||
self.metadata.size += changeset_data.len() as u64; | ||
} | ||
|
||
pub fn reset(&mut self) { | ||
self.metadata.size = 0; | ||
self.ids.clear(); | ||
} | ||
} |
29 changes: 19 additions & 10 deletions
29
statsig-lib/src/id_lists_adapter/id_lists_adapter_trait.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,45 @@ | ||
use crate::StatsigErr; | ||
use async_trait::async_trait; | ||
use serde::{Deserialize, Serialize}; | ||
use std::collections::{HashMap, HashSet}; | ||
use std::collections::HashMap; | ||
use std::sync::Arc; | ||
use std::time::Duration; | ||
use tokio::runtime::Handle; | ||
|
||
pub type IdListsResponse = HashMap<String, IdListEntry>; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct IdListEntry { | ||
pub struct IdListMetadata { | ||
pub name: String, | ||
pub url: Option<String>, | ||
pub url: String, | ||
|
||
#[serde(rename = "fileID")] | ||
pub file_id: Option<String>, | ||
|
||
pub size: u64, | ||
pub creation_time: i64, | ||
} | ||
|
||
#[serde(skip)] | ||
pub loaded_ids: HashSet<String>, | ||
pub struct IdListUpdate { | ||
pub raw_changeset: Option<String>, | ||
pub new_metadata: IdListMetadata, | ||
} | ||
|
||
#[async_trait] | ||
pub trait IdListsAdapter: Send + Sync { | ||
async fn start(self: Arc<Self>, runtime_handle: &Handle) -> Result<(), StatsigErr>; | ||
async fn start( | ||
self: Arc<Self>, | ||
runtime_handle: &Handle, | ||
listener: Arc<dyn IdListsUpdateListener + Send + Sync>, | ||
) -> Result<(), StatsigErr>; | ||
|
||
async fn shutdown(&self, timeout: Duration) -> Result<(), StatsigErr>; | ||
|
||
async fn sync_id_lists(&self) -> Result<(), StatsigErr>; | ||
} | ||
|
||
fn does_list_contain_id(&self, list_name: &str, id: &str) -> bool; | ||
pub trait IdListsUpdateListener: Send + Sync { | ||
fn get_current_id_list_metadata(&self) -> HashMap<String, IdListMetadata>; | ||
|
||
async fn shutdown(&self, timeout: Duration) -> Result<(), StatsigErr>; | ||
fn did_receive_id_list_updates(&self, updates: HashMap<String, IdListUpdate>); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
pub use id_list::*; | ||
pub use id_lists_adapter_trait::*; | ||
pub use statsig_http_id_lists_adapter::*; | ||
|
||
mod statsig_http_id_lists_adapter; | ||
mod id_list; | ||
mod id_lists_adapter_trait; | ||
mod statsig_http_id_lists_adapter; |
Oops, something went wrong.