closed flow also queues a closed todo on each agent that held one, after the clear
This commit is contained in:
parent
fb8aa23e66
commit
0a1e4db0f4
4 changed files with 99 additions and 24 deletions
|
|
@ -4,8 +4,9 @@
|
|||
//! `swarm_wire::notify_flows`; the built-in and the custom flows are the same
|
||||
//! type and this walk runs both. A `match` node passes when every one of its
|
||||
//! conditions holds, and then each of its children runs, so one event can
|
||||
//! reach several branches. A `todo` node emits one op per recipient. The
|
||||
//! router runs only flows that pass [`Flow::validate`].
|
||||
//! reach several branches, in edge order, so a clear listed before an upsert
|
||||
//! is queued before it. A `todo` node emits one op per recipient. The router
|
||||
//! runs only flows that pass [`Flow::validate`].
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
|
|
@ -46,10 +47,10 @@ pub fn evaluate(flow: &Flow, event_type: &str, fields: &Fields) -> Vec<Action> {
|
|||
while let Some(id) = stack.pop() {
|
||||
let Some(node) = flow.node(id) else { continue };
|
||||
match &node.kind {
|
||||
NodeKind::Source { .. } => stack.extend(flow.children(id)),
|
||||
NodeKind::Source { .. } => stack.extend(flow.children(id).into_iter().rev()),
|
||||
NodeKind::Match { when } => {
|
||||
if when.iter().all(|c| holds(c, fields)) {
|
||||
stack.extend(flow.children(id));
|
||||
stack.extend(flow.children(id).into_iter().rev());
|
||||
}
|
||||
}
|
||||
NodeKind::Todo(sink) => actions.extend(emit(flow, node, sink, fields)),
|
||||
|
|
@ -229,6 +230,7 @@ mod tests {
|
|||
"issues",
|
||||
&event("closed", &[], &[], &["atlas", "argus"]),
|
||||
);
|
||||
let got: Vec<_> = got.into_iter().filter(|a| a.node == "sink").collect();
|
||||
assert_eq!(got.len(), 2);
|
||||
for a in &got {
|
||||
assert_eq!(a.op.op, Op::Clear);
|
||||
|
|
@ -239,6 +241,43 @@ mod tests {
|
|||
assert!(evaluate(&closed, "issues", &event("reopened", &[], &[], &["atlas"])).is_empty());
|
||||
}
|
||||
|
||||
/// The clear runs before the `closed` todo, so its prefix does not take the
|
||||
/// todo with it, and both read the one holders set.
|
||||
#[test]
|
||||
fn closing_clears_then_tells_each_holder() {
|
||||
let closed = flow("closed");
|
||||
let got = evaluate(
|
||||
&closed,
|
||||
"pull_request",
|
||||
&event("closed", &[], &[], &["atlas", "argus"]),
|
||||
);
|
||||
let seen: Vec<(&str, &str, Op)> = got
|
||||
.iter()
|
||||
.map(|a| (a.node.as_str(), a.agent.as_str(), a.op.op))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
seen,
|
||||
[
|
||||
("sink", "atlas", Op::Clear),
|
||||
("sink", "argus", Op::Clear),
|
||||
("inform", "atlas", Op::Upsert),
|
||||
("inform", "argus", Op::Upsert),
|
||||
]
|
||||
);
|
||||
let tell = &got[2].op;
|
||||
assert_eq!(tell.key, "forge:hyperhive/hyperhive#7:closed");
|
||||
assert!(!tell.prefix);
|
||||
assert_eq!(
|
||||
tell.summary,
|
||||
"issue hyperhive/hyperhive#7 was closed: router (https://forge/7)"
|
||||
);
|
||||
assert_eq!(tell.source, "router:closed");
|
||||
// The clear's prefix covers the todo's key: the order is what saves it.
|
||||
assert!(tell.key.starts_with(&got[0].op.key));
|
||||
// No holders, no todos.
|
||||
assert!(evaluate(&closed, "issues", &event("closed", &[], &[], &[])).is_empty());
|
||||
}
|
||||
|
||||
/// A match node with two children runs both: the branching the tree
|
||||
/// allows.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -137,9 +137,18 @@ mod tests {
|
|||
&flows,
|
||||
is_agent,
|
||||
);
|
||||
// Per agent the clear comes before the closed todo that its prefix would take.
|
||||
let mut got = agents(&closed);
|
||||
got.sort_unstable_by_key(|(a, _)| *a);
|
||||
assert_eq!(got, [("atlas", Op::Clear), ("iris", Op::Clear)]);
|
||||
got.sort_by_key(|(a, _)| *a);
|
||||
assert_eq!(
|
||||
got,
|
||||
[
|
||||
("atlas", Op::Clear),
|
||||
("atlas", Op::Upsert),
|
||||
("iris", Op::Clear),
|
||||
("iris", Op::Upsert)
|
||||
]
|
||||
);
|
||||
assert!(closed.next.holders.is_empty());
|
||||
// A close leaves the assignee snapshot as the last assign set it.
|
||||
assert_eq!(closed.next.assignees, three.next.assignees);
|
||||
|
|
|
|||
Loading…
Reference in a new issue