Skip to content

Commit

Permalink
Suit new judge report APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
slhmy committed Jun 16, 2024
1 parent 204fcc5 commit 6e80ca8
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 92 deletions.
12 changes: 10 additions & 2 deletions judger/src/agent/http.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use reqwest::Url;

pub struct HttpClient {
client: reqwest::Client,
base_url: String,
Expand All @@ -9,7 +11,13 @@ impl HttpClient {
Self { client, base_url }
}

pub fn post(&self, path: String) -> reqwest::RequestBuilder {
self.client.post(format!("{}{}", self.base_url, path))
pub fn post(&self, path: String) -> Result<reqwest::RequestBuilder, anyhow::Error> {
let url = Url::parse(&format!("{}{}", self.base_url, path))?;
Ok(self.client.post(url))
}

pub fn put(&self, path: String) -> Result<reqwest::RequestBuilder, anyhow::Error> {
let url = Url::parse(&format!("{}{}", self.base_url, path))?;
Ok(self.client.put(url))
}
}
133 changes: 115 additions & 18 deletions judger/src/agent/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::http::HttpClient;
use judge_core::{compiler::Language, judge::result::JudgeResultInfo};
use judge_core::{compiler::Language, judge::result::JudgeVerdict};

pub struct PlatformClient {
client: HttpClient,
Expand All @@ -12,16 +12,41 @@ impl PlatformClient {
}
}

pub async fn pick_task(&self) -> Result<Option<JudgeTask>, anyhow::Error> {
pick_task(&self.client).await
pub async fn pick_judge_task(&self) -> Result<Option<JudgeTask>, anyhow::Error> {
pick_judge_task(&self.client).await
}

pub async fn report_task(
pub async fn report_judge_result_count(
&self,
judge_uid: &str,
result_count: usize,
) -> Result<(), anyhow::Error> {
report_judge_result_count(&self.client, judge_uid, result_count).await
}

pub async fn report_judge_result(
&self,
judge_uid: &str,
verdict: JudgeVerdict,
time_usage_ms: usize,
memory_usage_bytes: usize,
) -> Result<(), anyhow::Error> {
report_judge_result(
&self.client,
judge_uid,
verdict,
time_usage_ms,
memory_usage_bytes,
)
.await
}

pub async fn report_judge_task(
&self,
stream_id: &str,
results: Vec<JudgeResultInfo>,
verdict: JudgeVerdict,
) -> Result<(), anyhow::Error> {
report_task(&self.client, stream_id, results).await
report_task(&self.client, stream_id, verdict).await
}
}

Expand All @@ -45,12 +70,16 @@ struct PickTaskResponse {
task: JudgeTask,
}

async fn pick_task(client: &HttpClient) -> Result<Option<JudgeTask>, anyhow::Error> {
async fn pick_judge_task(client: &HttpClient) -> Result<Option<JudgeTask>, anyhow::Error> {
let pick_url = "api/v1/judge/task/pick";
let body = PickTaskBody {
consumer: "".to_string(),
};
let response = client.post(pick_url.to_string()).json(&body).send().await?;
let response = client
.post(pick_url.to_string())?
.json(&body)
.send()
.await?;

match response.status() {
reqwest::StatusCode::OK => Ok(Some(response.json::<PickTaskResponse>().await?.task)),
Expand All @@ -66,29 +95,97 @@ async fn pick_task(client: &HttpClient) -> Result<Option<JudgeTask>, anyhow::Err
}

#[derive(Serialize)]
struct ReportTaskBody {
struct ReportJudgeResultCountBody {
#[serde(rename = "judgeUID")]
judge_uid: String,
#[serde(rename = "resultCount")]
result_count: usize,
}

async fn report_judge_result_count(
client: &HttpClient,
judge_uid: &str,
result_count: usize,
) -> Result<(), anyhow::Error> {
let report_url = "api/v1/judge/task/report/result-count";
let body = ReportJudgeResultCountBody {
judge_uid: judge_uid.to_owned(),
result_count,
};
let response = client
.put(report_url.to_string())?
.json(&body)
.send()
.await?;

match response.status() {
reqwest::StatusCode::OK => Ok(()),
_ => Err(anyhow::anyhow!("Report JudgeResultCount Failed")),
}
}

#[derive(Serialize)]
struct ReportJudgeResultBody {
#[serde(rename = "judgeUID")]
judge_uid: String,
verdict: JudgeVerdict,
#[serde(rename = "timeUsageMS")]
time_usage_ms: usize,
#[serde(rename = "memoryUsageBytes")]
memory_usage_bytes: usize,
}

async fn report_judge_result(
client: &HttpClient,
judge_uid: &str,
verdict: JudgeVerdict,
time_usage_ms: usize,
memory_usage_bytes: usize,
) -> Result<(), anyhow::Error> {
let report_url = "api/v1/judge/task/report/result";
let body = ReportJudgeResultBody {
judge_uid: judge_uid.to_owned(),
verdict,
time_usage_ms,
memory_usage_bytes,
};
let response = client
.post(report_url.to_string())?
.json(&body)
.send()
.await?;

match response.status() {
reqwest::StatusCode::OK => Ok(()),
_ => Err(anyhow::anyhow!("Report JudgeResult Failed")),
}
}

#[derive(Serialize)]
struct ReportJudgeTaskBody {
consumer: String,
stream_id: String,
verdict_json: String,
#[serde(rename = "redisStreamID")]
redis_stream_id: String,
verdict: JudgeVerdict,
}
#[derive(Deserialize, Debug)]
struct ReportTaskResponse {
struct ReportJudgeTaskResponse {
message: String,
}

async fn report_task(
client: &HttpClient,
stream_id: &str,
results: Vec<JudgeResultInfo>,
verdict: JudgeVerdict,
) -> Result<(), anyhow::Error> {
let report_url = "api/v1/judge/task/report";
let body = ReportTaskBody {
let body = ReportJudgeTaskBody {
consumer: "".to_string(),
stream_id: stream_id.to_owned(),
verdict_json: serde_json::to_string(&results).unwrap(),
redis_stream_id: stream_id.to_owned(),
verdict,
};
let response = client
.post(report_url.to_string())
.put(report_url.to_string())?
.json(&body)
.send()
.await?;
Expand All @@ -97,7 +194,7 @@ async fn report_task(
reqwest::StatusCode::OK => {
log::debug!(
"Report message: {:?}",
response.json::<ReportTaskResponse>().await?.message
response.json::<ReportJudgeTaskResponse>().await?.message
);
Ok(())
}
Expand Down
3 changes: 1 addition & 2 deletions judger/src/handler/state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::sync::RwLock;

use actix_web::{get, web, HttpResponse};
use lazy_static::lazy_static;
use std::sync::RwLock;

use crate::error::ServiceError;

Expand Down
67 changes: 52 additions & 15 deletions judger/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ mod worker;
extern crate serde_derive;
extern crate lazy_static;

use std::{fs, path::PathBuf};
use std::{fs, path::PathBuf, time::Duration};

use actix_web::{App, HttpServer};
use agent::{platform, rclone::RcloneClient};
use judge_core::judge::{
result::{JudgeResultInfo, JudgeVerdict},
JudgeConfig,
};
use option::JudgerCommad;
use worker::JudgeWorker;

Expand Down Expand Up @@ -49,14 +53,17 @@ async fn main() -> std::io::Result<()> {
problem_slug,
language,
src_path,
} => judge(
maybe_rclone_client,
opt.problem_package_bucket,
opt.problem_package_dir,
problem_slug,
language,
src_path,
),
} => {
judge(
maybe_rclone_client,
opt.problem_package_bucket,
opt.problem_package_dir,
problem_slug,
language,
src_path,
)
.await
}
}
}

Expand Down Expand Up @@ -95,7 +102,7 @@ async fn serve(
.await
}

fn judge(
async fn judge(
maybe_rclone_client: Option<RcloneClient>,
problem_package_bucket: String,
problem_package_dir: PathBuf,
Expand Down Expand Up @@ -126,13 +133,43 @@ fn judge(
}
};

match worker.run_judge(problem_slug, language, code) {
Ok(result) => {
println!("{:?}", result);
let prepare_result = worker.prepare_judge(problem_slug.clone(), language, code.clone());
if prepare_result.is_err() {
log::error!("Failed to prepare judge: {:?}", prepare_result.err());
return Ok(());
}
let judge = prepare_result.unwrap();

let mut verdict = JudgeVerdict::Accepted;
for idx in 0..judge.testdata_configs.len() {
let judge_config = JudgeConfig {
test_data: judge.testdata_configs[idx].clone(),
program: judge.program_config.clone(),
checker: judge.checker_config.clone(),
runtime: judge.runtime_config.clone(),
};

let judge_result = worker.run_judge(judge_config);
let mut result = JudgeResultInfo {
verdict: JudgeVerdict::SystemError,
time_usage: Duration::from_secs(0),
memory_usage_bytes: 0,
exit_status: -1,
checker_exit_status: -1,
};
match judge_result {
Ok(r) => {
result = r;
}
Err(e) => {
log::debug!("Failed to run judge: {:?}", e);
}
}
Err(e) => {
log::error!("Failed to judge task: {:?}", e);
if result.verdict != JudgeVerdict::Accepted {
verdict = result.verdict;
break;
}
}
println!("{:?}", verdict);
Ok(())
}
Loading

0 comments on commit 6e80ca8

Please sign in to comment.