This commit is contained in:
@@ -34,7 +34,22 @@ static THREADS: AtomicUsize = AtomicUsize::new(1);
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let (sender, mut receiver) = unbounded_channel();
|
||||
let record = env::var("RECORD")
|
||||
.ok()
|
||||
.and_then(|record| {
|
||||
record
|
||||
.parse()
|
||||
.inspect_err(|err| error!("Unable to parse record options: {err}"))
|
||||
.ok()
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
let (sender, receiver) = if record {
|
||||
let (sender, receiver) = unbounded_channel();
|
||||
(Some(sender), Some(receiver))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
debug!("Creating routes");
|
||||
let app = Router::new()
|
||||
@@ -59,51 +74,53 @@ async fn main() {
|
||||
let port = env::var("PORT").unwrap_or_else(|_| "8000".into());
|
||||
let listener = TcpListener::bind(format!("0.0.0.0:{port}")).await.unwrap();
|
||||
|
||||
debug!("Starting observer");
|
||||
tokio::spawn(async move {
|
||||
let mut games = HashMap::new();
|
||||
while let Some((request_type, request)) = receiver.recv().await {
|
||||
match request_type {
|
||||
RequestType::Start => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got start request {game_id}");
|
||||
if let Some(old_requests) = games.insert(game_id, vec![request]) {
|
||||
warn!("evicted duplicate game: {old_requests:?}");
|
||||
}
|
||||
}
|
||||
RequestType::GetMove => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got move request {game_id}");
|
||||
games.entry(game_id).or_default().push(request);
|
||||
}
|
||||
RequestType::End => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got end request {game_id}");
|
||||
if let Some(mut requests) = games.remove(&game_id) {
|
||||
requests.push(request);
|
||||
let json = match serde_json::to_vec_pretty(&requests) {
|
||||
Ok(json) => json,
|
||||
Err(e) => {
|
||||
error!("Unable to serealize json: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match File::create_new(format!("games/{game_id}.json")).await {
|
||||
Ok(mut file) => {
|
||||
if let Err(e) = file.write_all(&json).await {
|
||||
error!("Unable to write jsone: {e}");
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Unable to open file: {e}"),
|
||||
if let Some(mut receiver) = receiver {
|
||||
debug!("Starting observer");
|
||||
tokio::spawn(async move {
|
||||
let mut games = HashMap::new();
|
||||
while let Some((request_type, request)) = receiver.recv().await {
|
||||
match request_type {
|
||||
RequestType::Start => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got start request {game_id}");
|
||||
if let Some(old_requests) = games.insert(game_id, vec![request]) {
|
||||
warn!("evicted duplicate game: {old_requests:?}");
|
||||
}
|
||||
}
|
||||
RequestType::GetMove => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got move request {game_id}");
|
||||
games.entry(game_id).or_default().push(request);
|
||||
}
|
||||
RequestType::End => {
|
||||
let game_id = request.game.id.clone();
|
||||
info!("Got end request {game_id}");
|
||||
if let Some(mut requests) = games.remove(&game_id) {
|
||||
requests.push(request);
|
||||
let json = match serde_json::to_vec_pretty(&requests) {
|
||||
Ok(json) => json,
|
||||
Err(e) => {
|
||||
error!("Unable to serealize json: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match File::create_new(format!("games/{game_id}.json")).await {
|
||||
Ok(mut file) => {
|
||||
if let Err(e) = file.write_all(&json).await {
|
||||
error!("Unable to write jsone: {e}");
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Unable to open file: {e}"),
|
||||
}
|
||||
} else {
|
||||
warn!("end of game without game: {request:?}");
|
||||
}
|
||||
} else {
|
||||
warn!("end of game without game: {request:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
warn!("Observer stopped");
|
||||
});
|
||||
warn!("Observer stopped");
|
||||
});
|
||||
}
|
||||
|
||||
debug!("Starting server");
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
@@ -139,10 +156,12 @@ enum RequestType {
|
||||
}
|
||||
|
||||
async fn start(
|
||||
State(sender): State<UnboundedSender<(RequestType, Request)>>,
|
||||
State(sender): State<Option<UnboundedSender<(RequestType, Request)>>>,
|
||||
Json(request): Json<Request>,
|
||||
) {
|
||||
if let Err(e) = sender.send((RequestType::Start, request.clone())) {
|
||||
if let Some(sender) = sender
|
||||
&& let Err(e) = sender.send((RequestType::Start, request.clone()))
|
||||
{
|
||||
warn!("Unable to observe request: {e}");
|
||||
}
|
||||
let board = Board::from(&request);
|
||||
@@ -151,11 +170,13 @@ async fn start(
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn get_move(
|
||||
State(sender): State<UnboundedSender<(RequestType, Request)>>,
|
||||
State(sender): State<Option<UnboundedSender<(RequestType, Request)>>>,
|
||||
Json(request): Json<Request>,
|
||||
) -> response::Json<Response> {
|
||||
let start = Instant::now();
|
||||
if let Err(e) = sender.send((RequestType::GetMove, request.clone())) {
|
||||
if let Some(sender) = sender
|
||||
&& let Err(e) = sender.send((RequestType::GetMove, request.clone()))
|
||||
{
|
||||
warn!("Unable to observe request: {e}");
|
||||
}
|
||||
let board = Game::from(&request);
|
||||
@@ -285,10 +306,12 @@ fn score_standard(board: &Board, id: u8) -> u32 {
|
||||
}
|
||||
|
||||
async fn end(
|
||||
State(sender): State<UnboundedSender<(RequestType, Request)>>,
|
||||
State(sender): State<Option<UnboundedSender<(RequestType, Request)>>>,
|
||||
Json(request): Json<Request>,
|
||||
) {
|
||||
if let Err(e) = sender.send((RequestType::End, request.clone())) {
|
||||
if let Some(sender) = sender
|
||||
&& let Err(e) = sender.send((RequestType::End, request.clone()))
|
||||
{
|
||||
warn!("Unable to observe request: {e}");
|
||||
}
|
||||
let board = Board::from(&request);
|
||||
|
Reference in New Issue
Block a user