Skip to content

Commit

Permalink
Try #4:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored May 30, 2021
2 parents 690a8ee + ea8e36a commit 4a638cb
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 28 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ serde_json = "1.0.64"
valuer-client = { path = "../valuer-client" }
strum = { version = "0.20.0", features = ["derive"] }
base64 = "0.13.0"
rand = "0.8.3"
rand_chacha = "0.3.0"
105 changes: 105 additions & 0 deletions processor/src/fake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//! Pure implementation that returns valid, but fake data
use crate::{JobProgress, ProtocolSender, Request};
use judge_apis::judge_log::{JudgeLog, JudgeLogSubtaskRow, JudgeLogTestRow};
use pom::TestId;
use rand::{
distributions::{Alphanumeric, Uniform},
prelude::SliceRandom,
Rng, SeedableRng,
};
use rand_chacha::ChaChaRng;
use std::hash::{Hash, Hasher};
use tokio::sync::{mpsc, oneshot};
use valuer_api::{status_codes, JudgeLogKind, Status, StatusKind, SubtaskId};

#[derive(Clone)]
pub struct FakeSettings {}

pub fn judge(req: Request, settings: FakeSettings) -> JobProgress {
let (done_tx, done_rx) = oneshot::channel();
let (events_tx, events_rx) = mpsc::channel(1);
tokio::task::spawn(async move {
let mut protocol_sender = ProtocolSender {
sent: Vec::new(),
tx: events_tx,
debug_dump_dir: None,
};

do_judge(req, &mut protocol_sender, settings).await;

done_tx.send(Ok(())).ok();
});
JobProgress { events_rx, done_rx }
}

fn stable_hash<T: Hash + ?Sized>(val: &T) -> u64 {
let mut h = std::collections::hash_map::DefaultHasher::new();
val.hash(&mut h);
h.finish()
}

fn generate_string((len_lo, len_hi): (usize, usize), rng: &mut ChaChaRng) -> String {
let dist = Uniform::new(len_lo, len_hi);
let len = rng.sample(dist);

(0..len).map(|_| rng.sample(Alphanumeric) as char).collect()
}

fn generate_judge_log(kind: JudgeLogKind, rng: &mut ChaChaRng) -> JudgeLog {
let test_count = rng.sample(Uniform::new(3_u32, 20));
let make_status = |rng: &mut ChaChaRng| Status {
kind: [StatusKind::Accepted, StatusKind::Rejected]
.choose(&mut *rng)
.copied()
.unwrap(),
code: [
status_codes::WRONG_ANSWER,
status_codes::TEST_PASSED,
status_codes::TIME_LIMIT_EXCEEDED,
status_codes::RUNTIME_ERROR,
]
.choose(&mut *rng)
.copied()
.unwrap()
.to_owned(),
};
let tests = (0..test_count)
.map(|id| JudgeLogTestRow {
test_id: TestId::make(id + 1),
status: Some(make_status(&mut *rng)),
test_stdin: Some(generate_string((3, 100), rng)),
test_stdout: Some(generate_string((3, 100), rng)),
test_stderr: Some(generate_string((3, 100), rng)),
test_answer: Some(generate_string((3, 100), rng)),
time_usage: Some(rng.sample(Uniform::new(1_000_000, 1_000_000_000))),
memory_usage: Some(rng.sample(Uniform::new(1_000_000, 1_000_000_000))),
})
.collect();
let subtask_count = rng.sample(Uniform::new(1_u32, 10));
let subtasks = (0..subtask_count)
.map(|id| JudgeLogSubtaskRow {
subtask_id: SubtaskId::make(id + 1),
score: Some(rng.sample(Uniform::new(0, 100))),
})
.collect();
JudgeLog {
kind,
tests,
subtasks,
score: rng.sample(Uniform::new(0, 100)),
status: make_status(rng),
compile_log: (generate_string((10, 200), rng)),
is_full: false,
}
}

