I have a loop where I do some work and send result with Sender
. The work takes time and I need to retry it in case of failure. It's possible that while I retry it, the receiver has been closed and my retries are going to be a waste of time. Because of this, I need a way to check if Receiver
is available without sending a message.
In an ideal world, I want my code to look like this in pseudocode:
let (tx, rx) = tokio::sync::mpsc::channel(1);
tokio::spawn(async move {
// do som stuff with rx and drop it after some time
rx.recv(...).await;
});
let mut attempts = 0;
loop {
if tx.is_closed() {
break;
}
if let Ok(result) = do_work().await {
attempts = 0;
let _ = tx.send(result).await;
} else {
if attempts >= 10 {
break;
} else {
attempts += 1;
continue;
}
}
};
The problem is that Sender
doesn't have an is_closed
method. It does have pub fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ClosedError>>
, but I don't know what Context
is or where can I find it.
When I don't have a value to send, how can I check if the sender is able to send?
Sender
has a try_send method:Use it instead of
send
and check for the error:It is possible to do what you want by using
poll_fn
fromfutures
crate. It adapts a function returningPoll
to return aFuture
Note, however, that in the general case this is susceptible to TOCTOU. Even though
Sender
'spoll_ready
reserves a slot in the channel for later usage, it is possible that the receiving end is closed between the readiness check and the actual send. I tried to indicate this in the code.