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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
// Copyright 2020 Cognite AS //! [Unleash](https://unleash.github.io) is a feature flag API system. This is a //! client for it to facilitate using the API to control features in Rust programs. //! //! ## Client overview //! //! The client is written using async. Any std compatible async runtime should be //! compatible. Examples with async-std and tokio are in the examples/ in the source //! tree. //! //! To use it in a sync program, run an async executor and `block_on()` the relevant //! calls. As the client specification requires sending background metrics to the API, //! you will need to arrange to call the `poll_for_updates` method from a thread as //! demonstrated in `examples/threads.rs`. //! //! The unleash defined strategies are included, to support custom strategies //! use the `ClientBuilder` and call the `strategy` method to register your custom //! strategy memoization function. //! //! ```no_run //! use std::collections::hash_map::HashMap; //! use std::collections::hash_set::HashSet; //! use std::hash::BuildHasher; //! use std::time::Duration; //! //! use async_std::task; //! use enum_map::Enum; //! use futures_timer::Delay; //! use serde::{Deserialize, Serialize}; //! //! use unleash_api_client::client; //! use unleash_api_client::config::EnvironmentConfig; //! use unleash_api_client::context::Context; //! use unleash_api_client::strategy; //! //! fn _reversed_uids<S: BuildHasher>( //! parameters: Option<HashMap<String, String, S>>, //! ) -> strategy::Evaluate { //! let mut uids: HashSet<String> = HashSet::new(); //! if let Some(parameters) = parameters { //! if let Some(uids_list) = parameters.get("userIds") { //! for uid in uids_list.split(',') { //! uids.insert(uid.chars().rev().collect()); //! } //! } //! } //! Box::new(move |context: &Context| -> bool { //! context //! .user_id //! .as_ref() //! .map(|uid| uids.contains(uid)) //! .unwrap_or(false) //! }) //! } //! //! #[allow(non_camel_case_types)] //! #[derive(Debug, Deserialize, Serialize, Enum, Clone)] //! enum UserFeatures { //! default //! } //! //! fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { //! let _ = simple_logger::init(); //! task::block_on(async { //! let config = EnvironmentConfig::from_env()?; //! let client = client::ClientBuilder::default() //! .strategy("reversed", Box::new(&_reversed_uids)) //! .into_client::<http_client::native::NativeClient, UserFeatures>( //! &config.api_url, //! &config.app_name, //! &config.instance_id, //! config.secret, //! )?; //! client.register().await?; //! futures::future::join(client.poll_for_updates(), async { //! // Ensure we have initial load of features completed //! Delay::new(Duration::from_millis(500)).await; //! assert_eq!(true, client.is_enabled(UserFeatures::default, None, false)); //! // ... serve more requests //! client.stop_poll().await; //! }).await; //! Ok(()) //! }) //! } //! ``` #![warn(clippy::all)] pub mod api; pub mod client; pub mod config; pub mod context; pub mod http; pub mod strategy; // Exports for ergonomical use pub use crate::client::{Client, ClientBuilder}; pub use crate::config::EnvironmentConfig; pub use crate::context::Context; pub use crate::strategy::Evaluate; /// For the complete minimalist /// /// ```no_run /// use enum_map::Enum; /// use serde::{Deserialize, Serialize}; /// use unleash_api_client::prelude::*; /// let config = EnvironmentConfig::from_env()?; /// /// #[allow(non_camel_case_types)] /// #[derive(Debug, Deserialize, Serialize, Enum, Clone)] /// enum UserFeatures { /// feature /// } /// /// let client = ClientBuilder::default() /// .into_client::<http_client::native::NativeClient, UserFeatures>( /// &config.api_url, /// &config.app_name, /// &config.instance_id, /// config.secret, /// )?; /// # Ok::<(), Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>(()) /// ``` pub mod prelude { pub use crate::client::ClientBuilder; pub use crate::config::EnvironmentConfig; }