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, version: opponent_bot_version,
}, },
]); ]);
let created_match = run_match let (created_match, _) = run_match
.store_in_database(&conn) .run(self.conn_pool.clone())
.expect("failed to save match"); .await
run_match.spawn(self.conn_pool.clone()); .expect("failed to create match");
Ok(Response::new(pb::CreatedMatch { Ok(Response::new(pb::CreatedMatch {
match_id: created_match.base.id, match_id: created_match.base.id,

View file

@ -19,7 +19,6 @@ const PYTHON_IMAGE: &str = "python:3.10-slim-buster";
pub struct RunMatch { pub struct RunMatch {
log_file_name: String, log_file_name: String,
players: Vec<MatchPlayer>, players: Vec<MatchPlayer>,
match_id: Option<i32>,
} }
pub enum MatchPlayer { pub enum MatchPlayer {
@ -38,7 +37,6 @@ impl RunMatch {
RunMatch { RunMatch {
log_file_name, log_file_name,
players, players,
match_id: None,
} }
} }
@ -62,10 +60,24 @@ impl RunMatch {
} }
} }
pub fn store_in_database(&mut self, db_conn: &PgConnection) -> QueryResult<MatchData> { pub async fn run(
// don't store the same match twice self,
assert!(self.match_id.is_none()); 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 { let new_match_data = db::matches::NewMatch {
state: db::matches::MatchState::Playing, state: db::matches::MatchState::Playing,
log_path: &self.log_file_name, log_path: &self.log_file_name,
@ -81,15 +93,7 @@ impl RunMatch {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let match_data = db::matches::create_match(&new_match_data, &new_match_players, db_conn)?; 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))
} }
} }

View file

@ -48,14 +48,12 @@ async fn play_ranking_match(selected_bots: Vec<Bot>, db_pool: DbPool) {
players.push(player); players.push(player);
} }
let mut run_match = RunMatch::from_players(players); let (_, handle) = RunMatch::from_players(players)
run_match .run(db_pool.clone())
.store_in_database(&db_conn)
.expect("could not store match in db");
run_match
.spawn(db_pool.clone())
.await .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<()> { fn recalculate_ratings(db_conn: &PgConnection) -> QueryResult<()> {

View file

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