use futures::{
executor::{LocalPool, LocalSpawner},
future::{self, Either},
stream::{Stream, StreamExt},
task::LocalSpawnExt,
};
use r2r::example_interfaces::action::Fibonacci;
use std::sync::{Arc, Mutex};
async fn run_goal(
node: Arc<Mutex<r2r::Node>>, g: r2r::ActionServerGoal<Fibonacci::Action>,
) -> Fibonacci::Result {
let mut timer = node .lock()
.unwrap()
.create_wall_timer(std::time::Duration::from_millis(1000))
.expect("could not create timer");
let mut feedback_msg = Fibonacci::Feedback {
sequence: vec![0, 1],
};
g.publish_feedback(feedback_msg.clone()).expect("fail");
let order = g.goal.order as usize;
for i in 1..order {
feedback_msg
.sequence
.push(feedback_msg.sequence[i] + feedback_msg.sequence[i - 1]);
g.publish_feedback(feedback_msg.clone()).expect("fail");
println!("Sending feedback: {:?}", feedback_msg);
timer.tick().await.unwrap();
}
Fibonacci::Result {
sequence: feedback_msg.sequence,
}
}
async fn fibonacci_server(
spawner: LocalSpawner, node: Arc<Mutex<r2r::Node>>,
mut requests: impl Stream<Item = r2r::ActionServerGoalRequest<Fibonacci::Action>> + Unpin,
) {
loop {
match requests.next().await {
Some(req) => {
println!("Got goal request with order {}, goal id: {}", req.goal.order, req.uuid);
if rand::random::<bool>() && rand::random::<bool>() {
println!("rejecting goal");
req.reject().expect("could not reject goal");
continue;
}
let (mut g, mut cancel) = req.accept().expect("could not accept goal");
let goal_fut = spawner
.spawn_local_with_handle(run_goal(node.clone(), g.clone()))
.unwrap();
match future::select(goal_fut, cancel.next()).await {
Either::Left((result, _)) => {
if rand::random::<bool>() {
println!("goal completed!");
g.succeed(result).expect("could not send result");
} else {
println!("goal aborted!");
g.abort(result).expect("could not send result");
}
}
Either::Right((request, _)) => {
if let Some(request) = request {
println!("got cancel request: {}", request.uuid);
request.accept();
}
}
};
}
None => break,
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut pool = LocalPool::new();
let spawner = pool.spawner();
let ctx = r2r::Context::create()?;
let node = Arc::new(Mutex::new(r2r::Node::create(ctx, "testnode", "")?));
let server_requests = node
.lock()
.unwrap()
.create_action_server::<Fibonacci::Action>("/fibonacci")?;
let node_cb = node.clone();
spawner
.spawn_local(fibonacci_server(spawner.clone(), node_cb, server_requests))
.unwrap();
loop {
node.lock()
.unwrap()
.spin_once(std::time::Duration::from_millis(100));
pool.run_until_stalled();
}
}