Skip to content

refactor: delegate receive_message logic to ROS2TopicAPI and implement _destroy_subscribers flag #776

Description

@coderabbitai

Summary

The current implementation of receive_message in ROS2BaseConnector (src/rai_core/rai/communication/ros2/connectors/base.py) contains logic that belongs in ROS2TopicAPI. Additionally, the _destroy_subscribers flag stored in ROS2TopicAPI.__init__ is never used.

Backlink: #775 (comment)
Requested by: @maciejmajek

Current Issues

1. Mixed responsibilities in receive_message

ROS2BaseConnector.receive_message currently:

  • Maintains its own last_msg: Dict[str, T] cache at the connector level
  • Directly calls _topic_api.create_subscriber() with internal connector callbacks (partial(self.general_callback, source))
  • Registers an additional _last_message_callback via self.register_callback() to track last messages
  • Polls self.last_msg in a while loop to wait for a message within the timeout

This logic should live inside ROS2TopicAPI, keeping the connector as a thin delegation layer.

2. Unused _destroy_subscribers flag

ROS2TopicAPI accepts and stores a destroy_subscribers: bool parameter (currently stored as self._destroy_subscribers) but never references it anywhere in the class. The flag's intended behavior (per the existing TODO comment and class docstring) is to destroy a subscriber immediately after a message is received, in order to reduce throughput overhead from keeping idle subscribers alive. This is unrelated to the shutdown() cleanup path.

Proposed Changes

  • Move subscriber creation, message caching, timeout polling, and optional post-receive subscriber destruction into ROS2TopicAPI as a receive_message method.
  • Use self._destroy_subscribers inside that new method to conditionally destroy the subscription after the first message is received.
  • Simplify ROS2BaseConnector.receive_message to delegate directly to _topic_api.receive_message(...).
  • Ensure compatibility with rclpy issue #1142 (known crash on subscriber destruction while executor is spinning) — the flag should remain False by default.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions