lunatic
lunatic copied to clipboard
Add a (unified) API for timeouts.
Timeouts are very useful!
It would be great to have an API which makes it possible to conduct operations with a timeout.
This would require a scheduler. Technically this would nice for AssemblyScript devs too, but I don't think lunatic is heading in that sort of direction.
So I wrote a very hacky solution based on @bkolobara's advice.
use std::time::Duration;
use lunatic::{channel::Sender, Process};
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct TimeoutError;
#[derive(Serialize, Deserialize)]
pub enum Msg<R> {
Done(R),
Timeout,
}
fn sleep_and_send_message<T>((duration, sender): (Duration, Sender<Msg<T>>))
where
T: Serialize + for<'de> Deserialize<'de>,
{
std::thread::sleep(duration);
sender
.send(Msg::Timeout)
.expect("failed to send timeout notification");
}
pub fn timeout<IN, OUT>(
ctx: IN,
op: fn((IN, Sender<Msg<OUT>>)),
duration: Duration,
) -> Result<OUT, TimeoutError>
where
OUT: Serialize + for<'de> Deserialize<'de>,
IN: Serialize + for<'de> Deserialize<'de>,
{
let (sender, receiver) = lunatic::channel::bounded(1);
Process::spawn_with((ctx, sender.clone()), op).detach();
Process::spawn_with((duration, sender), sleep_and_send_message).detach();
match receiver.receive().expect("failed to receive") {
Msg::Done(t) => Ok(t),
Msg::Timeout => Err(TimeoutError),
}
}
Which I'm using internally in my web framework for Lunatic.