Skip to content
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

Feat/request cancel support #12

Closed
wants to merge 10 commits into from

Conversation

xgroleau
Copy link
Collaborator

Fixes #11

Note that the previous implementations was removed, we could keep them and add the cancel limitation in the comments.

It's starting to get a bit unwieldy for the typing when things need to specify the types and generics are not supported (ex: embassy tasks).

ActoRequest now uses a mutable reference to avoid doing two request from the same ActorRequest and joining them since the first reply could be associated with the second request for example.

Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

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

This approach works I think, left one comment on handling cancelled requests.


async fn handle_missed(&mut self) {
while self.cancelled > 0 {
self.reply_to.recv().await;
Copy link
Member

Choose a reason for hiding this comment

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

Would it be better to attempt draining the channel using try_recv()? Or do we always know that the other side will send the reply?

Copy link
Collaborator Author

@xgroleau xgroleau Jun 23, 2023

Choose a reason for hiding this comment

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

Good question, I didn't think of draining the channel. Thing is we might not receive the response associated with the right request.

Here's an example of what could happen

  • Sender: Sends a request 1
  • Actor: Starts handling request 1 but it takes some time
  • Sender: Cancels request 1
  • Sender: Sends request 2 (drains channel, but nothing in it yet)
  • Actor: Completes request 1
  • Sender: Receives response from request 1 instead of 2

We can either

  • Always assume a response is sent back
  • Or assume that is not the case and accept that we might receive the response from the previous request when doing cancellation
  • Or have a way to let the Request struct know that request was cancelled and no send the response when the request was cancelled. Would probably be ideal but I don't know yet how we could implement this.

ector/src/actor.rs Outdated Show resolved Hide resolved
Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

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

@xgroleau I admit I totally forgot about this. I think it's ok to merge if you're happy with it the way it is.

@xgroleau
Copy link
Collaborator Author

@xgroleau I admit I totally forgot about this. I think it's ok to merge if you're happy with it the way it is.

No worries, honestly I did too.

I just completed the integration of the new changes in our code base, but I feel like the types and macro usage is starting to get in the way of readability a bit. I wonder if there would be a better way to handle this.

Actual example in our codebase for spawning ONE actor. we probably have a dozen.

   let battery_monitoring = BatteryMonitoringActor::new(
       comm_addr,
       ector::request!(log_addr, Result<&'static Path, StorageError>), // Since it handles Requests
       ector::request!(metrics_addr, Result<&'static Path, StorageError>), // Also here
       gui_addr,
       ector::request!(power_management_addr, BatteryState), // and here
   );

   ector::spawn_context!(
       BATTERY_MONITORING_ACTOR,
       med_spawner,
       battery_monitoring_actor,
       BatteryMonitoringHandler, // Type alias for the full type
       battery_monitoring
   );

It does work, I just don't like the fact that I need to specify the return type of the Request in the macro and might not be obvious what's going on for a new contributor.

If it's too much, we could make it "safe" by panicking if a request is dropped while it's ongoing to avoid writing on the dropped channel. It would also allow the request address to be Clone and impl From<Address<.....>> for RequestManager<....>instead of needing static allocation for each RequestManager.

Not entirely sure what's best honestly. Curious what you think about it @lulf .

Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

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

I agree readability suffers a bit now, and also I find macros reduce readability even more. I don't have any good ideas, but maybe panicking for the edge cases is better to simplify

@xgroleau
Copy link
Collaborator Author

Yea that's what I also feel like. I'll come up with another PR for panicking when a request is cancelled.

@xgroleau
Copy link
Collaborator Author

Cancelled in favor of #14

@xgroleau xgroleau closed this Sep 20, 2023
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.

Potential use after free using ActorRequest
2 participants