Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions launchdarkly-server-sdk/src/data_sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Synchronizer> {
//! Box::new(MySynchronizer)
//! }
//! }
//!
//! #[derive(Clone)]
//! struct MyConfig;
//!
//! impl FDv2SynchronizerConfig for MyConfig {
//! fn build_synchronizer(
//! &self,
//! _context: &DataSourceBuildContext,
//! ) -> Result<Box<dyn SynchronizerFactory>, DataSystemBuildError> {
//! Ok(Box::new(MyFactory))
//! }
//!
//! fn to_owned(&self) -> Box<dyn FDv2SynchronizerConfig> {
//! 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,
Expand All @@ -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};
66 changes: 66 additions & 0 deletions launchdarkly-server-sdk/src/data_system_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,33 @@ impl<T: HttpTransport + Clone + Send + Sync + 'static> FDv2StreamingBuilder<T> {
}

/// 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::<HyperTransport>::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::<HyperTransport>::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
Expand Down Expand Up @@ -179,12 +200,33 @@ impl<T: HttpTransport + Clone + Send + Sync + 'static> FDv2PollingBuilder<T> {
}

/// 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::<HyperTransport>::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::<HyperTransport>::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
Expand Down Expand Up @@ -268,6 +310,30 @@ impl<T: HttpTransport + Clone + Send + Sync + 'static> 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::<HyperTransport>::new());
/// data_system.synchronizer(FDv2StreamingBuilder::<HyperTransport>::new());
/// ConfigBuilder::new("sdk-key").data_system(&data_system);
/// # }
/// ```
pub struct DataSystemBuilder {
initializers: Vec<Box<dyn FDv2InitializerConfig>>,
synchronizers: Vec<Box<dyn FDv2SynchronizerConfig>>,
Expand Down
9 changes: 6 additions & 3 deletions launchdarkly-server-sdk/src/fdv2/source.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::time::Duration;

use futures::future::BoxFuture;
use rand::Rng;

use crate::stores::change_set::ChangeSet;
Expand Down Expand Up @@ -100,18 +99,22 @@ pub struct FDv2SourceEvent {
pub fdv1_fallback: Option<FDv1FallbackDirective>,
}

/// The future returned by an initializer or synchronizer as it produces an event.
pub type FDv2SourceEventFuture<'a> =
std::pin::Pin<Box<dyn std::future::Future<Output = FDv2SourceEvent> + 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;
}

/// 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;
}
Expand Down
Loading