m11p1 — decoupled ack/ship path: staged writes (seqno+WAL+relay-push, microseconds) separate from group-commit fsync; ShipQueue batches+windows outbound segments; receiver coalesces inbound chunks before applying. Adds first tidaldb_cluster_* metrics. m11p2 — leader WAL is now THE replicated log: fsynced batches feed a bounded WalShipFeed and ship byte-identical to followers; WAL seqnos survive restarts (relay-reset hazard gone). Item metadata and embeddings journal kind-1/2 blob records on the same stream as signals; the m8p10 HTTP broadcast is deleted. StreamSegments catch-up is follower-pulled via server-streaming RPC, triggered on gap detection, follower boot, and leader heal nudge. Promote carries a stream baseline so peers skip pre-stream history.
57 lines
2.7 KiB
Rust
57 lines
2.7 KiB
Rust
//! Cluster mode: multi-region tidalDB behind an HTTP surface.
|
||
//!
|
||
//! Two cluster modes share this module:
|
||
//!
|
||
//! * **Single-process** ([`ClusterState`], the m8p8 dev/demo default): every
|
||
//! region runs inside ONE process, wrapping [`SimulatedCluster`] with region
|
||
//! name ↔ [`RegionId`] mapping. Replication between regions still traverses a
|
||
//! real [`GrpcTransport`] on loopback (not in-process channels), but a crash
|
||
//! takes the whole "cluster" down — there is no process isolation.
|
||
//! * **Multi-process** ([`RegionClusterState`], the m8p10 mode, selected by
|
||
//! `--region`): this process owns exactly ONE region — one [`TidalDb`], one
|
||
//! [`GrpcTransport`] whose server binds this region's `grpc_addr` and whose
|
||
//! peers are every sibling region's real `grpc_addr` — and peers with sibling
|
||
//! processes over real gRPC. Process isolation is real; quorum-ack writes and
|
||
//! automatic failure detection are still future work.
|
||
//!
|
||
//! Both modes are gated behind the same explicit operator opt-in
|
||
//! ([`ensure_experimental_enabled`]).
|
||
//!
|
||
//! # Module layout (M0–M10 review Maintainability-S follow-up)
|
||
//!
|
||
//! The original single 1379-line `cluster.rs` carried four loosely-coupled
|
||
//! concerns; it was split (behavior-neutral) into:
|
||
//!
|
||
//! * [`topology`] — `TopologySpec` / `RegionSpec` / `load_topology` / validation
|
||
//! * [`transport`] — single-process self-loop gRPC transport wiring
|
||
//! * [`state`] — [`ClusterState`] (single-process) + the experimental gate
|
||
//! * [`routes`] — the single-process router + handlers
|
||
//! * [`node`] — [`RegionClusterState`] (multi-process) + its router/handlers
|
||
//!
|
||
//! [`GrpcTransport`]: tidal_net::GrpcTransport
|
||
//! [`RegionId`]: tidaldb::replication::shard::RegionId
|
||
//! [`SimulatedCluster`]: tidaldb::testing::SimulatedCluster
|
||
//! [`TidalDb`]: tidaldb::TidalDb
|
||
|
||
pub(crate) mod forward;
|
||
pub(crate) mod node;
|
||
pub(crate) mod routes;
|
||
mod state;
|
||
mod topology;
|
||
mod transport;
|
||
|
||
// ── Public API (preserved across the split) ─────────────────────────────────
|
||
|
||
pub use node::{RegionClusterState, build_region_router};
|
||
pub use routes::build_cluster_router;
|
||
pub use state::{ClusterMode, ClusterState, EXPERIMENTAL_CLUSTER_ENV, ensure_experimental_enabled};
|
||
pub use topology::{
|
||
GrpcTlsSpec, RegionSpec, ReplicationSpec, TimeoutsSpec, TopologySpec, WalSpec, load_topology,
|
||
validate_multiproc,
|
||
};
|
||
|
||
// The OpenAPI documents (`crate::openapi`) reach the handlers/DTOs through
|
||
// `cluster::routes::…` / `cluster::node::…` directly, so the
|
||
// `#[utoipa::path]`-generated `__path_*` types resolve in the module that
|
||
// defines them. `node` reaches `ClusterAppError` via `super::routes`.
|