diff --git a/dev-problem-package/hello-world/.timelimit b/dev-problem-package/hello-world/.timelimit index d00491f..0cfbf08 100644 --- a/dev-problem-package/hello-world/.timelimit +++ b/dev-problem-package/hello-world/.timelimit @@ -1 +1 @@ -1 +2 diff --git a/judge-server/src/service/judge.rs b/judge-server/src/service/judge.rs index 6e7a659..4b576c1 100644 --- a/judge-server/src/service/judge.rs +++ b/judge-server/src/service/judge.rs @@ -1,6 +1,6 @@ use std::{fs, path::PathBuf}; -use crate::error::ServiceError; +use crate::{error::ServiceError, service::state}; use actix_web::{post, web, HttpResponse}; use judge_core::{ @@ -28,12 +28,12 @@ pub fn route(cfg: &mut web::ServiceConfig) { // TODO: Remove the first `_` when the segment is actually used #[derive(Debug, ToSchema, Deserialize)] pub struct RunJudgeBody { - src: String, - src_language: Language + code: String, + language: Language, } #[utoipa::path( - context_path = "/api/v1/judge", + context_path = "/api/v1/judge", request_body(content = RunJudgeBody, content_type = "application/json", description = "The info a judge task should refer to"), responses( (status = 200, description = "Judge run successfully") @@ -45,23 +45,26 @@ pub async fn run_judge( body: web::Json, problem_package_dir: web::Data, ) -> Result { + state::set_busy().map_err(|e| { + println!("Failed to set busy: {:?}", e); + ServiceError::InternalError(anyhow::anyhow!("Judge server is busy")) + })?; + let package_slug = path.into_inner(); log::debug!("receive body: {:?}", body); let uuid = uuid::Uuid::new_v4(); let runtime_path = PathBuf::from("/tmp").join(uuid.to_string()); - let src_file_name = format!("src.{}", body.src_language.get_extension()); - println!("runtime_path: {:?}", runtime_path); + let src_file_name = format!("src.{}", body.language.get_extension()); + log::debug!("runtime_path: {:?}", runtime_path); fs::create_dir_all(runtime_path.clone()).map_err(|e| { - println!("Failed to create runtime dir: {:?}", e); + log::debug!("Failed to create runtime dir: {:?}", e); ServiceError::InternalError(anyhow::anyhow!("Failed to create runtime dir")) })?; - fs::write(runtime_path.clone().join(&src_file_name), body.src.clone()).map_err( - |e| { - println!("Failed to write src file: {:?}", e); - ServiceError::InternalError(anyhow::anyhow!("Failed to write src file")) - }, - )?; + fs::write(runtime_path.clone().join(&src_file_name), body.code.clone()).map_err(|e| { + log::debug!("Failed to write src file: {:?}", e); + ServiceError::InternalError(anyhow::anyhow!("Failed to write src file")) + })?; let handle: JoinHandle, JudgeCoreError>> = tokio::spawn(async move { @@ -69,18 +72,18 @@ pub async fn run_judge( package_type: PackageType::ICPC, package_path: problem_package_dir.join(package_slug.clone()), runtime_path: runtime_path.clone(), - src_language: body.src_language, + src_language: body.language, src_path: runtime_path.clone().join(&src_file_name), }); if new_builder_result.is_err() { - println!( + log::debug!( "Failed to new builder result: {:?}", new_builder_result.err() ); return Ok(vec![]); } let builder = new_builder_result?; - println!("Builder created: {:?}", builder); + log::debug!("Builder created: {:?}", builder); let mut results: Vec = vec![]; for idx in 0..builder.testdata_configs.len() { let judge_config = JudgeConfig { @@ -90,18 +93,19 @@ pub async fn run_judge( runtime: builder.runtime_config.clone(), }; let result = judge::common::run_judge(&judge_config)?; - println!("Judge result: {:?}", result); + log::debug!("Judge result: {:?}", result); results.push(result); } - println!("BatchJudge finished"); + state::set_idle(); + log::debug!("Judge finished"); Ok(results) }); match handle.await.unwrap() { Ok(results) => Ok(HttpResponse::Ok().json(results)), Err(e) => { - println!("Failed to await handle: {:?}", e); + log::info!("Failed to await handle: {:?}", e); Err(ServiceError::InternalError(anyhow::anyhow!("Judge failed"))) } } diff --git a/judge-server/src/service/mod.rs b/judge-server/src/service/mod.rs index 34fdcaa..39417e2 100644 --- a/judge-server/src/service/mod.rs +++ b/judge-server/src/service/mod.rs @@ -1,5 +1,6 @@ mod greet; mod judge; +mod state; use actix_web::web; use utoipa::OpenApi; diff --git a/judge-server/src/service/state.rs b/judge-server/src/service/state.rs new file mode 100644 index 0000000..42c832d --- /dev/null +++ b/judge-server/src/service/state.rs @@ -0,0 +1,32 @@ +use std::sync::RwLock; + +use lazy_static::lazy_static; + +#[derive(Clone, Debug, PartialEq)] +pub enum State { + Idle, + Busy, +} + +lazy_static! { + pub static ref STATE: RwLock = RwLock::new(State::Idle); +} + +pub fn set_busy() -> anyhow::Result<()> { + log::info!("Trying to set busy"); + let mut state = STATE + .try_write() + .map_err(|e| anyhow::anyhow!("Failed to lock state: {:?}", e))?; + log::info!("State: {:?}", *state); + if *state == State::Busy { + anyhow::bail!("Judge server is busy") + } + *state = State::Busy; + + Ok(()) +} + +pub fn set_idle() { + let mut state = STATE.write().unwrap(); + *state = State::Idle; +} diff --git a/postman/Judge Server.postman_collection.json b/postman/Judge Server.postman_collection.json index 82ed503..4535e53 100644 --- a/postman/Judge Server.postman_collection.json +++ b/postman/Judge Server.postman_collection.json @@ -7,13 +7,42 @@ }, "item": [ { - "name": "localhost:8000/api/v1/judge/hello-world", + "name": "v1/judge/hello-world", "request": { "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"src\": \"#include \\n\\nusing namespace std;\\n\\nint main() {\\n string s;\\n cin >> s;\\n cout << \\\"Hello! \\\" << s << endl;\\n}\\n\",\r\n \"src_language\": \"Cpp\"\r\n}", + "raw": "{\r\n \"code\": \"#include \\n\\nusing namespace std;\\n\\nint main() {\\n string s;\\n cin >> s;\\n cout << \\\"Hello! \\\" << s << endl;\\n}\\n\",\r\n \"language\": \"Cpp\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{Judger Host}}/api/v1/judge/hello-world", + "host": [ + "{{Judger Host}}" + ], + "path": [ + "api", + "v1", + "judge", + "hello-world" + ] + } + }, + "response": [] + }, + { + "name": "v1/judge/hello-world TLE", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"code\": \"#include \\r\\n#include \\r\\n\\r\\nint main() {\\r\\n clock_t start, step;\\r\\n start = clock();\\r\\n step = clock();\\r\\n while (true) {\\r\\n if (clock() - step > 1000000) {\\r\\n printf(\\\"%lds has passed..\\\\n\\\", (clock() - start) \\/ 1000000);\\r\\n step = clock();\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\r\n \"language\": \"Cpp\"\r\n}", "options": { "raw": { "language": "json"