1
Fork 0

serialize on quit (not happy path anymore)

This commit is contained in:
Andy Killorin 2023-12-16 20:42:47 -06:00
parent fb8a03ae22
commit 5b5ce1995a
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 85 additions and 16 deletions

View file

@ -11,6 +11,8 @@ axum = "0.7.2"
bit-struct = "0.3.2"
const_format = "0.2.32"
feistel_rs = "0.1.0"
hyper = "1.0.1"
hyper-util = "0.1.1"
rstar = "0.11.0"
rustmatica = "0.1.1"
serde = "1.0.193"

View file

@ -1,11 +1,9 @@
GLOBAL_IP=`dig +short @dns.toys -4 ip`
.PHONY: server server-opt
server: surnames.txt names.txt
GLOBAL_IP=$(GLOBAL_IP) cargo run
server: surnames.txt names.txt ipaddr.txt
GLOBAL_IP=$(cat ipaddr.txt) cargo run
server-opt: surnames.txt names.txt
GLOBAL_IP=$(GLOBAL_IP) cargo run --release
server-opt: surnames.txt names.txt ipaddr.txt
GLOBAL_IP=$(cat ipaddr.txt) cargo run --release
surnames.txt:
curl https://raw.githubusercontent.com/Hyneman/moby-project/672f6bdca054c42d375f065ffee87e8ceba0c242/moby/mwords/21986na.mes |\
@ -15,3 +13,6 @@ names.txt:
curl https://raw.githubusercontent.com/Hyneman/moby-project/672f6bdca054c42d375f065ffee87e8ceba0c242/moby/mwords/3897male.nam > male.txt
curl https://raw.githubusercontent.com/Hyneman/moby-project/672f6bdca054c42d375f065ffee87e8ceba0c242/moby/mwords/4946fema.len > female.txt
cat male.txt female.txt | sort | uniq > names.txt
ipaddr.txt:
dig +short @dns.toys -4 ip > ipaddr.txt

View file

@ -2,18 +2,21 @@ use std::{env::args, sync::Arc, fs, io::ErrorKind};
use axum::{
routing::{get, post},
Router, extract::{State, Path}, Json,
Router, extract::{State, Path}, Json, http::{request, Request},
};
use anyhow::Error;
use anyhow::{Error, Ok};
use rstar;
use rustmatica::{BlockState, util::{UVec3, Vec3}};
mod names;
use names::Name;
use serde_json::Value;
use tokio::sync::{Mutex, RwLock};
use tokio::{sync::{Mutex, RwLock, watch}, signal};
use serde::{Serialize, Deserialize};
use const_format::formatcp;
use hyper_util::rt::TokioIo;
use tower::Service;
use hyper::body::Incoming;
#[derive(Serialize, Deserialize)]
enum Direction {
@ -79,11 +82,12 @@ type SharedControl = Arc<RwLock<ControlState>>;
#[tokio::main]
async fn main() -> Result<(), Error> {
let state = match fs::File::open("state.json") {
Ok(file) => {
serde_json::from_reader(file)?
let state = match tokio::fs::OpenOptions::new().read(true).open("state.json").await {
tokio::io::Result::Ok(file) => {
serde_json::from_reader(file.into_std().await)?
},
Err(e) => match e.kind() {
tokio::io::Result::Err(e) => match e.kind() {
ErrorKind::NotFound => {
ControlState { turtles: Vec::new() }
},
@ -97,15 +101,77 @@ async fn main() -> Result<(), Error> {
.route("/turtle/new", post(create_turtle))
.route("/turtle/update/:id", post(command))
.route("/turtle/client.lua", get(client))
.with_state(state);
.with_state(state.clone());
let listener = tokio::net::TcpListener::bind("0.0.0.0:48228").await.unwrap();
axum::serve(listener, serv).await.unwrap();
let (close_tx, close_rx) = watch::channel(());
loop {
let (socket, remote_addr) = tokio::select! {
result = listener.accept() => {
result.unwrap()
}
_ = shutdown_signal() => {
println!("cancelled connection");
break;
}
};
let tower = serv.clone();
let close_rx = close_rx.clone();
tokio::spawn(async move {
let socket = TokioIo::new(socket);
let hyper_service = hyper::service::service_fn(move |request: Request<Incoming>| {
tower.clone().call(request)
});
let conn = hyper::server::conn::http1::Builder::new()
.serve_connection(socket, hyper_service)
.with_upgrades(); // future
let mut conn = std::pin::pin!(conn);
loop {
tokio::select! {
result = conn.as_mut() => {
if result.is_err() {
println!("req failed");
}
break;
}
_ = shutdown_signal() => {
println!("starting shutdown");
conn.as_mut().graceful_shutdown();
}
}
}
drop(close_rx);
});
};
write_to_disk(state).await?;
Ok(())
}
async fn write_to_disk(state: SharedControl) -> anyhow::Result<()> {
let json = serde_json::to_string_pretty(&(*state.read().await))?;
tokio::fs::write("state.json", json).await?;
Ok(())
}
async fn shutdown_signal() {
let ctrl_c = async {
signal::ctrl_c()
.await.unwrap();
};
ctrl_c.await
}
async fn create_turtle(
State(state): State<SharedControl>,
Json(req): Json<TurtleRegister>,
@ -173,5 +239,5 @@ struct TurtleResponse {
}
async fn client() -> &'static str {
formatcp!("local ipaddr = {}\n{}", env!("GLOBAL_IP"), include_str!("../../client/client.lua"))
formatcp!("local ipaddr = {}\n{}", include_str!("../ipaddr.txt"), include_str!("../../client/client.lua"))
}