Watch
0
0
Fork
You've already forked hyperhive
0

review classifier: the most classifications a run carries is a setting

The limit was a constant of ten in swarm-wire, so a repo with eleven rules
could not be reviewed and nothing short of a rebuild changed it. It is now
`max_classifications` in the classifier settings, beside
`max_concurrent_reviews`: 1 to 1000, ten until set, and a document stored
before the field decodes with the default. The classifier settings form in
the swarm UI gets a "rules per review" field, and the try-out's add button
stops at the saved limit instead of a hard-coded ten.

The controller checks a try-out, and a requested review's rules file, against
the setting where the run starts. The rules file itself may hold up to the
1000 the setting allows, so raising the limit needs no change to a repo.
A review whose rules exceed the limit posts a no-verdict comment saying so.

A run's reply deadline was a constant that covered ten classifications, a
minute plus three each. It is now computed from the run's own size, so a
bigger run waits as long as it needs and a default-sized one still waits 31
minutes. The classifier's answer window in the queue permissions covers the
biggest run the setting allows.
This commit is contained in:
iris 2026-11-07 10:37:52 +01:00 • committed by mara
commit cffe8895df

View file

@ -6,6 +6,7 @@
//! Three crates name these: the controller sends the request, the classifier
//! answers it, and the auth-callout responder grants the one subject to each.
use std::ops::RangeInclusive;
use std::time::Duration;
use serde::{Deserialize, Serialize};
@ -34,18 +35,34 @@ pub const REQUEST_SUBJECT_PREFIX: &str = "$SWARM.review-request";
/// from.
pub const REQUEST_CONSUMER: &str = "swarm-controller";
/// The most classifications one run carries.
pub const MAX_CLASSIFICATIONS: usize = 10;
/// What the most classifications one run carries may be set to: the swarm
/// setting's bounds. Each classification is one ask of up to
/// [`CLASSIFICATION_DEADLINE`], run one after another, so the top of the range
/// is a run of days; an administrator who sets it that high gets that.
pub const CLASSIFICATION_LIMITS: RangeInclusive<usize> = 1..=1000;
/// The most classifications one run carries until the setting says otherwise.
pub const DEFAULT_MAX_CLASSIFICATIONS: usize = 10;
/// The longest one classification may take, its first ask and any second ask
/// together, before it is stopped and its row carries a timeout.
pub const CLASSIFICATION_DEADLINE: Duration = Duration::from_mins(3);
/// The longest a whole run may take: every classification at its deadline,
/// run one after another, plus a minute for the rest. The controller waits
/// this long for the reply, and the queue lets the classifier answer for
/// this long.
pub const RUN_DEADLINE: Duration = Duration::from_mins(31);
/// The longest a run of `classifications` may take: every classification at
/// its deadline, run one after another, plus a minute for the rest. The
/// controller waits this long for the reply.
#[must_use]
pub fn run_deadline(classifications: usize) -> Duration {
let count = u32::try_from(classifications).unwrap_or(u32::MAX);
CLASSIFICATION_DEADLINE.saturating_mul(count) + Duration::from_mins(1)
}
/// The longest any run may take, for the biggest run the setting allows. The
/// queue lets the classifier answer for this long.
#[must_use]
pub fn max_run_deadline() -> Duration {
run_deadline(*CLASSIFICATION_LIMITS.end())
}
/// The model a run uses when its request names none, and the swarm-wide
/// setting's default.
@ -244,8 +261,16 @@ mod tests {
#[test]
fn the_run_deadline_covers_every_classification_at_its_deadline() {
let all = CLASSIFICATION_DEADLINE * u32::try_from(MAX_CLASSIFICATIONS).expect("small");
assert!(RUN_DEADLINE > all);
for n in [1, DEFAULT_MAX_CLASSIFICATIONS, *CLASSIFICATION_LIMITS.end()] {
let all = CLASSIFICATION_DEADLINE * u32::try_from(n).expect("small");
assert!(run_deadline(n) > all, "{n} classifications");
}
// A default-sized run waits the half hour it always has.
assert_eq!(
run_deadline(DEFAULT_MAX_CLASSIFICATIONS),
Duration::from_mins(31)
);
assert_eq!(max_run_deadline(), run_deadline(1000));
}
#[test]