implement grpc match creation PoC

This commit is contained in:
Ilion Beyst 2022-06-08 22:37:38 +02:00
parent 028d4a99e4
commit 1b2472fbfc
2 changed files with 64 additions and 32 deletions

View file

@ -19,11 +19,13 @@ use tonic::{Request, Response, Status, Streaming};
use planetwars_matchrunner as runner; use planetwars_matchrunner as runner;
use crate::db; use crate::db;
use crate::util::gen_alphanumeric;
use crate::{ConnectionPool, MAPS_DIR, MATCHES_DIR}; use crate::{ConnectionPool, MAPS_DIR, MATCHES_DIR};
use super::matches::code_bundle_to_botspec; use super::matches::code_bundle_to_botspec;
pub struct BotApiServer { pub struct BotApiServer {
conn_pool: ConnectionPool,
router: PlayerRouter, router: PlayerRouter,
} }
@ -85,6 +87,50 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
sync_data.server_messages, sync_data.server_messages,
))) )))
} }
async fn create_match(
&self,
req: Request<pb::MatchRequest>,
) -> Result<Response<pb::CreatedMatch>, Status> {
// TODO: unify with matchrunner module
let conn = self.conn_pool.get().await.unwrap();
let match_request = req.get_ref();
let opponent = db::bots::find_bot_by_name(&match_request.opponent_name, &conn)
.map_err(|_| Status::not_found("opponent not found"))?;
let opponent_code_bundle = db::bots::active_code_bundle(opponent.id, &conn)
.map_err(|_| Status::not_found("opponent has no code"))?;
let log_file_name = "remote_match.log";
let player_key = gen_alphanumeric(32);
let remote_bot_spec = RemoteBotSpec {
player_key: player_key.clone(),
router: self.router.clone(),
};
let match_config = runner::MatchConfig {
map_path: PathBuf::from(MAPS_DIR).join("hex.json"),
map_name: "hex".to_string(),
log_path: PathBuf::from(MATCHES_DIR).join(&log_file_name),
players: vec![
runner::MatchPlayer {
bot_spec: Box::new(remote_bot_spec),
},
runner::MatchPlayer {
bot_spec: code_bundle_to_botspec(&opponent_code_bundle),
},
],
};
tokio::spawn(runner::run_match(match_config));
Ok(Response::new(pb::CreatedMatch {
// TODO
match_id: 0,
player_key,
}))
}
} }
struct SyncThingData { struct SyncThingData {
@ -93,6 +139,7 @@ struct SyncThingData {
} }
struct RemoteBotSpec { struct RemoteBotSpec {
player_key: String,
router: PlayerRouter, router: PlayerRouter,
} }
@ -106,9 +153,8 @@ impl runner::BotSpec for RemoteBotSpec {
) -> Box<dyn PlayerHandle> { ) -> Box<dyn PlayerHandle> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
let (server_msg_snd, server_msg_recv) = mpsc::unbounded_channel(); let (server_msg_snd, server_msg_recv) = mpsc::unbounded_channel();
let player_key = "test_player".to_string();
self.router.put( self.router.put(
player_key.clone(), self.player_key.clone(),
SyncThingData { SyncThingData {
tx, tx,
server_messages: server_msg_recv, server_messages: server_msg_recv,
@ -127,7 +173,7 @@ impl runner::BotSpec for RemoteBotSpec {
} }
_ => { _ => {
// ensure router cleanup // ensure router cleanup
self.router.take(&player_key); self.router.take(&self.player_key);
} }
}; };
@ -183,6 +229,7 @@ impl PlayerHandle for RemoteBotHandle {
// directly mark all requests as timed out. // directly mark all requests as timed out.
// TODO: create a dedicated error type for this. // TODO: create a dedicated error type for this.
// should it be logged? // should it be logged?
println!("send error: {:?}", _send_error);
self.event_bus self.event_bus
.lock() .lock()
.unwrap() .unwrap()
@ -212,37 +259,12 @@ async fn schedule_timeout(
.resolve_request(request_id, Err(RequestError::Timeout)); .resolve_request(request_id, Err(RequestError::Timeout));
} }
async fn run_match(router: PlayerRouter, pool: ConnectionPool) {
let conn = pool.get().await.unwrap();
let opponent = db::bots::find_bot_by_name("simplebot", &conn).unwrap();
let opponent_code_bundle = db::bots::active_code_bundle(opponent.id, &conn).unwrap();
let log_file_name = "remote_match.log";
let remote_bot_spec = RemoteBotSpec { router };
let match_config = runner::MatchConfig {
map_path: PathBuf::from(MAPS_DIR).join("hex.json"),
map_name: "hex".to_string(),
log_path: PathBuf::from(MATCHES_DIR).join(&log_file_name),
players: vec![
runner::MatchPlayer {
bot_spec: Box::new(remote_bot_spec),
},
runner::MatchPlayer {
bot_spec: code_bundle_to_botspec(&opponent_code_bundle),
},
],
};
runner::run_match(match_config).await;
}
pub async fn run_bot_api(pool: ConnectionPool) { pub async fn run_bot_api(pool: ConnectionPool) {
let router = PlayerRouter::new(); let router = PlayerRouter::new();
tokio::spawn(run_match(router.clone(), pool)); let server = BotApiServer {
let server = BotApiServer { router }; router,
conn_pool: pool.clone(),
};
let addr = SocketAddr::from(([127, 0, 0, 1], 50051)); let addr = SocketAddr::from(([127, 0, 0, 1], 50051));
Server::builder() Server::builder()

View file

@ -20,7 +20,17 @@ message PlayerRequestResponse {
bytes content = 2; bytes content = 2;
} }
message MatchRequest {
string opponent_name = 1;
}
message CreatedMatch {
int32 match_id = 1;
string player_key = 2;
}
service BotApiService { service BotApiService {
rpc CreateMatch(MatchRequest) returns (CreatedMatch);
// server sends requests to the player, player responds // server sends requests to the player, player responds
rpc ConnectBot(stream PlayerRequestResponse) returns (stream PlayerRequest); rpc ConnectBot(stream PlayerRequestResponse) returns (stream PlayerRequest);
} }