Skip to content

Commit

Permalink
Merge pull request #22 from flipt-io/remove-box-dynamic
Browse files Browse the repository at this point in the history
feat: remove box dynamic dispatch and use generic trait bounds
  • Loading branch information
yquansah authored Dec 5, 2023
2 parents d6e669e + 2c12b72 commit a3438c9
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 422 deletions.
5 changes: 3 additions & 2 deletions flipt-engine/examples/evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use fliptengine::{self, evaluator, parser};
use std::collections::HashMap;

fn main() {
let evaluator = evaluator::Evaluator::new(
let evaluator = evaluator::Evaluator::new_snapshot_evaluator(
vec!["default".into()],
Box::new(parser::HTTPParser::new("http://localhost:8080")),
parser::HTTPParser::new("http://localhost:8080"),
);

let eng = fliptengine::Engine::new(evaluator.unwrap(), Default::default());
let mut context: HashMap<String, String> = HashMap::new();
context.insert("fizz".into(), "buzz".into());
Expand Down
119 changes: 68 additions & 51 deletions flipt-engine/src/evaluator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ const DEFAULT_PERCENT: f32 = 100.0;
const DEFAULT_TOTAL_BUCKET_NUMBER: u32 = 1000;
const DEFAULT_PERCENT_MULTIPIER: f32 = DEFAULT_TOTAL_BUCKET_NUMBER as f32 / DEFAULT_PERCENT;

pub struct Evaluator {
pub struct Evaluator<P, S>
where
P: Parser + Send,
S: Store + Send,
{
namespaces: Vec<String>,
parser: Box<dyn Parser + Send>,
snapshot: Box<dyn Store + Send>,
parser: P,
store: S,
mtx: Arc<RwLock<i32>>,
}

Expand Down Expand Up @@ -101,33 +105,46 @@ type VariantEvaluationResult<T> = std::result::Result<T, Whatever>;

type BooleanEvaluationResult<T> = std::result::Result<T, Whatever>;

impl Evaluator {
pub fn new(
namespaces: Vec<String>,
parser: Box<dyn Parser + Sync + Send>,
) -> Result<Self, Whatever> {
let snap = Snapshot::build(&namespaces, &*parser)?;
impl<P> Evaluator<P, Snapshot>
where
P: Parser + Send,
{
pub fn new_snapshot_evaluator(namespaces: Vec<String>, parser: P) -> Result<Self, Whatever> {
let snap = Snapshot::build(&namespaces, &parser)?;
Evaluator::new(namespaces, parser, snap)
}

pub fn replace_snapshot(&mut self) {
let snap = Snapshot::build(&self.namespaces, &self.parser);
self.replace_store(snap.unwrap());
}
}

impl<P, S> Evaluator<P, S>
where
P: Parser + Send,
S: Store + Send,
{
pub fn new(namespaces: Vec<String>, parser: P, store_impl: S) -> Result<Self, Whatever> {
Ok(Self {
namespaces,
parser,
snapshot: Box::new(snap),
store: store_impl,
mtx: Arc::new(RwLock::new(0)),
})
}

pub fn replace_snapshot(&mut self) {
pub fn replace_store(&mut self, store_impl: S) {
let _w_lock = self.mtx.write().unwrap();
let snap = Snapshot::build(&self.namespaces, self.parser.as_ref());
self.snapshot = Box::new(snap.unwrap());
self.store = store_impl;
}

pub fn variant(
&self,
evaluation_request: &EvaluationRequest,
) -> VariantEvaluationResult<VariantEvaluationResponse> {
let _r_lock = self.mtx.read().unwrap();
let flag = match self.snapshot.get_flag(
let flag = match self.store.get_flag(
&evaluation_request.namespace_key,
&evaluation_request.flag_key,
) {
Expand All @@ -152,7 +169,7 @@ impl Evaluator {
evaluation_request: &EvaluationRequest,
) -> BooleanEvaluationResult<BooleanEvaluationResponse> {
let _r_lock = self.mtx.read().unwrap();
let flag = match self.snapshot.get_flag(
let flag = match self.store.get_flag(
&evaluation_request.namespace_key,
&evaluation_request.flag_key,
) {
Expand Down Expand Up @@ -180,7 +197,7 @@ impl Evaluator {

for request in requests {
let flag = match self
.snapshot
.store
.get_flag(&request.namespace_key, &request.flag_key)
{
Some(f) => f,
Expand Down Expand Up @@ -240,7 +257,7 @@ impl Evaluator {
return Ok(variant_evaluation_response);
}

let evaluation_rules = match self.snapshot.get_evaluation_rules(
let evaluation_rules = match self.store.get_evaluation_rules(
&evaluation_request.namespace_key,
&evaluation_request.flag_key,
) {
Expand Down Expand Up @@ -291,7 +308,7 @@ impl Evaluator {
variant_evaluation_response.segment_keys = segment_keys;

let distributions = match self
.snapshot
.store
.get_evaluation_distributions(&evaluation_request.namespace_key, &rule.id)
{
Some(evaluation_distributions) => evaluation_distributions,
Expand Down Expand Up @@ -373,7 +390,7 @@ impl Evaluator {
let now = SystemTime::now();
let mut last_rank = 0;

let evaluation_rollouts = match self.snapshot.get_evaluation_rollouts(
let evaluation_rollouts = match self.store.get_evaluation_rollouts(
&evaluation_request.namespace_key,
&evaluation_request.flag_key,
) {
Expand Down Expand Up @@ -991,8 +1008,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1083,8 +1100,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1202,8 +1219,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1303,8 +1320,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1409,8 +1426,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1542,8 +1559,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1626,8 +1643,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1723,8 +1740,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1814,8 +1831,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -1932,8 +1949,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2032,8 +2049,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2129,8 +2146,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2261,8 +2278,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2344,8 +2361,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2466,8 +2483,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down Expand Up @@ -2578,8 +2595,8 @@ mod tests {

let evaluator = &Evaluator {
namespaces: vec!["default".into()],
parser: Box::new(test_parser),
snapshot: Box::new(mock_store),
parser: test_parser,
store: mock_store,
mtx: Arc::new(RwLock::new(0)),
};

Expand Down
10 changes: 6 additions & 4 deletions flipt-engine/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use libc::c_void;
use parser::HTTPParser;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use snafu::{prelude::*, Whatever};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::sync::{Arc, Mutex};
use store::Snapshot;

pub mod evaluator;
mod models;
Expand Down Expand Up @@ -81,11 +83,11 @@ impl Default for EngineOpts {

pub struct Engine {
pub opts: EngineOpts,
pub evaluator: Arc<Mutex<evaluator::Evaluator>>,
pub evaluator: Arc<Mutex<evaluator::Evaluator<HTTPParser, Snapshot>>>,
}

impl Engine {
pub fn new(evaluator: evaluator::Evaluator, opts: EngineOpts) -> Self {
pub fn new(evaluator: evaluator::Evaluator<HTTPParser, Snapshot>, opts: EngineOpts) -> Self {
let mut engine = Self {
opts,
evaluator: Arc::new(Mutex::new(evaluator)),
Expand Down Expand Up @@ -177,8 +179,8 @@ pub unsafe extern "C" fn initialize_engine(
.to_owned()
.unwrap_or("http://localhost:8080".into());

let parser = Box::new(parser::HTTPParser::new(&http_url));
let evaluator = evaluator::Evaluator::new(namespaces_vec, parser);
let parser = parser::HTTPParser::new(&http_url);
let evaluator = evaluator::Evaluator::new_snapshot_evaluator(namespaces_vec, parser);

Box::into_raw(Box::new(Engine::new(evaluator.unwrap(), engine_opts))) as *mut c_void
}
Expand Down
5 changes: 4 additions & 1 deletion flipt-engine/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ struct Namespace {
}

impl Snapshot {
pub fn build(namespaces: &Vec<String>, parser: &dyn Parser) -> Result<Snapshot, Whatever> {
pub fn build<P>(namespaces: &Vec<String>, parser: &P) -> Result<Snapshot, Whatever>
where
P: Parser + Send,
{
let mut ns: HashMap<String, Namespace> = HashMap::new();

for n in namespaces {
Expand Down
Loading

0 comments on commit a3438c9

Please sign in to comment.