diff --git a/launchdarkly-server-sdk/src/data_sources.rs b/launchdarkly-server-sdk/src/data_sources.rs index f924b2c..3efbf72 100644 --- a/launchdarkly-server-sdk/src/data_sources.rs +++ b/launchdarkly-server-sdk/src/data_sources.rs @@ -2,6 +2,62 @@ //! //! This module is experimental and not subject to semantic versioning. Its API //! may change in any release. +//! +//! # Examples +//! +//! Implement a custom synchronizer and add it to a data system. +//! ``` +//! use launchdarkly_server_sdk::data_sources::{ +//! DataSourceBuildContext, FDv2SourceEvent, FDv2SourceEventFuture, FDv2SourceResult, +//! FDv2SynchronizerConfig, Selector, Synchronizer, SynchronizerFactory, +//! }; +//! use launchdarkly_server_sdk::{ConfigBuilder, DataSystemBuildError, DataSystemBuilder}; +//! +//! struct MySynchronizer; +//! +//! impl Synchronizer for MySynchronizer { +//! fn next(&mut self, _selector: Selector) -> FDv2SourceEventFuture<'_> { +//! Box::pin(async { +//! FDv2SourceEvent { +//! result: FDv2SourceResult::Goodbye, +//! fdv1_fallback: None, +//! } +//! }) +//! } +//! +//! fn name(&self) -> &str { +//! "my-synchronizer" +//! } +//! } +//! +//! struct MyFactory; +//! +//! impl SynchronizerFactory for MyFactory { +//! fn create(&self) -> Box { +//! Box::new(MySynchronizer) +//! } +//! } +//! +//! #[derive(Clone)] +//! struct MyConfig; +//! +//! impl FDv2SynchronizerConfig for MyConfig { +//! fn build_synchronizer( +//! &self, +//! _context: &DataSourceBuildContext, +//! ) -> Result, DataSystemBuildError> { +//! Ok(Box::new(MyFactory)) +//! } +//! +//! fn to_owned(&self) -> Box { +//! Box::new(self.clone()) +//! } +//! } +//! +//! let mut data_system = DataSystemBuilder::custom(); +//! data_system.synchronizer(MyConfig); +//! ConfigBuilder::new("sdk-key").data_system(&data_system); +//! ``` pub use crate::data_system_builders::{ DataSourceBuildContext, FDv2InitializerConfig, FDv2SynchronizerConfig, @@ -10,7 +66,7 @@ pub use crate::fdv2::data_system::{InitializerFactory, SynchronizerFactory}; pub use crate::fdv2::model::{ChangeSetKind, Selector}; pub use crate::fdv2::request_headers::RequestHeaders; pub use crate::fdv2::source::{ - ErrorInfo, ErrorKind, FDv1FallbackDirective, FDv2SourceEvent, FDv2SourceResult, Initializer, - Synchronizer, + ErrorInfo, ErrorKind, FDv1FallbackDirective, FDv2SourceEvent, FDv2SourceEventFuture, + FDv2SourceResult, Initializer, Synchronizer, }; pub use crate::stores::change_set::{ChangeSet, ItemChange}; diff --git a/launchdarkly-server-sdk/src/data_system_builders.rs b/launchdarkly-server-sdk/src/data_system_builders.rs index bd7741e..fe0b25f 100644 --- a/launchdarkly-server-sdk/src/data_system_builders.rs +++ b/launchdarkly-server-sdk/src/data_system_builders.rs @@ -103,12 +103,33 @@ impl FDv2StreamingBuilder { } /// Sets the initial reconnect delay for the streaming connection. + /// + /// # Examples + /// ``` + /// # use launchdarkly_server_sdk::FDv2StreamingBuilder; + /// # use launchdarkly_sdk_transport::HyperTransport; + /// # use std::time::Duration; + /// # fn main() { + /// let mut source = FDv2StreamingBuilder::::new(); + /// source.initial_reconnect_delay(Duration::from_secs(10)); + /// # } + /// ``` pub fn initial_reconnect_delay(&mut self, duration: Duration) -> &mut Self { self.initial_reconnect_delay = duration; self } /// Sets the streaming base URL, overriding the configured service endpoints. + /// + /// # Examples + /// ``` + /// # use launchdarkly_server_sdk::FDv2StreamingBuilder; + /// # use launchdarkly_sdk_transport::HyperTransport; + /// # fn main() { + /// let mut source = FDv2StreamingBuilder::::new(); + /// source.base_url("https://stream.example.com"); + /// # } + /// ``` pub fn base_url(&mut self, url: &str) -> &mut Self { self.base_url = Some(url.to_string()); self @@ -179,12 +200,33 @@ impl FDv2PollingBuilder { } /// Sets the interval between polling requests, with an effective minimum of 30 seconds. + /// + /// # Examples + /// ``` + /// # use launchdarkly_server_sdk::FDv2PollingBuilder; + /// # use launchdarkly_sdk_transport::HyperTransport; + /// # use std::time::Duration; + /// # fn main() { + /// let mut source = FDv2PollingBuilder::::new(); + /// source.poll_interval(Duration::from_secs(60)); + /// # } + /// ``` pub fn poll_interval(&mut self, poll_interval: Duration) -> &mut Self { self.poll_interval = poll_interval; self } /// Sets the polling base URL, overriding the configured service endpoints. + /// + /// # Examples + /// ``` + /// # use launchdarkly_server_sdk::FDv2PollingBuilder; + /// # use launchdarkly_sdk_transport::HyperTransport; + /// # fn main() { + /// let mut source = FDv2PollingBuilder::::new(); + /// source.base_url("https://polling.example.com"); + /// # } + /// ``` pub fn base_url(&mut self, url: &str) -> &mut Self { self.base_url = Some(url.to_string()); self @@ -268,6 +310,30 @@ impl Default for FDv2PollingBu } /// Configures the FDv2 data system. +/// +/// # Examples +/// +/// Use the recommended data system. +/// ``` +/// # use launchdarkly_server_sdk::{ConfigBuilder, DataSystemBuilder}; +/// # fn main() { +/// ConfigBuilder::new("sdk-key").data_system(&DataSystemBuilder::default()); +/// # } +/// ``` +/// +/// Assemble a custom data system from individual sources. +/// ``` +/// # use launchdarkly_server_sdk::{ +/// # ConfigBuilder, DataSystemBuilder, FDv2PollingBuilder, FDv2StreamingBuilder, +/// # }; +/// # use launchdarkly_sdk_transport::HyperTransport; +/// # fn main() { +/// let mut data_system = DataSystemBuilder::custom(); +/// data_system.initializer(FDv2PollingBuilder::::new()); +/// data_system.synchronizer(FDv2StreamingBuilder::::new()); +/// ConfigBuilder::new("sdk-key").data_system(&data_system); +/// # } +/// ``` pub struct DataSystemBuilder { initializers: Vec>, synchronizers: Vec>, diff --git a/launchdarkly-server-sdk/src/fdv2/source.rs b/launchdarkly-server-sdk/src/fdv2/source.rs index 770d075..bbe65bd 100644 --- a/launchdarkly-server-sdk/src/fdv2/source.rs +++ b/launchdarkly-server-sdk/src/fdv2/source.rs @@ -1,6 +1,5 @@ use std::time::Duration; -use futures::future::BoxFuture; use rand::Rng; use crate::stores::change_set::ChangeSet; @@ -100,10 +99,14 @@ pub struct FDv2SourceEvent { pub fdv1_fallback: Option, } +/// The future returned by an initializer or synchronizer as it produces an event. +pub type FDv2SourceEventFuture<'a> = + std::pin::Pin + Send + 'a>>; + /// A data source that can obtain an initial payload. pub trait Initializer: Send { /// Runs once to obtain an initial payload. - fn run(&mut self) -> BoxFuture<'_, FDv2SourceEvent>; + fn run(&mut self) -> FDv2SourceEventFuture<'_>; /// The name used in logs. fn name(&self) -> &str; } @@ -111,7 +114,7 @@ pub trait Initializer: Send { /// A data source that keeps flag data up to date. pub trait Synchronizer: Send { /// Fetches the next batch of changes after the given selector. - fn next(&mut self, selector: Selector) -> BoxFuture<'_, FDv2SourceEvent>; + fn next(&mut self, selector: Selector) -> FDv2SourceEventFuture<'_>; /// The name used in logs. fn name(&self) -> &str; }