Skip to main content

boatramp_node/
backends.rs

1//! Backend-selection enums for a node's blob + KV stores (node-library N2b).
2//!
3//! These are the domain types the store-construction assembly dispatches on. They
4//! live here (not the binary) so the assembly can move into the library; the
5//! `clap::ValueEnum` derive is behind the optional `clap` feature so the CLI
6//! binary uses them directly in its args, while a non-CLI embedder never pulls
7//! clap. (`build_kv`/`build_blobs` join this module as they migrate off the
8//! binary's `ServeArgs`.)
9
10use std::path::Path;
11use std::sync::Arc;
12
13use boatramp_core::kv::{KvStore, MemoryKv};
14
15use crate::error::Result;
16
17/// Blob (file-content) backend.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
20pub enum BlobBackend {
21    /// Local filesystem (`<data-dir>/blobs`).
22    Fs,
23    /// S3-compatible object store (requires `--features s3`).
24    S3,
25    /// Google Cloud Storage (requires `--features gcs`).
26    Gcs,
27    /// Azure Blob Storage (requires `--features azure`).
28    Azure,
29}
30
31/// Metadata (manifest + pointer) backend.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
34pub enum KvBackend {
35    /// Transactional LSM over object storage; durable local default
36    /// (`<data-dir>/kv-slate`). Requires `--features slatedb` (on by default).
37    Slatedb,
38    /// In-memory (ephemeral; lost on restart).
39    Memory,
40    /// Cloudflare KV over REST (requires `--features cloudflare-kv`).
41    Cloudflare,
42}
43
44/// Flush interval for the control-plane SlateDB store: tiny, so a control-plane
45/// write is durable almost immediately (correctness over throughput).
46pub const CONTROL_PLANE_FLUSH: std::time::Duration = std::time::Duration::from_millis(5);
47
48/// Build the metadata KV store for the selected [`KvBackend`].
49pub async fn build_kv(kv: KvBackend, data_dir: &Path) -> Result<Arc<dyn KvStore>> {
50    match kv {
51        KvBackend::Slatedb => build_slatedb_kv(data_dir).await,
52        KvBackend::Memory => Ok(Arc::new(MemoryKv::new())),
53        KvBackend::Cloudflare => build_cloudflare_kv(),
54    }
55}
56
57#[cfg(feature = "slatedb")]
58async fn build_slatedb_kv(data_dir: &Path) -> Result<Arc<dyn KvStore>> {
59    Ok(Arc::new(
60        boatramp_storage::SlateKv::open_local_with_flush(
61            data_dir.join("kv-slate"),
62            CONTROL_PLANE_FLUSH,
63        )
64        .await?,
65    ))
66}
67
68#[cfg(not(feature = "slatedb"))]
69async fn build_slatedb_kv(_data_dir: &Path) -> Result<Arc<dyn KvStore>> {
70    Err(crate::error::Error::NoSlatedbSupport)
71}
72
73#[cfg(feature = "cloudflare-kv")]
74fn build_cloudflare_kv() -> Result<Arc<dyn KvStore>> {
75    Ok(Arc::new(boatramp_storage::CloudflareKv::from_env()?))
76}
77
78#[cfg(not(feature = "cloudflare-kv"))]
79fn build_cloudflare_kv() -> Result<Arc<dyn KvStore>> {
80    Err(crate::error::Error::NoCloudflareKvSupport)
81}