Skip to main content

quorum_set/quorum/
quorum_set.rs

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