Skip to content

Show example cycle when ls-apis errors about them#10235

Open
iximeow wants to merge 1 commit intomainfrom
ixi/ls-apis-debug
Open

Show example cycle when ls-apis errors about them#10235
iximeow wants to merge 1 commit intomainfrom
ixi/ls-apis-debug

Conversation

@iximeow
Copy link
Copy Markdown
Member

@iximeow iximeow commented Apr 7, 2026

cargo xtask ls-apis check will report an error if the software component graph contains a cycle, as well as if the deployment units form a cycle, but prints only the name of a node in the graph that was in the cycle. If you've added a cycle to either of these graphs, the error and node can tell you about the what that is wrong. Going a bit further and printing an example cycle including the troublesome node can help with the how you got there.

With this change, the first approach at #10231 (which introduced a cycle
in, but all in one deployment unit: sled-agent -> propolis-server ->
sled-agent) errors with a more clear message about propolis-server and sled-agent being the problems:

Error: graph of server-managed API dependencies between components has a cycle
(includes node: "propolis-server", example cycle: propolis-server, omicron-sled-agent)

(this is the PR that @jgallagher alluded to me putting together, in #10232 )

`cargo xtask ls-apis check` will report an error if the software
component graph contains a cycle, as well as if the deployment units
form a cycle, but prints only the name of a node in the graph that was
in the cycle. If you've added a cycle to either of these graphs, the
error and node can tell you about the what that is wrong. Going a bit
further and printing an example cycle including the troublesome node can
help with the how you got there.

With this change, the first approach at #10231 (which introduced a cycle
in, but all in one deployment unit: sled-agent -> propolis-server ->
sled-agent) errors with a more clear message about propolis-server and
sled-agent being the problems:

```
Error: graph of server-managed API dependencies between components has a cycle
(includes node: "propolis-server", example cycle: propolis-server, omicron-sled-agent)
```
@iximeow iximeow requested a review from davepacheco April 7, 2026 03:28
Copy link
Copy Markdown
Collaborator

@davepacheco davepacheco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement.

let reverse_nodes: BTreeMap<_, _> =
nodes.iter().map(|(s_c, node)| (node, s_c)).collect();
if let Err(error) = petgraph::algo::toposort(&graph, None) {
let example_cycle =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're only constructing reverse_nodes and calling toposort to look for a cycle. Rather than use toposort to detect a cycle and then tarjan_scc to print more information, how about just using tarjan_scc to look for cycles and construct a printed summary if it finds one?

I think it's worth a one-line mention of the relationship between cycles and SCCs -- I didn't remember the connection off the top of my head. (If anybody else forgot, too: a node participates in a cycle if it (1) has a self-loop, or (2) is in an SCC with at least one other node.)

Comment on lines +137 to +139
let Some(first_cycle) = sccs.get(0) else {
return None;
};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely forgot all of this, but: doesn't every node appear in at least one SCC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants