diff options
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | examples/async_source/main.rs | 75 |
2 files changed, 79 insertions, 0 deletions
@@ -40,3 +40,7 @@ json5_rs = { version = "0.3", optional = true, package = "json5" } serde_derive = "1.0.8" float-cmp = "0.8" chrono = { version = "0.4", features = ["serde"] } +tokio = { version = "1", features = ["rt-multi-thread", "macros", "fs", "io-util", "time"]} +warp = "0.3.1" +futures = "0.3.15" +reqwest = "0.11.3" diff --git a/examples/async_source/main.rs b/examples/async_source/main.rs new file mode 100644 index 0000000..979f829 --- /dev/null +++ b/examples/async_source/main.rs @@ -0,0 +1,75 @@ +use std::{collections::HashMap, error::Error}; + +use config::{builder::AsyncState, AsyncSource, ConfigBuilder, ConfigError, FileFormat}; + +use async_trait::async_trait; +use futures::{select, FutureExt}; +use warp::Filter; + +// Example below presents sample configuration server and client. +// +// Server serves simple configuration on HTTP endpoint. +// Client consumes it using custom HTTP AsyncSource built on top of reqwest. + +#[tokio::main] +async fn main() -> Result<(), Box<dyn Error>> { + select! { + r = run_server().fuse() => r, + r = run_client().fuse() => r + } +} + +async fn run_server() -> Result<(), Box<dyn Error>> { + let service = warp::path("configuration").map(|| r#"{ "value" : 123 }"#); + + println!("Running server on localhost:5001"); + + warp::serve(service).bind(([127, 0, 0, 1], 5001)).await; + + Ok(()) +} + +async fn run_client() -> Result<(), Box<dyn Error>> { + // Good enough for an example to allow server to start + tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; + + let config = ConfigBuilder::<AsyncState>::default() + .add_async_source(HttpSource { + uri: "http://localhost:5001/configuration".into(), + format: FileFormat::Json, + }) + .build() + .await?; + + println!("Config value is {}", config.get::<String>("value")?); + + Ok(()) +} + +// Actual implementation of AsyncSource can be found below + +#[derive(Debug)] +struct HttpSource { + uri: String, + format: FileFormat, +} + +impl HttpSource { + async fn call(&self) -> Result<String, reqwest::Error> { + reqwest::get(&self.uri).await?.text().await + } +} + +#[async_trait] +impl AsyncSource for HttpSource { + async fn collect(&self) -> Result<HashMap<String, config::Value>, ConfigError> { + self.call() + .await + .map_err(|e| ConfigError::Foreign(Box::new(e))) + .and_then(|text| { + self.format + .parse(Some(&self.uri), &text) + .map_err(|e| ConfigError::Foreign(e)) + }) + } +} |