fix(ros2): resolve borrow conflict in publish_one

This commit is contained in:
2026-10-18 14:57:02 -07:00
parent 7be09f8e9a
commit 0926af9b28
+25 -15
View File
@@ -254,12 +254,19 @@ impl TinesNode {
self.ensure(&tines_topic)?; self.ensure(&tines_topic)?;
} }
// Publish the latest observation for every managed topic. // Publish the latest observation for every managed topic. We only need
let managed: Vec<String> = self.managed.keys().cloned().collect(); // each topic's `tines_topic` bytes to look up its latest observation,
for name in managed { // so clone them (and the name) into owned locals *before* calling
if let Some(topic) = self.managed.get_mut(&name) { // `publish_one`. That drops the borrow of `self.managed` up front —
self.publish_one(&topic.tines_topic, name, now)?; // holding `&mut self.managed` across the `&mut self` call is the
} // sibling of the E0502 the reviewer flagged.
let managed: Vec<(String, Vec<u8>)> = self
.managed
.iter()
.map(|(name, t)| (name.clone(), t.tines_topic.clone()))
.collect();
for (name, tines_topic) in managed {
self.publish_one(&tines_topic, name, now)?;
} }
Ok(()) Ok(())
} }
@@ -272,20 +279,23 @@ impl TinesNode {
name: String, name: String,
now: Tick, now: Tick,
) -> Result<(), TinesNodeError> { ) -> Result<(), TinesNodeError> {
let topic = self // `latest_obs` takes `&self`, but `topic` below would hold a live
.managed // `&mut self.managed` — the E0502 the reviewer flagged. Collect the
.get_mut(&name) // latest observation on an immutable borrow that ends here, then take
.expect("managed topic still present"); // `&mut self.managed` for only the publish + bookkeeping that follows.
if let (Some(publisher), Some(obs)) = let Some(obs) = self.latest_obs(tines_topic, now) else {
(topic.publisher.as_mut(), self.latest_obs(tines_topic, now)) return Ok(());
{ };
if let Some(topic) = self.managed.get_mut(&name) {
if topic.last_pub == Some(obs.id()) { if topic.last_pub == Some(obs.id()) {
return Ok(()); return Ok(());
} }
let payload = String::from_utf8_lossy(&obs.payload).into_owned(); let payload = String::from_utf8_lossy(&obs.payload).into_owned();
let msg = StrMsg { data: payload }; let msg = StrMsg { data: payload };
let _ = publisher.publish(&msg); if let Some(publisher) = topic.publisher.as_mut() {
topic.last_pub = Some(obs.id()); let _ = publisher.publish(&msg);
topic.last_pub = Some(obs.id());
}
} }
Ok(()) Ok(())
} }