dynomite-engine 0.0.2

Embeddable Dynamo-style distributed replication engine: token-ring partitioning, gossip cluster, hinted handoff, anti-entropy, RediSearch FT.* surface.
Documentation
//! Public embedding API for the Dynomite engine.
//!
//! `dynomite::embed` is the surface an embedding program uses to
//! construct, run, observe, and shut down a Dynomite engine
//! in-process. The same surface drives the [`dynomited`] binary;
//! the binary is a thin wrapper around this module rather than a
//! parallel code path.
//!
//! # Two-tier API
//!
//! 1. [`Server::builder`] returns a [`ServerBuilder`] - a typed,
//!    fluent, validated-at-`build` builder that mirrors every
//!    YAML-visible [`crate::conf::ConfPool`] field plus typed
//!    setters for hook traits with no YAML form.
//! 2. [`Server::start`] returns immediately; the tokio runtime
//!    owns the background work. The caller drives the running
//!    server through a [`ServerHandle`].
//!
//! # Hooks
//!
//! Five public traits expose every cross-cutting concern an
//! embedder may want to override:
//!
//! * [`hooks::Datastore`] - backing store (Redis / Memcache /
//!   custom).
//! * [`hooks::SeedsProvider`] - service discovery integration.
//! * [`hooks::CryptoProvider`] - HSM / KMS integration.
//! * [`hooks::MetricsSink`] - exporter integration.
//! * [`crate::io::reactor::Transport`] - already exposed by
//!   `io::reactor`; re-exported here as
//!   [`Transport`](crate::embed::Transport) for discoverability.
//!
//! Every trait has at least one default implementation shipped
//! in-crate, and the crate-root re-exports below mean a typical
//! embedder writes
//! `use dynomite::embed::{Server, ServerBuilder, ServerHandle};`
//! without reaching into the submodules.
//!
//! # Examples
//!
//! ```no_run
//! use dynomite::embed::{Server, ServerBuilder};
//! use dynomite::conf::DataStore;
//! # tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async {
//! let server: Server = ServerBuilder::new("dyn_o_mite")
//!     .listen("127.0.0.1:0".parse().unwrap())
//!     .dyn_listen("127.0.0.1:0".parse().unwrap())
//!     .data_store(DataStore::Redis)
//!     .servers(vec![dynomite::conf::ConfServer::parse("127.0.0.1:6379:1").unwrap()])
//!     .tokens_str("0")
//!     .build()
//!     .unwrap();
//! let handle = server.start().await.unwrap();
//! assert_eq!(handle.peers().len(), 1);
//! handle.shutdown().await.unwrap();
//! # });
//! ```
//!
//! [`dynomited`]: ../../dynomited/index.html

pub mod builder;
pub mod error;
pub mod events;
pub mod extension;
pub mod hooks;
pub mod server;
pub mod snapshots;

pub use crate::io::reactor::{ConnRole, TcpTransport, Transport};

pub use self::builder::ServerBuilder;
pub use self::error::EmbedError;
pub use self::events::{
    CloseReason, ConnId, ConnRoleTag, EventStream, PeerDownReason, PeerId, ServerEvent,
};
pub use self::extension::{CommandExtension, HsetOutcome};
pub use self::hooks::{
    BoxFuture, CryptoProvider, CryptoProviderError, Datastore, DatastoreError, DnsSeedsProvider,
    FloridaSeedsProvider, LoggingMetricsSink, MemcacheDatastore, MemoryDatastore, MetricsError,
    MetricsSink, Protocol, RedisDatastore, RustCryptoProvider, SeedsProvider, SimpleSeedsProvider,
};
pub use self::server::{Server, ServerHandle};
pub use self::snapshots::{DatacenterSnapshot, PeerSnapshot, RackSnapshot, RingSnapshot};

impl Server {
    /// Convenience entry point.
    ///
    /// # Examples
    ///
    /// ```
    /// use dynomite::embed::Server;
    /// let _b = Server::builder("dyn_o_mite");
    /// ```
    #[must_use]
    pub fn builder(pool_name: impl Into<String>) -> ServerBuilder {
        ServerBuilder::new(pool_name)
    }

    /// One-shot "validate, build, and start" helper.
    ///
    /// Equivalent to calling `builder.build()?.start().await`. The
    /// chained-call form remains available for embedders that
    /// want to inspect the [`Server`] before spawning tasks; this
    /// helper exists because most embedders only ever build then
    /// immediately start.
    ///
    /// # Errors
    ///
    /// Returns the same [`EmbedError`] variants that
    /// [`ServerBuilder::build`] and [`Server::start`] surface.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use dynomite::embed::{Server, ServerBuilder};
    /// use dynomite::conf::DataStore;
    /// # tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async {
    /// let builder = ServerBuilder::new("dyn_o_mite")
    ///     .listen("127.0.0.1:0".parse().unwrap())
    ///     .dyn_listen("127.0.0.1:0".parse().unwrap())
    ///     .data_store(DataStore::Redis)
    ///     .servers(vec![dynomite::conf::ConfServer::parse("127.0.0.1:6379:1").unwrap()])
    ///     .tokens_str("0");
    /// let handle = Server::start_with(builder).await.unwrap();
    /// handle.shutdown().await.unwrap();
    /// # });
    /// ```
    pub async fn start_with(builder: ServerBuilder) -> Result<ServerHandle, EmbedError> {
        builder.build()?.start().await
    }
}