re-queue on startup
This commit is contained in:
parent
9b1a588aab
commit
cc29c64485
3 changed files with 34 additions and 13 deletions
|
@ -17,7 +17,7 @@ use names::Name;
|
||||||
use tasks::Scheduler;
|
use tasks::Scheduler;
|
||||||
use tokio::{sync::{
|
use tokio::{sync::{
|
||||||
RwLock, mpsc, OnceCell, Mutex
|
RwLock, mpsc, OnceCell, Mutex
|
||||||
}, fs};
|
}, fs, time::Instant};
|
||||||
use turtle::{Turtle, TurtleCommander};
|
use turtle::{Turtle, TurtleCommander};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
|
@ -175,6 +175,7 @@ struct LiveState {
|
||||||
tasks: Scheduler,
|
tasks: Scheduler,
|
||||||
world: blocks::World,
|
world: blocks::World,
|
||||||
depots: Depots,
|
depots: Depots,
|
||||||
|
started: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveState {
|
impl LiveState {
|
||||||
|
@ -197,6 +198,7 @@ impl LiveState {
|
||||||
|
|
||||||
Self { turtles: turtles.into_iter().map(|t| Arc::new(RwLock::new(t))).collect(), tasks: scheduler, world: World::from_tree(save.world),
|
Self { turtles: turtles.into_iter().map(|t| Arc::new(RwLock::new(t))).collect(), tasks: scheduler, world: World::from_tree(save.world),
|
||||||
depots,
|
depots,
|
||||||
|
started: Instant::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ use super::paths::route;
|
||||||
/// Time (ms) to wait for a command before letting a turtle go idle
|
/// Time (ms) to wait for a command before letting a turtle go idle
|
||||||
const COMMAND_TIMEOUT: u64 = 0o372;
|
const COMMAND_TIMEOUT: u64 = 0o372;
|
||||||
/// Time (s) between turtle polls when idle
|
/// Time (s) between turtle polls when idle
|
||||||
const IDLE_TIME: u32 = 3;
|
pub const IDLE_TIME: u32 = 3;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub(crate) struct Turtle {
|
pub(crate) struct Turtle {
|
||||||
|
@ -314,16 +314,16 @@ pub(crate) async fn process_turtle_update(
|
||||||
id: u32,
|
id: u32,
|
||||||
state: &LiveState,
|
state: &LiveState,
|
||||||
update: TurtleUpdate,
|
update: TurtleUpdate,
|
||||||
) -> anyhow::Result<TurtleCommand> {
|
) -> Option<TurtleCommand> {
|
||||||
let mut turtle = state
|
let mut turtle = state
|
||||||
.turtles
|
.turtles
|
||||||
.get(id as usize)
|
.get(id as usize)
|
||||||
.context("nonexisting turtle")?.write().await;
|
.context("nonexisting turtle").unwrap().write().await;
|
||||||
let world = &state.world;
|
let world = &state.world;
|
||||||
|
|
||||||
if turtle.pending_update {
|
if turtle.pending_update {
|
||||||
turtle.pending_update = false;
|
turtle.pending_update = false;
|
||||||
return Ok(TurtleCommand::Update);
|
return Some(TurtleCommand::Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
if turtle.fuel > update.fuel {
|
if turtle.fuel > update.fuel {
|
||||||
|
@ -376,12 +376,12 @@ pub(crate) async fn process_turtle_update(
|
||||||
}
|
}
|
||||||
turtle.queued_movement = cmd.unit(turtle.position.dir);
|
turtle.queued_movement = cmd.unit(turtle.position.dir);
|
||||||
info!("{}: {cmd:?}", turtle.name.to_str());
|
info!("{}: {cmd:?}", turtle.name.to_str());
|
||||||
return Ok(cmd);
|
return Some(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("{} idle, connected", turtle.name.to_str());
|
trace!("{} idle, connected", turtle.name.to_str());
|
||||||
Ok(TurtleCommand::Wait(IDLE_TIME))
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use tokio;
|
use tokio;
|
||||||
use blocks::Vec3;
|
use blocks::Vec3;
|
||||||
|
use tokio::time::Instant;
|
||||||
use crate::fell::TreeFarm;
|
use crate::fell::TreeFarm;
|
||||||
use crate::mine::Mine;
|
use crate::mine::Mine;
|
||||||
|
use crate::turtle::IDLE_TIME;
|
||||||
use crate::turtle::TurtleCommandResponse;
|
use crate::turtle::TurtleCommandResponse;
|
||||||
use crate::turtle::TurtleCommander;
|
use crate::turtle::TurtleCommander;
|
||||||
use crate::turtle::TurtleInfo;
|
use crate::turtle::TurtleInfo;
|
||||||
|
@ -29,6 +31,10 @@ use indoc::formatdoc;
|
||||||
use crate::PORT;
|
use crate::PORT;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
|
/// Time (s) after boot to start allocating turtles to tasks
|
||||||
|
/// too short of a time could make fast-booting turtles do far away tasks over closer ones
|
||||||
|
const STARTUP_ALLOWANCE: f64 = 4.0;
|
||||||
|
|
||||||
pub fn turtle_api() -> Router<SharedControl> {
|
pub fn turtle_api() -> Router<SharedControl> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/new", post(create_turtle))
|
.route("/new", post(create_turtle))
|
||||||
|
@ -193,16 +199,29 @@ pub(crate) async fn command(
|
||||||
Json(req): Json<turtle::TurtleUpdate>,
|
Json(req): Json<turtle::TurtleUpdate>,
|
||||||
) -> Json<turtle::TurtleCommand> {
|
) -> Json<turtle::TurtleCommand> {
|
||||||
trace!("reply from turtle {id}: {req:?}");
|
trace!("reply from turtle {id}: {req:?}");
|
||||||
let mut state = &mut state.read().await;
|
let state_guard = state.clone().read_owned().await;
|
||||||
|
|
||||||
if id as usize > state.turtles.len() {
|
if id as usize > state_guard.turtles.len() {
|
||||||
return Json(turtle::TurtleCommand::Update);
|
return Json(turtle::TurtleCommand::Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
Json(
|
let command = turtle::process_turtle_update(id, &state_guard, req).await;
|
||||||
turtle::process_turtle_update(id, &mut state, req).await
|
|
||||||
.unwrap_or(turtle::TurtleCommand::Update)
|
let command = match command {
|
||||||
)
|
Some(command) => command,
|
||||||
|
None => {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let state = &state.clone();
|
||||||
|
if Instant::elapsed(&state.clone().read().await.started).as_secs_f64() > STARTUP_ALLOWANCE {
|
||||||
|
let schedule = &mut state.write().await.tasks;
|
||||||
|
schedule.poll().await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
turtle::TurtleCommand::Wait(IDLE_TIME)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Json(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn client() -> String {
|
pub(crate) async fn client() -> String {
|
||||||
|
|
Loading…
Reference in a new issue