rename bot_api to client_api
This commit is contained in:
parent
93c4306b10
commit
67276bd0bb
8 changed files with 93 additions and 80 deletions
|
@ -4,6 +4,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tonic_build::configure()
|
tonic_build::configure()
|
||||||
.build_server(false)
|
.build_server(false)
|
||||||
.build_client(true)
|
.build_client(true)
|
||||||
.compile(&["../proto/bot_api.proto"], &["../proto"])?;
|
.compile(&["../proto/client_api.proto"], &["../proto"])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
pub mod pb {
|
pub mod pb {
|
||||||
tonic::include_proto!("grpc.planetwars.bot_api");
|
tonic::include_proto!("grpc.planetwars.client_api");
|
||||||
|
|
||||||
|
pub use player_api_client_message::ClientMessage as PlayerApiClientMessageType;
|
||||||
|
pub use player_api_server_message::ServerMessage as PlayerApiServerMessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use pb::bot_api_service_client::BotApiServiceClient;
|
use pb::client_api_service_client::ClientApiServiceClient;
|
||||||
use planetwars_matchrunner::bot_runner::Bot;
|
use planetwars_matchrunner::bot_runner::Bot;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{path::PathBuf, time::Duration};
|
use std::{path::PathBuf, time::Duration};
|
||||||
|
@ -77,16 +80,19 @@ async fn main() {
|
||||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_match(channel: Channel, opponent_name: String) -> Result<pb::CreatedMatch, Status> {
|
async fn create_match(
|
||||||
let mut client = BotApiServiceClient::new(channel);
|
channel: Channel,
|
||||||
|
opponent_name: String,
|
||||||
|
) -> Result<pb::CreateMatchResponse, Status> {
|
||||||
|
let mut client = ClientApiServiceClient::new(channel);
|
||||||
let res = client
|
let res = client
|
||||||
.create_match(Request::new(pb::MatchRequest { opponent_name }))
|
.create_match(Request::new(pb::CreateMatchRequest { opponent_name }))
|
||||||
.await;
|
.await;
|
||||||
res.map(|response| response.into_inner())
|
res.map(|response| response.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_player(bot_config: BotConfig, player_key: String, channel: Channel) {
|
async fn run_player(bot_config: BotConfig, player_key: String, channel: Channel) {
|
||||||
let mut client = BotApiServiceClient::with_interceptor(channel, |mut req: Request<()>| {
|
let mut client = ClientApiServiceClient::with_interceptor(channel, |mut req: Request<()>| {
|
||||||
let player_key: MetadataValue<_> = player_key.parse().unwrap();
|
let player_key: MetadataValue<_> = player_key.parse().unwrap();
|
||||||
req.metadata_mut().insert("player_key", player_key);
|
req.metadata_mut().insert("player_key", player_key);
|
||||||
Ok(req)
|
Ok(req)
|
||||||
|
@ -109,18 +115,15 @@ async fn run_player(bot_config: BotConfig, player_key: String, channel: Channel)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_inner();
|
.into_inner();
|
||||||
while let Some(message) = stream.message().await.unwrap() {
|
while let Some(message) = stream.message().await.unwrap() {
|
||||||
use pb::client_message::ClientMessage;
|
|
||||||
use pb::server_message::ServerMessage;
|
|
||||||
|
|
||||||
match message.server_message {
|
match message.server_message {
|
||||||
Some(ServerMessage::PlayerRequest(req)) => {
|
Some(pb::PlayerApiServerMessageType::ActionRequest(req)) => {
|
||||||
let moves = bot_process.communicate(&req.content).await.unwrap();
|
let moves = bot_process.communicate(&req.content).await.unwrap();
|
||||||
let resp = pb::PlayerRequestResponse {
|
let action = pb::PlayerAction {
|
||||||
request_id: req.request_id,
|
action_request_id: req.action_request_id,
|
||||||
content: moves.as_bytes().to_vec(),
|
content: moves.as_bytes().to_vec(),
|
||||||
};
|
};
|
||||||
let msg = pb::ClientMessage {
|
let msg = pb::PlayerApiClientMessage {
|
||||||
client_message: Some(ClientMessage::RequestResponse(resp)),
|
client_message: Some(pb::PlayerApiClientMessageType::Action(action)),
|
||||||
};
|
};
|
||||||
tx.send(msg).unwrap();
|
tx.send(msg).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tonic_build::configure()
|
tonic_build::configure()
|
||||||
.build_server(true)
|
.build_server(true)
|
||||||
.build_client(false)
|
.build_client(false)
|
||||||
.compile(&["../proto/bot_api.proto"], &["../proto"])?;
|
.compile(&["../proto/client_api.proto"], &["../proto"])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use bb8::{Pool, PooledConnection};
|
||||||
use bb8_diesel::{self, DieselConnectionManager};
|
use bb8_diesel::{self, DieselConnectionManager};
|
||||||
use config::ConfigError;
|
use config::ConfigError;
|
||||||
use diesel::{Connection, PgConnection};
|
use diesel::{Connection, PgConnection};
|
||||||
use modules::bot_api::run_bot_api;
|
use modules::client_api::run_client_api;
|
||||||
use modules::ranking::run_ranker;
|
use modules::ranking::run_ranker;
|
||||||
use modules::registry::registry_service;
|
use modules::registry::registry_service;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -172,7 +172,7 @@ pub async fn run_app() {
|
||||||
tokio::spawn(run_ranker(global_config.clone(), db_pool.clone()));
|
tokio::spawn(run_ranker(global_config.clone(), db_pool.clone()));
|
||||||
}
|
}
|
||||||
tokio::spawn(run_registry(global_config.clone(), db_pool.clone()));
|
tokio::spawn(run_registry(global_config.clone(), db_pool.clone()));
|
||||||
tokio::spawn(run_bot_api(global_config.clone(), db_pool.clone()));
|
tokio::spawn(run_client_api(global_config.clone(), db_pool.clone()));
|
||||||
|
|
||||||
let api_service = Router::new()
|
let api_service = Router::new()
|
||||||
.nest("/api", api())
|
.nest("/api", api())
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
pub mod pb {
|
pub mod pb {
|
||||||
tonic::include_proto!("grpc.planetwars.bot_api");
|
tonic::include_proto!("grpc.planetwars.client_api");
|
||||||
|
|
||||||
|
pub use player_api_client_message::ClientMessage as PlayerApiClientMessageType;
|
||||||
|
pub use player_api_server_message::ServerMessage as PlayerApiServerMessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -24,7 +27,7 @@ use crate::GlobalConfig;
|
||||||
|
|
||||||
use super::matches::{MatchPlayer, RunMatch};
|
use super::matches::{MatchPlayer, RunMatch};
|
||||||
|
|
||||||
pub struct BotApiServer {
|
pub struct ClientApiServer {
|
||||||
conn_pool: ConnectionPool,
|
conn_pool: ConnectionPool,
|
||||||
runner_config: Arc<GlobalConfig>,
|
runner_config: Arc<GlobalConfig>,
|
||||||
router: PlayerRouter,
|
router: PlayerRouter,
|
||||||
|
@ -65,12 +68,12 @@ impl PlayerRouter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::bot_api_service_server::BotApiService for BotApiServer {
|
impl pb::client_api_service_server::ClientApiService for ClientApiServer {
|
||||||
type ConnectPlayerStream = UnboundedReceiverStream<Result<pb::ServerMessage, Status>>;
|
type ConnectPlayerStream = UnboundedReceiverStream<Result<pb::PlayerApiServerMessage, Status>>;
|
||||||
|
|
||||||
async fn connect_player(
|
async fn connect_player(
|
||||||
&self,
|
&self,
|
||||||
req: Request<Streaming<pb::ClientMessage>>,
|
req: Request<Streaming<pb::PlayerApiClientMessage>>,
|
||||||
) -> Result<Response<Self::ConnectPlayerStream>, Status> {
|
) -> Result<Response<Self::ConnectPlayerStream>, Status> {
|
||||||
// TODO: clean up errors
|
// TODO: clean up errors
|
||||||
let player_key = req
|
let player_key = req
|
||||||
|
@ -97,8 +100,8 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
|
||||||
|
|
||||||
async fn create_match(
|
async fn create_match(
|
||||||
&self,
|
&self,
|
||||||
req: Request<pb::MatchRequest>,
|
req: Request<pb::CreateMatchRequest>,
|
||||||
) -> Result<Response<pb::CreatedMatch>, Status> {
|
) -> Result<Response<pb::CreateMatchResponse>, Status> {
|
||||||
// TODO: unify with matchrunner module
|
// TODO: unify with matchrunner module
|
||||||
let conn = self.conn_pool.get().await.unwrap();
|
let conn = self.conn_pool.get().await.unwrap();
|
||||||
|
|
||||||
|
@ -131,7 +134,7 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
|
||||||
.await
|
.await
|
||||||
.expect("failed to create match");
|
.expect("failed to create match");
|
||||||
|
|
||||||
Ok(Response::new(pb::CreatedMatch {
|
Ok(Response::new(pb::CreateMatchResponse {
|
||||||
match_id: created_match.base.id,
|
match_id: created_match.base.id,
|
||||||
player_key,
|
player_key,
|
||||||
// TODO: can we avoid hardcoding this?
|
// TODO: can we avoid hardcoding this?
|
||||||
|
@ -145,8 +148,8 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
|
||||||
|
|
||||||
// TODO: please rename me
|
// TODO: please rename me
|
||||||
struct SyncThingData {
|
struct SyncThingData {
|
||||||
tx: oneshot::Sender<Streaming<pb::ClientMessage>>,
|
tx: oneshot::Sender<Streaming<pb::PlayerApiClientMessage>>,
|
||||||
server_messages: mpsc::UnboundedReceiver<Result<pb::ServerMessage, Status>>,
|
server_messages: mpsc::UnboundedReceiver<Result<pb::PlayerApiServerMessage, Status>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RemoteBotSpec {
|
struct RemoteBotSpec {
|
||||||
|
@ -203,13 +206,13 @@ impl runner::BotSpec for RemoteBotSpec {
|
||||||
async fn handle_bot_messages(
|
async fn handle_bot_messages(
|
||||||
player_id: u32,
|
player_id: u32,
|
||||||
event_bus: Arc<Mutex<EventBus>>,
|
event_bus: Arc<Mutex<EventBus>>,
|
||||||
mut messages: Streaming<pb::ClientMessage>,
|
mut messages: Streaming<pb::PlayerApiClientMessage>,
|
||||||
) {
|
) {
|
||||||
// TODO: can this be writte nmore nicely?
|
// TODO: can this be writte nmore nicely?
|
||||||
while let Some(message) = messages.message().await.unwrap() {
|
while let Some(message) = messages.message().await.unwrap() {
|
||||||
match message.client_message {
|
match message.client_message {
|
||||||
Some(pb::client_message::ClientMessage::RequestResponse(resp)) => {
|
Some(pb::PlayerApiClientMessageType::Action(resp)) => {
|
||||||
let request_id = (player_id, resp.request_id as u32);
|
let request_id = (player_id, resp.action_request_id as u32);
|
||||||
event_bus
|
event_bus
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -221,20 +224,20 @@ async fn handle_bot_messages(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RemoteBotHandle {
|
struct RemoteBotHandle {
|
||||||
sender: mpsc::UnboundedSender<Result<pb::ServerMessage, Status>>,
|
sender: mpsc::UnboundedSender<Result<pb::PlayerApiServerMessage, Status>>,
|
||||||
player_id: u32,
|
player_id: u32,
|
||||||
event_bus: Arc<Mutex<EventBus>>,
|
event_bus: Arc<Mutex<EventBus>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlayerHandle for RemoteBotHandle {
|
impl PlayerHandle for RemoteBotHandle {
|
||||||
fn send_request(&mut self, r: RequestMessage) {
|
fn send_request(&mut self, r: RequestMessage) {
|
||||||
let req = pb::PlayerRequest {
|
let req = pb::PlayerActionRequest {
|
||||||
request_id: r.request_id as i32,
|
action_request_id: r.request_id as i32,
|
||||||
content: r.content,
|
content: r.content,
|
||||||
};
|
};
|
||||||
|
|
||||||
let server_message = pb::ServerMessage {
|
let server_message = pb::PlayerApiServerMessage {
|
||||||
server_message: Some(pb::server_message::ServerMessage::PlayerRequest(req)),
|
server_message: Some(pb::PlayerApiServerMessageType::ActionRequest(req)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = self.sender.send(Ok(server_message));
|
let res = self.sender.send(Ok(server_message));
|
||||||
|
@ -282,9 +285,9 @@ async fn schedule_timeout(
|
||||||
.resolve_request(request_id, Err(RequestError::Timeout));
|
.resolve_request(request_id, Err(RequestError::Timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_bot_api(runner_config: Arc<GlobalConfig>, pool: ConnectionPool) {
|
pub async fn run_client_api(runner_config: Arc<GlobalConfig>, pool: ConnectionPool) {
|
||||||
let router = PlayerRouter::new();
|
let router = PlayerRouter::new();
|
||||||
let server = BotApiServer {
|
let server = ClientApiServer {
|
||||||
router,
|
router,
|
||||||
conn_pool: pool,
|
conn_pool: pool,
|
||||||
runner_config,
|
runner_config,
|
||||||
|
@ -292,7 +295,9 @@ pub async fn run_bot_api(runner_config: Arc<GlobalConfig>, pool: ConnectionPool)
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 50051));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 50051));
|
||||||
Server::builder()
|
Server::builder()
|
||||||
.add_service(pb::bot_api_service_server::BotApiServiceServer::new(server))
|
.add_service(pb::client_api_service_server::ClientApiServiceServer::new(
|
||||||
|
server,
|
||||||
|
))
|
||||||
.serve(addr)
|
.serve(addr)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
|
@ -1,7 +1,7 @@
|
||||||
// This module implements general domain logic, not directly
|
// This module implements general domain logic, not directly
|
||||||
// tied to the database or API layers.
|
// tied to the database or API layers.
|
||||||
pub mod bot_api;
|
|
||||||
pub mod bots;
|
pub mod bots;
|
||||||
|
pub mod client_api;
|
||||||
pub mod matches;
|
pub mod matches;
|
||||||
pub mod ranking;
|
pub mod ranking;
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package grpc.planetwars.bot_api;
|
|
||||||
|
|
||||||
message ServerMessage {
|
|
||||||
oneof server_message {
|
|
||||||
PlayerRequest player_request = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message PlayerRequest {
|
|
||||||
int32 request_id = 1;
|
|
||||||
bytes content = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ClientMessage {
|
|
||||||
oneof client_message {
|
|
||||||
PlayerRequestResponse request_response = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message PlayerRequestResponse {
|
|
||||||
int32 request_id = 1;
|
|
||||||
bytes content = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message MatchRequest {
|
|
||||||
string opponent_name = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CreatedMatch {
|
|
||||||
int32 match_id = 1;
|
|
||||||
string player_key = 2;
|
|
||||||
string match_url = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
service BotApiService {
|
|
||||||
rpc CreateMatch(MatchRequest) returns (CreatedMatch);
|
|
||||||
// server sends requests to the player, player responds
|
|
||||||
rpc ConnectPlayer(stream ClientMessage) returns (stream ServerMessage);
|
|
||||||
}
|
|
45
proto/client_api.proto
Normal file
45
proto/client_api.proto
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package grpc.planetwars.client_api;
|
||||||
|
|
||||||
|
// Provides the planetwars client API, allowing for remote play.
|
||||||
|
service ClientApiService {
|
||||||
|
rpc CreateMatch(CreateMatchRequest) returns (CreateMatchResponse);
|
||||||
|
rpc ConnectPlayer(stream PlayerApiClientMessage) returns (stream PlayerApiServerMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateMatchRequest {
|
||||||
|
string opponent_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateMatchResponse {
|
||||||
|
int32 match_id = 1;
|
||||||
|
string player_key = 2;
|
||||||
|
string match_url = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Server messages
|
||||||
|
message PlayerApiServerMessage {
|
||||||
|
oneof server_message {
|
||||||
|
PlayerActionRequest action_request = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerActionRequest {
|
||||||
|
int32 action_request_id = 1;
|
||||||
|
bytes content = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Player messages
|
||||||
|
message PlayerApiClientMessage {
|
||||||
|
oneof client_message {
|
||||||
|
PlayerAction action = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerAction {
|
||||||
|
int32 action_request_id = 1;
|
||||||
|
bytes content = 2;
|
||||||
|
}
|
Loading…
Reference in a new issue