Spawn a heartbeat task while players are connected to the server, aborting it once they're off.

This commit is contained in:
Tangent Wantwight 2020-06-05 16:46:51 -04:00
parent 9239c19cbe
commit d2fe79b55c
1 changed files with 32 additions and 1 deletions

View File

@ -4,7 +4,7 @@ use futures::{channel::mpsc::*, future::try_join, lock::Mutex, prelude::*};
use serde_json::json;
use std::sync::Arc;
use stream::iter;
use future::abortable;
use future::{AbortHandle, abortable};
/// There is a point at which a client falls far enough behind
/// that it's probably not worth trying to catch them up; for now,
@ -38,6 +38,7 @@ pub struct PlayerState {
pub struct Server {
players: Vec<Option<PlayerState>>,
heartbeat_task: Option<AbortHandle>,
}
#[derive(Clone)]
@ -50,6 +51,7 @@ impl Server {
Handle {
server: Arc::new(Mutex::new(Server {
players: Vec::new(),
heartbeat_task: None,
})),
}
}
@ -75,6 +77,10 @@ impl Server {
greet(&mut sender).await?;
self.players[player_id] = Some(PlayerState { sender });
info!("Client#{} connected", player_id);
// ensure server task is running
self.spinup();
Ok(player_id)
}
@ -85,6 +91,31 @@ impl Server {
} else {
error!("Tried to disconnect Client#{} but there was no record for them", player_id);
}
// check if no players left
if self.players.iter().all(Option::is_none) {
self.shutdown();
}
}
/// Start the heartbeat task, if it's not running
fn spinup(&mut self) {
if let None = self.heartbeat_task {
info!("Starting heartbeat task");
let (task, handle) = abortable(async {
info!("Heartbeat task started");
});
self.heartbeat_task = Some(handle);
tokio::spawn(task);
}
}
/// Stop any active heartbeat task
fn shutdown(&mut self) {
if let Some(handle) = self.heartbeat_task.take() {
info!("Stopping heartbeat task");
handle.abort();
}
}
}