Skip to main content

quorum_set/quorum/
quorum_set.rs

1use std::sync::Arc;
2
3#[cfg(doc)]
4use crate::BothQuorums;
5#[cfg(doc)]
6use crate::Joint;
7#[cfg(doc)]
8use crate::QuorumTree;
9#[cfg(doc)]
10use crate::ReadOrBoth;
11#[cfg(doc)]
12use crate::ThresholdQuorumSet;
13#[cfg(doc)]
14use crate::VecProgress;
15#[cfg(doc)]
16use crate::verify_intersection;
17
18/// Common interface for every quorum rule supported by this crate.
19///
20/// A quorum is a collection of nodes that a read or write operation in a distributed system has to
21/// contact. See: <http://web.mit.edu/6.033/2005/wwwdocs/quorum_note.html>
22///
23/// Every implementation must follow four rules:
24///
25/// - Upward-closed: adding IDs to an accepted quorum keeps it accepted. [`VecProgress`] and
26///   [`verify_intersection`] rely on this rule.
27/// - Closed over [`ids()`](Self::ids): an ID that `ids()` does not yield never changes the result
28///   of [`is_quorum()`](Self::is_quorum). [`verify_intersection`] enumerates only the IDs that
29///   `ids()` yields, so it relies on this rule.
30/// - Duplicate-safe: an ID that appears more than once in the `is_quorum()` input counts once, so
31///   callers may pass an iterator with repeats.
32/// - No empty quorum: an input that holds no ID from `ids()`, such as an empty input, is never a
33///   quorum. An upward-closed rule that accepted the empty input would accept every input, so a
34///   read or write operation would succeed without contacting any node.
35///
36/// The crate provides implementations for flat majority sets, joint quorum sets,
37/// [`ThresholdQuorumSet`] rules, [`Joint`] rules over any rule type, hierarchical [`QuorumTree`]
38/// rules, and [`BothQuorums`], which requires both a read and a write quorum.
39/// [`ReadOrBoth`] holds either a read rule alone or a [`BothQuorums`].
40pub trait QuorumSet {
41    /// Node ID type in this quorum set.
42    type Id;
43
44    /// Iterator over every voter ID tracked by this quorum set.
45    ///
46    /// Implementations that combine multiple sub-rules return each ID once.
47    type Iter: Iterator<Item = Self::Id>;
48
49    /// Return `true` if the candidate IDs satisfy this quorum rule.
50    ///
51    /// Repeated IDs count once, and IDs that [`ids()`](Self::ids) does not yield are ignored.
52    /// An empty input is never a quorum.
53    fn is_quorum<'a, I>(&self, ids: I) -> bool
54    where
55        Self::Id: 'a,
56        I: Iterator<Item = &'a Self::Id> + Clone;
57
58    /// Return all voter IDs in this quorum set.
59    fn ids(&self) -> Self::Iter;
60}
61
62impl<T> QuorumSet for Arc<T>
63where T: QuorumSet
64{
65    type Id = T::Id;
66
67    type Iter = T::Iter;
68
69    fn is_quorum<'a, I>(&self, ids: I) -> bool
70    where
71        Self::Id: 'a,
72        I: Iterator<Item = &'a Self::Id> + Clone,
73    {
74        self.as_ref().is_quorum(ids)
75    }
76
77    fn ids(&self) -> Self::Iter {
78        self.as_ref().ids()
79    }
80}