job_queue: drop insert_unless_live, accept extra queue passes
mara chose to accept extra queued sweep passes over adding a new hive-jobq primitive (or a hive-c0re one-off) for "don't queue another of this kind". Every sweep caller now plain-inserts its node; the capacity-1 Dep::Resource per sweep kind (MatrixSweep/KnowledgeTree) still keeps two passes of the same kind from running concurrently, it just no longer collapses a tick that lands while one is live or queued into the existing one.
This commit is contained in:
parent
1d4c77d2c8
commit
313d582c01
6 changed files with 37 additions and 90 deletions
|
|
@ -192,39 +192,6 @@ impl JobQueue {
|
|||
Ok(named)
|
||||
}
|
||||
|
||||
/// Insert the single node `declare` names, unless a node of `kind` is
|
||||
/// already in one of the `fold_into` states. `None` means the caller's
|
||||
/// request folded into that node and nothing was inserted.
|
||||
///
|
||||
/// For a standalone sweep, where a pass that has not started yet already
|
||||
/// covers "one more pass": it reads whatever is current when it runs. The
|
||||
/// read and the insert share one lock, so two racing callers cannot both
|
||||
/// miss the other.
|
||||
///
|
||||
/// # Errors
|
||||
/// Propagates a graph-insert error.
|
||||
pub fn insert_unless_live(
|
||||
&self,
|
||||
kind: &NodeKind,
|
||||
fold_into: &[State],
|
||||
declare: impl FnOnce(&JobBuilder) -> Handle<'_>,
|
||||
) -> anyhow::Result<Option<NodeId>> {
|
||||
let mut inner = self.lock();
|
||||
let live = inner
|
||||
.graph()
|
||||
.nodes()
|
||||
.any(|n| &n.payload == kind && fold_into.contains(&n.state));
|
||||
if live {
|
||||
return Ok(None);
|
||||
}
|
||||
let named = inner
|
||||
.insert_job(None, |b| vec![declare(b).guid()])
|
||||
.map_err(|e| anyhow::anyhow!("job_queue: graph insert failed: {e}"))?;
|
||||
drop(inner);
|
||||
self.notify.notify_one();
|
||||
Ok(named.first().copied())
|
||||
}
|
||||
|
||||
/// The scheduler itself, for `hive_jobq`'s run-loop seam
|
||||
/// (`Scheduler::claim_next`), which takes exactly this type.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ fn reconcile_transients(coord: &Arc<Coordinator>, prev: &mut TransientSeen) {
|
|||
mod tests {
|
||||
use hive_jobq::scheduler::{Outcome, Scheduler};
|
||||
|
||||
use super::super::{JobQueue, NodeKind, State, templates};
|
||||
use super::super::{JobQueue, State, templates};
|
||||
|
||||
/// Claim one runnable node through the same seam [`super::run_worker`]
|
||||
/// uses. The returned future completes the node when awaited. `None` when
|
||||
|
|
@ -271,38 +271,28 @@ mod tests {
|
|||
second.await;
|
||||
}
|
||||
|
||||
/// A tick landing while a pass is already live queues a second pass; the
|
||||
/// shared `Resource::KnowledgeTree` dep holds it back until the first
|
||||
/// finishes, so the two never run together.
|
||||
#[tokio::test]
|
||||
async fn a_tick_folds_into_a_live_pull_and_an_event_queues_one_behind_it() {
|
||||
async fn a_tick_during_a_live_pull_queues_one_pass_behind_it() {
|
||||
let q = JobQueue::new(1);
|
||||
let kind = NodeKind::KnowledgePull;
|
||||
let queued = [State::Pending];
|
||||
let live = [State::Pending, State::Running];
|
||||
let submit = |fold_into: &[State]| {
|
||||
q.insert_unless_live(&kind, fold_into, templates::knowledge_pull)
|
||||
.expect("insert")
|
||||
.is_some()
|
||||
};
|
||||
q.insert_job(|b| vec![templates::knowledge_pull(b).guid()])
|
||||
.expect("insert");
|
||||
let live = claim(&q).expect("the first pull is runnable");
|
||||
assert_eq!(running(&q), ["knowledge_pull"]);
|
||||
|
||||
assert!(submit(&live), "nothing live: a tick inserts");
|
||||
let pull = claim(&q).expect("the pull is runnable");
|
||||
assert!(!submit(&live), "a tick folds into the running pull");
|
||||
assert!(
|
||||
submit(&queued),
|
||||
"an event queues a pull behind the running one"
|
||||
);
|
||||
assert!(
|
||||
!submit(&queued),
|
||||
"a second event folds into the queued pull"
|
||||
);
|
||||
assert!(!submit(&live), "a tick folds into the queued pull");
|
||||
q.insert_job(|b| vec![templates::knowledge_pull(b).guid()])
|
||||
.expect("insert");
|
||||
assert_eq!(count(&q, "knowledge_pull"), 2);
|
||||
|
||||
assert!(
|
||||
q.insert_unless_live(&NodeKind::MatrixSweep, &live, templates::matrix_sweep)
|
||||
.expect("insert")
|
||||
.is_some(),
|
||||
"a live pull does not fold a different sweep"
|
||||
claim(&q).is_none(),
|
||||
"the second pull waits for the resource the first one holds"
|
||||
);
|
||||
pull.await;
|
||||
|
||||
live.await;
|
||||
let second = claim(&q).expect("the second pull runs once the first is done");
|
||||
assert_eq!(running(&q), ["knowledge_pull"]);
|
||||
second.await;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue