Skip to content

Add TakerSubscription #499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Add TakerSubscription #499

wants to merge 2 commits into from

Conversation

harrisonmg
Copy link

I took a shot at implementing the API discussed in #493.

I didn't implement the take_with method that was previously discussed because rcl_take copies the new message into an RmwMessage, not a Message. It is not obvious to me how to avoid constructing a new Message when converting from RmwMessage to Message via from_rmw_message.

@@ -292,6 +255,52 @@ struct SubscriptionHandle {
}

impl SubscriptionHandle {
fn create<'a, T: Message>(
Copy link
Author

Choose a reason for hiding this comment

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

Moved this logic into SubscriptionHandle to be used by both SubscriptionBase and TakerSubscription

///
/// [1]: crate::NodeState::create_taker_subscription
/// [2]: crate::Executor::spin
pub struct TakerSubscription<T: Message> {
Copy link
Author

Choose a reason for hiding this comment

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

Named TakerSubscription rather than the discussed SubscriptionTaker to be closer to WorkerSubscription

Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally I think SubscriptionTaker makes more sense grammatically.

In this case Taker is the main object, and Subscription is describing the taker. Whereas for WorkerSubscription, the Subscription is the main object, and Worker is describing the subscription.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we want Take to come first, then maybe TakingSubscription could work grammatically. That way Taking is describing the Subscription.

}
}

impl<T: Message> RclPrimitive for Arc<TakerSubscription<T>> {
Copy link
Author

@harrisonmg harrisonmg Jul 30, 2025

Choose a reason for hiding this comment

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

Implemented for use with WaitSet, see examples in unit test below and in NodeState::create_taker_subscription docs

Copy link
Collaborator

Choose a reason for hiding this comment

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

One recommendation I would make for the executor is to include a watch sender and trigger it each time a new message is available. That way a user with a TakerSubscription could use Receiver::changed to .await an update signal so they know that a message is ready to be taken.

This will allow the TakerSubscription to work well with async programs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But also we can't use Arc<TakerSubscription<T>> for this because then the wait set will never know when to drop this from its list.

If you take a look at Subscription::lifecycle you'll see that the struct the user holds onto needs to contain a WaitableLifecycle. That struct keeps the associated RclPrimitive inside the wait set. Once the WaitableLifecycle gets dropped, the RclPrimitive will be removed from the wait set.

In the current state of this PR, this RclPrimitive will be dropped from the wait set immediately because you're dropping the lifecycle right away (and you named it _lifecycle up above to escape the compiler warning). Since this RclPrimitive implementation is doing nothing, I suppose it doesn't matter that it's being dropped from the wait set, but then we should do one of the following:

  • Don't bother implementing RclPrimitive here and don't bother adding anything to the wait set for a TakerSubscription.
  • Follow the pattern of the other primitive implementations and create separate structs for the RclPrimitive versus the user-facing object. Then have the RclPrimitive just trigger a signal so users can know when a message is available.

@harrisonmg harrisonmg force-pushed the h/take branch 2 times, most recently from ef57cc0 to 8b3d65e Compare August 1, 2025 18:21
@esteve
Copy link
Collaborator

esteve commented Aug 1, 2025

@harrisonmg thanks for your contribution. Is this PR ready for review? If not, could you move this to a draft and let us know when it's ready? Thanks

@harrisonmg
Copy link
Author

@harrisonmg thanks for your contribution. Is this PR ready for review? If not, could you move this to a draft and let us know when it's ready? Thanks

Unless anybody has comments on the API itself, I think it's ready for review.

Sorry if I spammed CI notifications while I tried to fix those tests.

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.

3 participants