fix(errorgraph): attribute topic-wait roots to the blocked dependent, not the expected publisher - #120
fix(errorgraph): attribute topic-wait roots to the blocked dependent, not the expected publisher#120spurnvoj wants to merge 1 commit into
Conversation
… not the expected publisher find_error_roots() previously attributed a missing-topic root to the topic's expected publisher, even though that publisher never reported anything -- the message was fabricated at serialization time using the wrong identity, and its timestamp was never set (always zero). A healthy, actively-reporting publisher could show up as its own "root cause" purely for being named in someone else's waiting_for_topic error, while the component actually stuck waiting was invisible in the aggregated root_errors output. find_error_roots(), find_roots(), and find_dependency_roots() now attribute each topic-wait root to the component actually blocked on it (via a shared append_info() helper), emitting one entry per distinct waiter instead of collapsing multiple waiters (or misattributing) into one. The expected publisher is preserved as context inside the error's waited_for_node field, correctly separated from the outer identity via topic_info_t's new source_node/expected_publisher split. Separately, expected_publisher metadata on a waiting_for_topic error no longer counts as a waited_for_node-style dependency edge -- only genuine TYPE_WAITING_FOR_NODE errors do. Missing topic data can have causes unrelated to the named node's health (QoS mismatch, wrong topic name, etc.), so naming a node as expected publisher must not by itself make that node root-eligible; the pre-existing behavior for genuine node-dependencies (find_error_roots_waiting_with_no_error_dependency) is unchanged. Finally, find_element_mutable(node_id_t) now only matches real node elements, not topic placeholders that happen to share the same source_node identity (the expected publisher). Without this, removing expected_publisher from waited_for_nodes() above stopped prepare_graph() from pre-creating a node placeholder for that identity, which had been accidentally shielding a subtle bug: a publisher's first real report could resolve to a pre-existing topic placeholder instead of creating its own element, permanently losing that publisher's errors (and the topic-wait entry) for the process lifetime once triggered (e.g. by a HwApiManager restart racing a stuck sensor's topic-wait).
|
@matemat13 sorry for the spam, but I got a nice setup when I am finding issues with errorgraph. :) |
matemat13
left a comment
There was a problem hiding this comment.
Looks mostly good. But doesn't this break the dependency graph sometimes? Like when a node is genuinely supposed to publish a topic that other nodes are waiting for, but it itself is waiting for something else... This change would hide that dependency, no? That was the original idea why it was implemented like this...
| { | ||
| waited_for_topic = msg.waited_for_topic; | ||
| if (!msg.waited_for_node.node.empty() || !msg.waited_for_node.component.empty()) | ||
| waited_for_node = node_id_t::from_msg(msg.waited_for_node); |
There was a problem hiding this comment.
hmm I don't particularly like reusing the waited_for_node member for the expected publisher. Those two have slightly different semantics. I propose adding an extra field to error_t - expected_publisher and similarly to the message to make the distinction clear.
| topic_error.type = mrs_msgs::msg::ErrorgraphError::TYPE_WAITING_FOR_TOPIC; | ||
| topic_error.waited_for_topic = topic_name; | ||
| topic_error.waited_for_node = source_node.to_msg(); | ||
| topic_error.waited_for_node = expected_publisher.to_msg(); |
There was a problem hiding this comment.
See my comment to erorgraph.h:R118
| for (const auto& el : errors) | ||
| { | ||
| if (el.waited_for_node.has_value()) | ||
| if (el.is_waiting_for_node() && el.waited_for_node.has_value()) |
There was a problem hiding this comment.
see my comment to R118. Adding that extra member expected_publisher would also make the comment here at 251-253 redundant and this code harder to break
| graph_up_to_date_ = true; | ||
| } | ||
|
|
||
| void Errorgraph::append_info(const element_t& el, std::vector<element_info_t>& out) |
There was a problem hiding this comment.
Can't this simply be implemented within to_info()? I.e. if the element is of topic type, it returns a vector of topic infos of the waiting nodes. If not, it returns a single-element vector of its own info. The method should then probably be renamed to to_infos() or something... I'm not particularly fond of creating an extra method within Errograph for this.
| { | ||
| if (type == type_t::topic) | ||
| return topic_info_t{topic_name, source_node, stamp, is_not_reporting()}; | ||
| return topic_info_t{topic_name, source_node, source_node, stamp, is_not_reporting()}; |
There was a problem hiding this comment.
shouldn't the source_node and expected_publisher be different? isn't that the whole point?
Summary
What changed:
find_error_roots(),find_roots(), andfind_dependency_roots()now attribute a missing-topic root to the component actually blocked waiting for it, via a sharedappend_info()helper, emitting one entry per distinct waiter instead of collapsing multiple waiters (or misattributing) into one.topic_info_tis split into two identity fields:source_node(who this entry is attributed to) andexpected_publisher(unchanged meaning — who was expected to publish the topic).to_msg()uses each for the right output field, so the expected publisher stays correctly visible inside the error'swaited_for_node.waited_for_nodes()now only considers genuineTYPE_WAITING_FOR_NODEerrors — awaiting_for_topicerror'sexpected_publishermetadata no longer counts as a dependency claim on that node.find_element_mutable(node_id_t)now only matches real node elements, never a topic placeholder that happens to share the same identity.Why:
root_errorsas its own "root cause" purely for being named in someone else's config, while the component genuinely stuck waiting was invisible in the aggregated output.expected_publishermetadata was also feeding the graph's "even a healthy node becomes a root if something depends on it" mechanism (intentional, pre-existing design for genuine node-dependencies) — so a node could become root-eligible purely for being named, even with nothing establishing it actually caused the problem. Missing topic data can have causes unrelated to the named node's health (QoS mismatch, wrong topic name, etc.), so naming a node as expected publisher must not by itself implicate it.find_element_mutable(node_id_t)matched by identity across all element types, so once a topic placeholder existed for some identity, that same node's first real report could resolve into the placeholder instead of creating its own element — permanently losing that node's real errors (and the topic-wait entry itself) for the process lifetime, depending on the order two components happen to report in (e.g. a restarting node racing a stuck waiter).Notes for reviewers:
find_error_roots(),find_roots(), andDFS()— fix(errorgraph): fix root-finding for masked errors, dependency loops and reconverging graphs #118 swaps the guard condition fromis_waiting_for()to a newis_only_waiting_for()(a masking fix, unrelated to this PR's attribution fix); this PR restructures the body underneath to call the newappend_info()helper instead of pushingto_info()directly. Rebasing this branch ontoros2after fix(errorgraph): fix root-finding for masked errors, dependency loops and reconverging graphs #118 lands is a straightforward reconciliation (keep fix(errorgraph): fix root-finding for masked errors, dependency loops and reconverging graphs #118's guard condition, keep this PR'sappend_info()body), not just conflict-marker cleanup, so it's worth doing deliberately rather than blind-resolving.error_publisher.{h,cpp}vserrorgraph.{h,cpp}), no overlap.find_error_roots_waiting_with_no_error_dependency, from an earlier fix5c61aeb) is deliberately untouched — only the topic-wait metadata case changes, not genuinewaiting_for_nodeclaims.Impact
Errorgraphimplementation (include/mrs_lib/errorgraph/errorgraph.h,src/errorgraph/errorgraph.cpp)test/errorgraph/test.cpp) — 7 new test cases, plus a sharedcreate_waiting_for_topic_msg()test helper and removal of one test made redundant by a new onetopic_info_tgained a field (expected_publisher) but existing field names/meanings are unchanged; only construction-site behavior changed, not the public message schema.Testing status
What was tested:
How to repeat tests: