1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
//! Thesis provides the `Experiment` struct, which represents an experiment to //! run which compares the return values of multiple methods for accomplishing //! the same task. //! //! Let's imagine that we already have a function called `load_data_from_db`, //! which loads some data from a database. We want to refactor this to instead //! load the same data from redis. We write a new function called //! `load_data_from_redis` to accomplish the same task, but with redis instead of //! a DB. We want to use the redis version on only a very small percentage of //! traffic, say 0.5% of incoming requests, and we want to log it out if the //! redis data doesn't match the DB data, treating the DB data as accurate and //! discarding the redis data if so. Here's how we can use an `Experiment` to do //! this. //! //! ``` //! use thesis::{Experiment, rollout::Percent}; //! //! async fn load_data_from_db(id: i32) -> i32 { id } //! async fn load_data_from_redis(id: i32) -> i32 { id } //! //! # tokio_test::block_on(async { //! let id = 4; //! let result = Experiment::new("redis migration") //! .control(load_data_from_db(id)) //! .experimental(load_data_from_redis(id)) //! .rollout_strategy(Percent::new(0.5)) //! .on_mismatch(|mismatch| { //! eprintln!( //! "DB & Redis data differ - db={}, redis={}", //! mismatch.control, //! mismatch.experimental, //! ); //! //! // the `control` value here comes from the DB //! mismatch.control //! }) //! .run() //! .await; //! //! assert_eq!(result, 4); //! # }); //! ``` pub mod experiment; pub mod rollout; pub mod mismatch; pub use experiment::Experiment; pub use rollout::{RolloutDecision, RolloutStrategy}; pub use mismatch::{MismatchHandler, Mismatch};