oxedyne/fe2o3/fe2o3_o3db_sync/src/oam/config.rs
2.4 KiB, 34 runs
created by r1870400018:11366, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | //! The OAM configuration block. |
| 2 | //! |
| 3 | //! An [`OamConfig`] is the inputs of the placement inequality: the replication |
| 4 | //! factor `n` and the current estimated network size `N`. It is held by every |
| 5 | //! peer and refreshed when either input changes -- `n` on a configuration |
| 6 | //! reload, `N` on a HyperLogLog-driven estimate update. |
| 7 | //! |
| 8 | //! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\ |
| 9 | //! Anthropic Claude |
| 10 | |
| 11 | use super::threshold::Threshold; |
| 12 | |
| 13 | use oxedyne_fe2o3_core::prelude::*; |
| 14 | |
| 15 | |
| 16 | /// The OAM configuration held by every peer. |
| 17 | /// |
| 18 | /// # Invariants |
| 19 | /// |
| 20 | /// - `replication` is the target number of holders per record. |
| 21 | /// - `network_size` is the current estimated peer count, `N`. |
| 22 | /// |
| 23 | /// Both are allowed to be zero; the resulting threshold will saturate to |
| 24 | /// [`Threshold::None`] or [`Threshold::All`] accordingly. [`OamConfig::new`] |
| 25 | /// rejects the genuinely nonsensical combination `replication > 0 && |
| 26 | /// network_size == 0` so the caller does not accidentally declare "twenty |
| 27 | /// replicas on nothing" as if it were a routine state. |
| 28 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
| 29 | pub struct OamConfig { |
| 30 | pub replication: u64, // n in the specification |
| 31 | pub network_size: u64, // N in the specification |
| 32 | } |
| 33 | |
| 34 | impl OamConfig { |
| 35 | // The figure quoted in the Hematite specification. |
| 36 | pub const DEFAULT_REPLICATION: u64 = 20; |
| 37 | |
| 38 | /// The spec allows `replication == 0` -- no peer holds anything -- as a |
| 39 | /// well-defined limit. `network_size == 0` with a non-zero replication is |
| 40 | /// an operator mistake rather than a valid operating point, and is |
| 41 | /// rejected. |
| 42 | pub fn new(replication: u64, network_size: u64) -> Outcome<Self> { |
| 43 | if replication > 0 && network_size == 0 { |
| 44 | return Err(err!( |
| 45 | "OAM configuration requires network_size > 0 when \ |
| 46 | replication > 0, got replication={} network_size=0.", |
| 47 | replication; |
| 48 | Invalid, Input, Size)); |
| 49 | } |
| 50 | Ok(Self { |
| 51 | replication, |
| 52 | network_size, |
| 53 | }) |
| 54 | } |
| 55 | |
| 56 | pub fn default_replication(network_size: u64) -> Outcome<Self> { |
| 57 | Self::new(Self::DEFAULT_REPLICATION, network_size) |
| 58 | } |
| 59 | |
| 60 | /// A pure function of `(replication, network_size)`, and worth caching when |
| 61 | /// a peer checks placement against many records. |
| 62 | pub fn threshold(&self) -> Threshold { |
| 63 | Threshold::from_params(self.replication, self.network_size) |
| 64 | } |
| 65 | |
| 66 | /// Per record, clamped to `min(replication, network_size)`. |
| 67 | pub fn expected_holders(&self) -> u64 { |
| 68 | self.replication.min(self.network_size) |
| 69 | } |
| 70 | } |