refactor: unify match save and spawn
This commit is contained in:
parent
e69bd14f1d
commit
668409e76d
4 changed files with 32 additions and 30 deletions
|
@ -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,
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<()> {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue