tidaldb/tidal/src/replication/mod.rs
jordan.washburn fe711870be feat: M8 phases 7-10 — gRPC transport, cluster server, scatter-gather, multi-node UAT
Delivers the distributed fabric's network layer and HTTP cluster surface:

**m8p7: tidal-net crate (gRPC transport)**
- GrpcTransport implementing Transport trait via tonic 0.12
- Per-peer circuit breaker (Closed/Open/HalfOpen), mutual TLS via rustls
- Boxed error types (clippy-clean), graceful mutex recovery, debug_assert
  against calling block_on from tokio context
- Proto: WalShipping service (ShipSegment, StreamSegments stub, Heartbeat)
- 19 tests: contract, mTLS, reconnection, multi-node UAT, benchmarks

**m8p8: cluster subcommand + HTTP routes**
- ClusterState wrapping SimulatedCluster with region name mapping
- Routes: /health, /cluster/status, /cluster/promote, /partition, /heal
- Data routes: /items, /embeddings, /signals, /feed, /search (region-aware)
- Ranking profiles wired through ClusterConfig to all cluster nodes
- Topology YAML config, docker/cluster/Dockerfile (ENTRYPOINT+CMD, non-root)

**m8p9: scatter-gather query routing**
- Entity-sharded writes via Knuth multiplicative hash
- Scatter-gather RETRIEVE and SEARCH with deadline propagation (50ms-5ms)
- Partial failure: degraded=true with unavailable_shards metadata
- 6 tests: distribution, determinism, multi-shard retrieve, degraded
  partial results, deadline propagation, scatter-gather search

**m8p10: gRPC transport integration tests**
- 8 tests over real gRPC: replication convergence, idempotent replay,
  mixed signals, 3-node fan-out, partition/heal, degraded follower, perf
- Documented as tier-2 (in-process+gRPC); tier-3 multi-process pending
2026-04-11 13:51:08 -06:00

55 lines
1.9 KiB
Rust

//! Replication types and protocols for distributed tidalDB deployments.
//!
//! The `replication` module is empty in single-node deployments --
//! all types default to `shard_id=0`, `region_id=0`, and routing is a no-op.
pub mod control;
pub mod crdt;
pub mod idempotency;
pub mod in_process;
pub mod lag;
pub mod migration;
pub mod receiver;
pub mod reconcile;
pub mod segment_id;
pub mod session_bridge;
pub mod shard;
pub mod shipper;
pub mod state;
pub mod tenant;
pub mod transport;
pub mod upgrade;
pub use control::{ClusterHealth, ControlPlane, RegionHealth, ShardStats};
pub use crdt::{Hlc, HlcTimestamp};
pub use idempotency::{IdempotencyKey, IdempotencyStore};
pub use in_process::{InProcessTransport, InProcessTransportFactory};
pub use lag::ReplicationLagGauge;
pub use migration::{MigrationState, TenantMigration};
pub use receiver::{SegmentReceiverHandle, apply_payload, spawn_receiver};
pub use reconcile::{HardNegAction, MergePlan, ReconciliationEngine, StateSnapshot};
pub use segment_id::WalSegmentId;
pub use session_bridge::{
InProcessSessionTransportFactory, SessionBridgeError, SessionPayload, SessionReplicationBridge,
SessionShardTransport,
};
pub use shard::{EntityIdRange, RegionId, RouterError, RoutingStrategy, ShardId, ShardRouter};
pub use shipper::{ShipperConfig, WalShipperHandle, spawn_shipper};
pub use state::ReplicationState;
pub use tenant::{
ClusterTopology, ShardAssignment, TenantConfig, TenantId, TenantRateLimiter, TenantRouter,
};
pub use transport::{Transport, TransportError, WalSegmentPayload};
pub use upgrade::{RollingUpgradeCoordinator, UpgradePhase};
/// Current wall-clock time in nanoseconds since the Unix epoch.
///
/// Uses `u64`, which overflows in year 2554 — safe for all practical purposes.
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn now_ns() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64
}