# datum-cluster-sharding
`datum-cluster-sharding` is the v0.10 cluster-sharding satellite for Datum. It
ships `ShardEnvelope`, shard extraction, deterministic oldest-member
coordinator allocation, peer `ShardRegion` routing over C2 DCP node-session
shard pipes, bounded buffering while a shard is allocated, bounded handoff
buffering while a shard is rebalanced, and first-message entity actor startup.
The data path uses long-lived per-peer pipes with batch-when-behind/no-linger
flushing; shard allocation misses remain on the control-plane request/response
path.
The default shard extractor uses a stable FNV-1a hash for cross-version and
cross-platform shard IDs. Upgrading from 0.10.0 causes a one-time remap for
deployments that used the old default extractor.
Delivery in v0.10 is intentionally modest: at-most-once per send attempt,
ordering per entity from a single sender that awaits each send, in-memory
allocation tables, and no persistent shard allocation store. When a node is
downed, the coordinator reallocates its shards with the least-shards strategy;
entity state is not migrated. Graceful join-driven rebalance uses the same
strategy with `rebalance_per_round` as the Akka-style per-round cap.
Remember-entities is opt-in per entity type via
`register_remembered_entity_type`. A configured `RememberEntitiesStore` records
entity starts/stops through a bounded write-behind queue, so store writes do not
block normal message delivery. When a remembered shard starts locally after
rebalance, restart recovery, or coordinator takeover, the region lists the
shard's remembered ids and starts those entity actors without waiting for the
next message.
Two stores ship with the SPI. `InMemoryStore` is for tests and single-process
development: it survives rebalance only when all regions share the same store
value, and it does not survive process death. `FileStore` writes one append log
per shard under a configured directory and compacts the shard log on
passivation. Its default fsync policy fsyncs appends and compactions, but
delivery is still write-behind: a message can be acknowledged before the start
record is durable. `FileStoreFsyncPolicy::Never` and `OnCompaction` trade
durability for less storage overhead. A future `datum-cdc`/persistent store is a
follow-up, not part of this crate.
Passivation removes remembered ids: `EntityRef::passivate()` stops the current
entity actor and deletes it from the remember store, while
`passivation_idle_timeout` passivates idle local entities on the region tick.
If a passivation command or user envelope reaches a moving shard, it is ordered
through the same bounded handoff buffer before the new owner sees later
messages. Ordinary entity actor failure/restart and node stop are not
passivation and do not remove the id from the store.
Coordinator takeover rebuilds the allocation table from surviving regions and
keeps the highest generation for each shard. Any rebuilt entry that still points
at a non-eligible member is reallocated by the new coordinator, so an in-flight
migration can be lost as a generation update but cannot orphan the shard.
Remember store failures publish `RememberEntitiesEvent` shard-level errors.
`FailOpen` keeps routing after an event; `FailClosed` marks that shard failed so
future messages fail fast until the region is restarted or replaced.