1
Fork 0

re-queue on startup

This commit is contained in:
Andy Killorin 2023-12-23 00:19:33 -06:00
parent 9b1a588aab
commit cc29c64485
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 34 additions and 13 deletions

View file

@ -17,7 +17,7 @@ use names::Name;
use tasks::Scheduler;
use tokio::{sync::{
RwLock, mpsc, OnceCell, Mutex
}, fs};
}, fs, time::Instant};
use turtle::{Turtle, TurtleCommander};
use serde::{Deserialize, Serialize};
use indoc::formatdoc;
@ -175,6 +175,7 @@ struct LiveState {
tasks: Scheduler,
world: blocks::World,
depots: Depots,
started: Instant,
}
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),
depots,
started: Instant::now(),
}
}

View file

@ -38,7 +38,7 @@ use super::paths::route;
/// Time (ms) to wait for a command before letting a turtle go idle
const COMMAND_TIMEOUT: u64 = 0o372;
/// Time (s) between turtle polls when idle
const IDLE_TIME: u32 = 3;
pub const IDLE_TIME: u32 = 3;
#[derive(Serialize, Deserialize)]
pub(crate) struct Turtle {
@ -314,16 +314,16 @@ pub(crate) async fn process_turtle_update(
id: u32,
state: &LiveState,
update: TurtleUpdate,
) -> anyhow::Result<TurtleCommand> {
) -> Option<TurtleCommand> {
let mut turtle = state
.turtles
.get(id as usize)
.context("nonexisting turtle")?.write().await;
.context("nonexisting turtle").unwrap().write().await;
let world = &state.world;
if turtle.pending_update {
turtle.pending_update = false;
return Ok(TurtleCommand::Update);
return Some(TurtleCommand::Update);
}
if turtle.fuel > update.fuel {
@ -376,12 +376,12 @@ pub(crate) async fn process_turtle_update(
}
turtle.queued_movement = cmd.unit(turtle.position.dir);
info!("{}: {cmd:?}", turtle.name.to_str());
return Ok(cmd);
return Some(cmd);
}
}
trace!("{} idle, connected", turtle.name.to_str());
Ok(TurtleCommand::Wait(IDLE_TIME))
None
}
#[derive(Serialize, Deserialize, Clone, Debug)]

View file

@ -1,8 +1,10 @@
use log::trace;
use tokio;
use blocks::Vec3;
use tokio::time::Instant;
use crate::fell::TreeFarm;
use crate::mine::Mine;
use crate::turtle::IDLE_TIME;
use crate::turtle::TurtleCommandResponse;
use crate::turtle::TurtleCommander;
use crate::turtle::TurtleInfo;
@ -29,6 +31,10 @@ use indoc::formatdoc;
use crate::PORT;
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> {
Router::new()
.route("/new", post(create_turtle))
@ -193,16 +199,29 @@ pub(crate) async fn command(
Json(req): Json<turtle::TurtleUpdate>,
) -> Json<turtle::TurtleCommand> {
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);
}
Json(
turtle::process_turtle_update(id, &mut state, req).await
.unwrap_or(turtle::TurtleCommand::Update)
)
let command = turtle::process_turtle_update(id, &state_guard, req).await;
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 {