Skip to content

Commit 4701bc3

Browse files
authored
feat: 동시 채점 수 제한 (#45)
## 추가된 기능 메모리가 터지는 것을 방지하기 위해 동시 채점 수를 제한합니다. ## 테스트 방법 동시에 여러 요청을 날리며 log를 찍어봅니다. 테스트를 위해 python의 aiohttp 라이브러리르 이용하여 동시에 요청하는 상황을 시뮬레이션해보았습니다. ## 관련 링크 https://wafflestudio.slack.com/archives/C07DDPK0TD4/p1723207545909049
1 parent 167bf54 commit 4701bc3

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

hodu-server/src/api/judge/view.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1-
use std::panic::AssertUnwindSafe;
1+
use std::{panic::AssertUnwindSafe, sync::atomic::Ordering, time::Duration};
22

33
use actix_web::{post, web, Responder};
44
use hodu_core::{mark, MarkParams};
55

66
use futures::FutureExt;
77

8-
use crate::api::judge::{
9-
error::JudgeError,
10-
schema::{CodeSubmission, MarkResponse},
8+
use crate::{
9+
api::judge::{
10+
error::JudgeError,
11+
schema::{CodeSubmission, MarkResponse},
12+
},
13+
MarkCounter,
1114
};
1215

16+
const MAX_SUBMISSIONS: u32 = 20;
17+
1318
#[post("/submit")]
1419
async fn submit_code(
1520
submission: Result<web::Json<CodeSubmission>, actix_web::Error>,
21+
counter: web::Data<MarkCounter>,
1622
) -> Result<impl Responder, JudgeError> {
1723
let submission = submission.map_err(|e| JudgeError::PayloadParseError(e))?;
1824
tracing::info!(
@@ -21,6 +27,14 @@ async fn submit_code(
2127
submission.language
2228
);
2329

30+
let mut current_count = counter.count.load(Ordering::SeqCst);
31+
while current_count >= MAX_SUBMISSIONS {
32+
tracing::info!("Max submissions reached, waiting for a slot...");
33+
tokio::time::sleep(Duration::from_secs(1)).await;
34+
current_count = counter.count.load(Ordering::SeqCst);
35+
}
36+
let previous_count = counter.count.fetch_add(1, Ordering::SeqCst);
37+
tracing::info!("Current count: {}", previous_count + 1);
2438
let output = AssertUnwindSafe(mark(MarkParams {
2539
language: &submission.language.clone().into(),
2640
code: &submission.code,
@@ -31,7 +45,11 @@ async fn submit_code(
3145
}))
3246
.catch_unwind()
3347
.await
34-
.map_err(|_| JudgeError::HoduCoreError)?;
48+
.map_err(|_| {
49+
counter.count.fetch_sub(1, Ordering::SeqCst);
50+
JudgeError::HoduCoreError
51+
})?;
52+
counter.count.fetch_sub(1, Ordering::SeqCst);
3553

3654
Ok(web::Json(
3755
serde_json::to_value(MarkResponse::new(&output, &submission.fields)).unwrap(),

hodu-server/src/main.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
use actix_web::{App, HttpServer};
1+
use std::sync::atomic::AtomicU32;
2+
3+
use actix_web::{web, App, HttpServer};
24

35
mod api;
46

7+
pub struct MarkCounter {
8+
count: AtomicU32,
9+
}
10+
511
#[actix_web::main]
612
async fn main() -> std::io::Result<()> {
713
tracing_subscriber::fmt::init();
814

9-
HttpServer::new(|| App::new().service(api::v1_router()))
10-
.bind("0.0.0.0:8080")?
11-
.run()
12-
.await
15+
let counter = web::Data::new(MarkCounter {
16+
count: AtomicU32::new(0),
17+
});
18+
19+
HttpServer::new(move || {
20+
App::new()
21+
.app_data(counter.clone())
22+
.service(api::v1_router())
23+
})
24+
.bind("0.0.0.0:8080")?
25+
.run()
26+
.await
1327
}

0 commit comments

Comments
 (0)