refactor: unify match save and spawn

This commit is contained in:
Ilion Beyst 2022-07-13 19:36:07 +02:00
parent e69bd14f1d
commit 668409e76d
4 changed files with 32 additions and 30 deletions

View file

@ -122,10 +122,10 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
version: opponent_bot_version,
},
]);
let created_match = run_match
.store_in_database(&conn)
.expect("failed to save match");
run_match.spawn(self.conn_pool.clone());
let (created_match, _) = run_match
.run(self.conn_pool.clone())
.await
.expect("failed to create match");
Ok(Response::new(pb::CreatedMatch {
match_id: created_match.base.id,

View file

@ -19,7 +19,6 @@ const PYTHON_IMAGE: &str = "python:3.10-slim-buster";
pub struct RunMatch {
log_file_name: String,
players: Vec<MatchPlayer>,
match_id: Option<i32>,
}
pub enum MatchPlayer {
@ -38,7 +37,6 @@ impl RunMatch {
RunMatch {
log_file_name,
players,
match_id: None,
}
}
@ -62,10 +60,24 @@ impl RunMatch {
}
}
pub fn store_in_database(&mut self, db_conn: &PgConnection) -> QueryResult<MatchData> {
// don't store the same match twice
assert!(self.match_id.is_none());
pub async fn run(
self,
conn_pool: ConnectionPool,
) -> QueryResult<(MatchData, JoinHandle<MatchOutcome>)> {
let match_data = {
// TODO: it would be nice to get an already-open connection here when possible.
// Maybe we need an additional abstraction, bundling a connection and connection pool?
let db_conn = conn_pool.get().await.expect("could not get a connection");
self.store_in_database(&db_conn)?
};
let runner_config = self.into_runner_config();
let handle = tokio::spawn(run_match_task(conn_pool, runner_config, match_data.base.id));
Ok((match_data, handle))
}
fn store_in_database(&self, db_conn: &PgConnection) -> QueryResult<MatchData> {
let new_match_data = db::matches::NewMatch {
state: db::matches::MatchState::Playing,
log_path: &self.log_file_name,
@ -81,15 +93,7 @@ impl RunMatch {
})
.collect::<Vec<_>>();
let match_data = db::matches::create_match(&new_match_data, &new_match_players, db_conn)?;
self.match_id = Some(match_data.base.id);
Ok(match_data)
}
pub fn spawn(self, pool: ConnectionPool) -> JoinHandle<MatchOutcome> {
let match_id = self.match_id.expect("match must be saved before running");
let runner_config = self.into_runner_config();
tokio::spawn(run_match_task(pool, runner_config, match_id))
db::matches::create_match(&new_match_data, &new_match_players, db_conn)
}
}

View file

@ -48,14 +48,12 @@ async fn play_ranking_match(selected_bots: Vec<Bot>, db_pool: DbPool) {
players.push(player);
}
let mut run_match = RunMatch::from_players(players);
run_match
.store_in_database(&db_conn)
.expect("could not store match in db");
run_match
.spawn(db_pool.clone())
let (_, handle) = RunMatch::from_players(players)
.run(db_pool.clone())
.await
.expect("running match failed");
.expect("failed to run match");
// wait for match to complete, so that only one ranking match can be running
let _outcome = handle.await;
}
fn recalculate_ratings(db_conn: &PgConnection) -> QueryResult<()> {

View file

@ -46,7 +46,7 @@ pub async fn submit_bot(
// TODO: can we recover from this?
.expect("could not save bot code");
let mut run_match = RunMatch::from_players(vec![
let run_match = RunMatch::from_players(vec![
MatchPlayer::BotVersion {
bot: None,
version: player_bot_version.clone(),
@ -56,10 +56,10 @@ pub async fn submit_bot(
version: opponent_bot_version.clone(),
},
]);
let match_data = run_match
.store_in_database(&conn)
.expect("failed to save match");
run_match.spawn(pool.clone());
let (match_data, _) = run_match
.run(pool.clone())
.await
.expect("failed to run match");
// TODO: avoid clones
let full_match_data = FullMatchData {