radicle: store threshold in Canonical
The Canonical type is generally constructed with the threshold, needed for the quorum computation, in scope. To make it easier to use and encapsulate its functionality, it now holds the threshold as an additional field.
This commit is contained in:
parent
b614167bd9
commit
b2bcd561cf
|
|
@ -280,6 +280,7 @@ pub fn run(
|
||||||
stored,
|
stored,
|
||||||
&project,
|
&project,
|
||||||
identity.delegates().as_ref(),
|
identity.delegates().as_ref(),
|
||||||
|
identity.threshold(),
|
||||||
)?;
|
)?;
|
||||||
let converges = canonical::converges(
|
let converges = canonical::converges(
|
||||||
canonical
|
canonical
|
||||||
|
|
@ -292,7 +293,7 @@ pub fn run(
|
||||||
canonical.modify_vote(me, head.into());
|
canonical.modify_vote(me, head.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
match canonical.quorum(identity.threshold(), &working) {
|
match canonical.quorum(&working) {
|
||||||
Ok(canonical_oid) => {
|
Ok(canonical_oid) => {
|
||||||
// Canonical head is an ancestor of head.
|
// Canonical head is an ancestor of head.
|
||||||
let is_ff = head == *canonical_oid
|
let is_ff = head == *canonical_oid
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@ use super::{lit, Oid, Qualified};
|
||||||
///
|
///
|
||||||
/// `Canonical` can then be used for performing calculations about the
|
/// `Canonical` can then be used for performing calculations about the
|
||||||
/// canonicity of the reference, most importantly the [`Canonical::quorum`].
|
/// canonicity of the reference, most importantly the [`Canonical::quorum`].
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Canonical {
|
pub struct Canonical {
|
||||||
tips: BTreeMap<Did, Oid>,
|
tips: BTreeMap<Did, Oid>,
|
||||||
|
threshold: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error that can occur when calculation the [`Canonical::quorum`].
|
/// Error that can occur when calculation the [`Canonical::quorum`].
|
||||||
|
|
@ -90,6 +92,7 @@ impl Canonical {
|
||||||
repo: &S,
|
repo: &S,
|
||||||
project: &Project,
|
project: &Project,
|
||||||
delegates: &NonEmpty<Did>,
|
delegates: &NonEmpty<Did>,
|
||||||
|
threshold: usize,
|
||||||
) -> Result<Self, raw::Error>
|
) -> Result<Self, raw::Error>
|
||||||
where
|
where
|
||||||
S: ReadRepository,
|
S: ReadRepository,
|
||||||
|
|
@ -98,6 +101,7 @@ impl Canonical {
|
||||||
repo,
|
repo,
|
||||||
delegates,
|
delegates,
|
||||||
&lit::refs_heads(project.default_branch()).into(),
|
&lit::refs_heads(project.default_branch()).into(),
|
||||||
|
threshold,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,6 +111,7 @@ impl Canonical {
|
||||||
repo: &S,
|
repo: &S,
|
||||||
delegates: &NonEmpty<Did>,
|
delegates: &NonEmpty<Did>,
|
||||||
name: &Qualified,
|
name: &Qualified,
|
||||||
|
threshold: usize,
|
||||||
) -> Result<Self, raw::Error>
|
) -> Result<Self, raw::Error>
|
||||||
where
|
where
|
||||||
S: ReadRepository,
|
S: ReadRepository,
|
||||||
|
|
@ -127,7 +132,7 @@ impl Canonical {
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Canonical { tips })
|
Ok(Canonical { tips, threshold })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the set of [`Did`]s and their [`Oid`] tip.
|
/// Return the set of [`Did`]s and their [`Oid`] tip.
|
||||||
|
|
@ -171,7 +176,7 @@ impl Canonical {
|
||||||
///
|
///
|
||||||
/// Also returns an error if `heads` is empty or `threshold` cannot be
|
/// Also returns an error if `heads` is empty or `threshold` cannot be
|
||||||
/// satisified with the number of heads given.
|
/// satisified with the number of heads given.
|
||||||
pub fn quorum(&self, threshold: usize, repo: &raw::Repository) -> Result<Oid, QuorumError> {
|
pub fn quorum(&self, repo: &raw::Repository) -> Result<Oid, QuorumError> {
|
||||||
let mut candidates = BTreeMap::<_, usize>::new();
|
let mut candidates = BTreeMap::<_, usize>::new();
|
||||||
|
|
||||||
// Build a list of candidate commits and count how many "votes" each of them has.
|
// Build a list of candidate commits and count how many "votes" each of them has.
|
||||||
|
|
@ -196,11 +201,14 @@ impl Canonical {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Keep commits which pass the threshold.
|
// Keep commits which pass the threshold.
|
||||||
candidates.retain(|_, votes| *votes >= threshold);
|
candidates.retain(|_, votes| *votes >= self.threshold);
|
||||||
|
|
||||||
let (mut longest, _) = candidates
|
let (mut longest, _) =
|
||||||
.pop_first()
|
candidates
|
||||||
.ok_or(QuorumError::NoCandidates(NoCandidates { threshold }))?;
|
.pop_first()
|
||||||
|
.ok_or(QuorumError::NoCandidates(NoCandidates {
|
||||||
|
threshold: self.threshold,
|
||||||
|
}))?;
|
||||||
|
|
||||||
// Now that all scores are calculated, figure out what is the longest branch
|
// Now that all scores are calculated, figure out what is the longest branch
|
||||||
// that passes the threshold. In case of divergence, return an error.
|
// that passes the threshold. In case of divergence, return an error.
|
||||||
|
|
@ -235,7 +243,7 @@ impl Canonical {
|
||||||
// |
|
// |
|
||||||
//
|
//
|
||||||
return Err(QuorumError::Diverging(Diverging {
|
return Err(QuorumError::Diverging(Diverging {
|
||||||
threshold,
|
threshold: self.threshold,
|
||||||
base: base.into(),
|
base: base.into(),
|
||||||
longest,
|
longest,
|
||||||
head: *head,
|
head: *head,
|
||||||
|
|
@ -271,7 +279,7 @@ mod tests {
|
||||||
(did, (*head).into())
|
(did, (*head).into())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Canonical { tips }.quorum(threshold, repo)
|
Canonical { tips, threshold }.quorum(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -752,8 +752,9 @@ impl ReadRepository for Repository {
|
||||||
let project = doc.project()?;
|
let project = doc.project()?;
|
||||||
let branch_ref = git::refs::branch(project.default_branch());
|
let branch_ref = git::refs::branch(project.default_branch());
|
||||||
let raw = self.raw();
|
let raw = self.raw();
|
||||||
let oid = Canonical::default_branch(self, &project, doc.delegates().into())?
|
let oid =
|
||||||
.quorum(doc.threshold(), raw)?;
|
Canonical::default_branch(self, &project, doc.delegates().into(), doc.threshold())?
|
||||||
|
.quorum(raw)?;
|
||||||
Ok((branch_ref, oid))
|
Ok((branch_ref, oid))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue