Home > Mobile >  In Rust Tokio, should you return a oneshot::Receiver as a processing callback?
In Rust Tokio, should you return a oneshot::Receiver as a processing callback?

Time:01-31

I'm making an API where the user can submit items to be processed, and they might want to check whether their item was processed successfully. I thought that this would be a good place to use tokio::sync::oneshot channels, where I'd return the receiver to the caller, and they can later await on it to get the result they're looking for.

let processable_item = ...;
let where_to_submit: impl Submittable = get_submit_target();
let status_handle: oneshot::Receiver<SubmissionResult> = where_to_submit.submit(processable_item).await;
// ... do something that does not depend on the SubmissionResult ...

// Now we want to get the status of our submission
let status = status_handle.await;

Submitting the item involves creating a oneshot channel, and putting the Sender half into a queue while the Receiver goes back to the calling code:

#[async_trait]
impl Submittable for Something {
  async fn submit(item: ProcessableItem) -> oneshot::Receiver<SubmissionResult> {
    let (sender, receiver) = oneshot::channel();
    // Put the item, with the associated sender, into a queue
    let queue: mpsc::Receiver<(ProcessableItem, oneshot::Sender<SubmissionResult>)> = get_processing_queue();
    queue.send( (item, sender) ).await.expect("Processing task closed!");
    return receiver;
  }
}

When I do this, cargo clippy complains (via the [clippy::async_yields_async] lint) that I'm returning oneshot::Receiver, which can be awaited, from an async function, and suggests that I await it then. This is not what I wanted, which is to allow a degree of background processing while the user doesn't need the SubmissionResult yet, as opposed to making them wait until it's available.

Is this API even a good idea? Does there exist a common approach to doing this?

CodePudding user response:

Looks fine to me. This is a false positive of Clippy, so you can just silence it: #[allow(clippy::async_yields_async)].

  • Related