async fn do_judge(req: Request, protocol_sender: &mut ProtocolSender, _settings: FakeSettings) {
for kind in JudgeLogKind::list() {
let seed = stable_hash(&(&req.toolchain_name, &req.run_source, kind.as_str()));
tracing::info!(kind = kind.as_str(), seed = seed, "generating judge log");
let mut rng = ChaChaRng::seed_from_u64(seed);
let log = generate_judge_log(kind, &mut rng);
protocol_sender.send_log(log).await;
}
}
1 change: 1 addition & 0 deletions processor/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Processor is part of judge that deals with a single run (and it doesn't
//! care where have it come from).
pub mod fake;
mod compile;
mod exec_test;
mod request_builder;
Expand Down
41 changes: 31 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ struct Args {
/// Directory containing judging logs. Set to `/dev/null` to disable logging
#[clap(long, default_value = "/var/log/judges")]
logs: PathBuf,
/// Enable fake mode.
/// In this mode judge never loads problems or toolchains and just
/// generates random data for requests
#[clap(long)]
fake: bool,
}

async fn create_clients(args: &Args) -> anyhow::Result<processor::Clients> {
Expand All @@ -54,18 +59,10 @@ async fn create_clients(args: &Args) -> anyhow::Result<processor::Clients> {
})
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
let args: Args = Clap::parse();
async fn initialize_normal(args: &Args) -> anyhow::Result<rest::ServeKind> {
let clients = create_clients(&args)
.await
.context("failed to initialize dependency clients")?;
tracing::info!("Running REST API");
let cfg = rest::RestConfig { port: args.port };

let settings = {
let checker_logs = match &args.logs {
p if p == Path::new("/dev/null") => (None),
Expand All @@ -81,6 +78,30 @@ async fn main() -> anyhow::Result<()> {
}
processor::Settings { checker_logs }
};
rest::serve(cfg, clients, settings).await?;
Ok(rest::ServeKind::Normal { settings, clients })
}

fn initialize_fake() -> rest::ServeKind {
rest::ServeKind::Fake {
settings: processor::fake::FakeSettings {},
}
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
let args: Args = Clap::parse();
tracing::info!("Running REST API");
let cfg = rest::RestConfig { port: args.port };

let serve_config = if args.fake {
initialize_fake()
} else {
initialize_normal(&args).await?
};

rest::serve(cfg, serve_config).await?;
Ok(())
}
46 changes: 28 additions & 18 deletions src/rest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,19 @@ impl JudgeJob {
}
}

pub enum ServeKind {
Normal {
clients: processor::Clients,
settings: processor::Settings,
},
Fake {
settings: processor::fake::FakeSettings,
},
}

struct State {
judge: RwLock<HashMap<Uuid, Arc<Mutex<JudgeJob>>>>,
clients: processor::Clients,
settings: processor::Settings,
kind: ServeKind,
}

async fn start_job(
Expand All @@ -58,15 +67,21 @@ async fn start_job(
run_source: req.run_source.0,
};
let job_id = Uuid::new_v4();
let mut settings = state.settings.clone();
{
let mut job_id_s = Uuid::encode_buffer();
let job_id_s = job_id.to_hyphenated().encode_lower(&mut job_id_s);
if let Some(p) = &mut settings.checker_logs {
p.push(&*job_id_s);

let mut progress = match &state.kind {
ServeKind::Normal { settings, clients } => {
let mut settings = settings.clone();
{
let mut job_id_s = Uuid::encode_buffer();
let job_id_s = job_id.to_hyphenated().encode_lower(&mut job_id_s);
if let Some(p) = &mut settings.checker_logs {
p.push(&*job_id_s);
}
}
processor::judge(proc_request, clients.clone(), settings)
}
}
let mut progress = processor::judge(proc_request, state.clients.clone(), settings);
ServeKind::Fake { settings } => processor::fake::judge(proc_request, settings.clone()),
};
let job = JudgeJob {
id: job_id,
live_test: None,
Expand Down Expand Up @@ -154,16 +169,11 @@ async fn get_job_judge_log(
}

/// Serves api
#[tracing::instrument(skip(cfg, clients, settings))]
pub async fn serve(
cfg: RestConfig,
clients: processor::Clients,
settings: processor::Settings,
) -> anyhow::Result<()> {
#[tracing::instrument(skip(cfg, kind))]
pub async fn serve(cfg: RestConfig, kind: ServeKind) -> anyhow::Result<()> {
let state = Arc::new(State {
judge: RwLock::new(HashMap::new()),
clients,
settings,
kind,
});
let state2 = state.clone();
let route_create_job = warp::post()
Expand Down

0 comments on commit 4a638cb

Please sign in to comment.