diff options
author | Ilion Beyst <ilion.beyst@gmail.com> | 2022-02-27 20:35:22 +0100 |
---|---|---|
committer | Ilion Beyst <ilion.beyst@gmail.com> | 2022-02-27 20:35:22 +0100 |
commit | 22a8f3d619e8ef89eeb9a60ab0a27aed01aa93f7 (patch) | |
tree | 1d6307c96ebd3456e74509203e1155a2c82ffee1 | |
parent | 6ef6a872fe3bbe389e92145b39fd88d864f6a790 (diff) | |
download | planetwars.dev-22a8f3d619e8ef89eeb9a60ab0a27aed01aa93f7.tar.xz planetwars.dev-22a8f3d619e8ef89eeb9a60ab0a27aed01aa93f7.zip |
save all uploaded code bundles in database
-rw-r--r-- | planetwars-server/migrations/2021-12-18-130837_bots/up.sql | 2 | ||||
-rw-r--r-- | planetwars-server/src/db/bots.rs | 4 | ||||
-rw-r--r-- | planetwars-server/src/lib.rs | 17 | ||||
-rw-r--r-- | planetwars-server/src/modules/bots.rs | 23 | ||||
-rw-r--r-- | planetwars-server/src/modules/mod.rs | 3 | ||||
-rw-r--r-- | planetwars-server/src/routes/bots.rs | 2 | ||||
-rw-r--r-- | planetwars-server/src/routes/demo.rs | 24 | ||||
-rw-r--r-- | planetwars-server/src/schema.rs | 2 | ||||
-rw-r--r-- | planetwars-server/src/util.rs | 9 |
9 files changed, 60 insertions, 26 deletions
diff --git a/planetwars-server/migrations/2021-12-18-130837_bots/up.sql b/planetwars-server/migrations/2021-12-18-130837_bots/up.sql index 22e250b..a23fbf7 100644 --- a/planetwars-server/migrations/2021-12-18-130837_bots/up.sql +++ b/planetwars-server/migrations/2021-12-18-130837_bots/up.sql @@ -8,7 +8,7 @@ CREATE UNIQUE INDEX bots_index ON bots(owner_id, name); CREATE TABLE code_bundles ( id serial PRIMARY KEY, - bot_id integer REFERENCES bots(id) NOT NULL, + bot_id integer REFERENCES bots(id), path text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP );
\ No newline at end of file diff --git a/planetwars-server/src/db/bots.rs b/planetwars-server/src/db/bots.rs index f7d8373..baabd5a 100644 --- a/planetwars-server/src/db/bots.rs +++ b/planetwars-server/src/db/bots.rs @@ -42,14 +42,14 @@ pub fn find_all_bots(conn: &PgConnection) -> QueryResult<Vec<Bot>> { #[derive(Insertable)] #[table_name = "code_bundles"] pub struct NewCodeBundle<'a> { - pub bot_id: i32, + pub bot_id: Option<i32>, pub path: &'a str, } #[derive(Queryable, Serialize, Deserialize, Debug)] pub struct CodeBundle { pub id: i32, - pub bot_id: i32, + pub bot_id: Option<i32>, pub path: String, pub created_at: chrono::NaiveDateTime, } diff --git a/planetwars-server/src/lib.rs b/planetwars-server/src/lib.rs index b74525b..89b3d7a 100644 --- a/planetwars-server/src/lib.rs +++ b/planetwars-server/src/lib.rs @@ -3,15 +3,17 @@ extern crate diesel; pub mod db; pub mod db_types; +pub mod modules; pub mod routes; pub mod schema; +pub mod util; use std::ops::Deref; use axum; -use bb8::PooledConnection; +use bb8::{Pool, PooledConnection}; use bb8_diesel::{self, DieselConnectionManager}; -use diesel::PgConnection; +use diesel::{Connection, PgConnection}; use serde::Deserialize; use axum::{ @@ -29,9 +31,14 @@ const MAPS_DIR: &str = "./data/maps"; type ConnectionPool = bb8::Pool<DieselConnectionManager<PgConnection>>; -pub async fn api(configuration: Configuration) -> Router { - let manager = DieselConnectionManager::<PgConnection>::new(configuration.database_url); +pub async fn prepare_db(database_url: &str) -> Pool<DieselConnectionManager<PgConnection>> { + let manager = DieselConnectionManager::<PgConnection>::new(database_url); let pool = bb8::Pool::builder().build(manager).await.unwrap(); + return pool; +} + +pub async fn api(configuration: Configuration) -> Router { + let db_pool = prepare_db(&configuration.database_url).await; let api = Router::new() .route("/register", post(routes::users::register)) @@ -57,7 +64,7 @@ pub async fn api(configuration: Configuration) -> Router { get(routes::matches::get_match_log), ) .route("/submit_bot", post(routes::demo::submit_bot)) - .layer(AddExtensionLayer::new(pool)); + .layer(AddExtensionLayer::new(db_pool)); api } diff --git a/planetwars-server/src/modules/bots.rs b/planetwars-server/src/modules/bots.rs new file mode 100644 index 0000000..843e48d --- /dev/null +++ b/planetwars-server/src/modules/bots.rs @@ -0,0 +1,23 @@ +use std::path::PathBuf; + +use diesel::{PgConnection, QueryResult}; + +use crate::{db, util::gen_alphanumeric, BOTS_DIR}; + +pub fn save_code_bundle( + bot_code: &str, + bot_id: Option<i32>, + conn: &PgConnection, +) -> QueryResult<db::bots::CodeBundle> { + let bundle_name = gen_alphanumeric(16); + + let code_bundle_dir = PathBuf::from(BOTS_DIR).join(&bundle_name); + std::fs::create_dir(&code_bundle_dir).unwrap(); + std::fs::write(code_bundle_dir.join("bot.py"), bot_code).unwrap(); + + let new_code_bundle = db::bots::NewCodeBundle { + bot_id, + path: &bundle_name, + }; + db::bots::create_code_bundle(&new_code_bundle, conn) +} diff --git a/planetwars-server/src/modules/mod.rs b/planetwars-server/src/modules/mod.rs new file mode 100644 index 0000000..57c1ef5 --- /dev/null +++ b/planetwars-server/src/modules/mod.rs @@ -0,0 +1,3 @@ +// This module implements general domain logic, not directly +// tied to the database or API layers. +pub mod bots; diff --git a/planetwars-server/src/routes/bots.rs b/planetwars-server/src/routes/bots.rs index 0edfaa9..66b4d82 100644 --- a/planetwars-server/src/routes/bots.rs +++ b/planetwars-server/src/routes/bots.rs @@ -97,7 +97,7 @@ pub async fn upload_code_multipart( .map_err(|_| StatusCode::BAD_REQUEST)?; let bundle = bots::NewCodeBundle { - bot_id: bot.id, + bot_id: Some(bot.id), path: &folder_name, }; let code_bundle = diff --git a/planetwars-server/src/routes/demo.rs b/planetwars-server/src/routes/demo.rs index dbcdb64..28eab97 100644 --- a/planetwars-server/src/routes/demo.rs +++ b/planetwars-server/src/routes/demo.rs @@ -1,10 +1,11 @@ use crate::db::matches::{self, MatchState}; +use crate::modules::bots::save_code_bundle; +use crate::util::gen_alphanumeric; use crate::{ConnectionPool, BOTS_DIR, MAPS_DIR, MATCHES_DIR}; use axum::extract::Extension; use axum::Json; use hyper::StatusCode; use planetwars_matchrunner::{docker_runner::DockerBotSpec, run_match, MatchConfig, MatchPlayer}; -use rand::{distributions::Alphanumeric, Rng}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -15,6 +16,7 @@ const SIMPLEBOT_PATH: &'static str = "../simplebot"; #[derive(Serialize, Deserialize, Debug)] pub struct SubmitBotParams { + pub bot_name: Option<String>, pub code: String, } @@ -32,14 +34,12 @@ pub async fn submit_bot( ) -> Result<Json<SubmitBotResponse>, StatusCode> { let conn = pool.get().await.expect("could not get database connection"); - let uploaded_bot_uuid: String = gen_alphanumeric(16); - let log_file_name = format!("{}.log", gen_alphanumeric(16)); - - // store uploaded bot - let uploaded_bot_dir = PathBuf::from(BOTS_DIR).join(&uploaded_bot_uuid); - std::fs::create_dir(&uploaded_bot_dir).unwrap(); - std::fs::write(uploaded_bot_dir.join("bot.py"), params.code.as_bytes()).unwrap(); + let code_bundle = save_code_bundle(¶ms.code, None, &conn) + // TODO: can we recover from this? + .expect("could not save bot code"); + let log_file_name = format!("{}.log", gen_alphanumeric(16)); + let uploaded_bot_dir = PathBuf::from(BOTS_DIR).join(&code_bundle.path); // play the match let match_config = MatchConfig { map_path: PathBuf::from(MAPS_DIR).join("hex.json"), @@ -95,11 +95,3 @@ async fn run_match_task(match_id: i32, match_config: MatchConfig, connection_poo matches::set_match_state(match_id, MatchState::Finished, &conn) .expect("failed to update match state"); } - -pub fn gen_alphanumeric(length: usize) -> String { - rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(length) - .map(char::from) - .collect() -} diff --git a/planetwars-server/src/schema.rs b/planetwars-server/src/schema.rs index e67ef3a..0ebddf3 100644 --- a/planetwars-server/src/schema.rs +++ b/planetwars-server/src/schema.rs @@ -18,7 +18,7 @@ table! { code_bundles (id) { id -> Int4, - bot_id -> Int4, + bot_id -> Nullable<Int4>, path -> Text, created_at -> Timestamp, } diff --git a/planetwars-server/src/util.rs b/planetwars-server/src/util.rs new file mode 100644 index 0000000..44fcf1c --- /dev/null +++ b/planetwars-server/src/util.rs @@ -0,0 +1,9 @@ +use rand::{distributions::Alphanumeric, Rng}; + +pub fn gen_alphanumeric(length: usize) -> String { + rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(length) + .map(char::from) + .collect() +} |