Skip to content

Commit

Permalink
Merge branch 'master' of github.com:mdcpp/mdoj
Browse files Browse the repository at this point in the history
  • Loading branch information
KAIYOHUGO committed Dec 27, 2023
2 parents 79b3b74 + ebbc157 commit 80edf5e
Show file tree
Hide file tree
Showing 72 changed files with 570 additions and 315 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions backend/migration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ path = "src/lib.rs"
[dependencies]
log = "0.4.20"
tracing-subscriber = "0.3"
paste = "1.0.12"

[dependencies.tracing]
version = "0.1.40"
Expand Down
76 changes: 76 additions & 0 deletions backend/migration/src/m20231207_000001_create_table.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
use paste::paste;
use sea_orm::{DatabaseBackend, Statement};
use sea_orm_migration::prelude::*;

// static UPDATE_AT: &str = "DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
static UPDATE_AT: &str = "DEFAULT CURRENT_TIMESTAMP";
static CREATE_AT: &str = "DEFAULT CURRENT_TIMESTAMP";

macro_rules! index {
($manager:expr,$table:ident,$col:ident) => {
paste! {
$manager
.create_index(
Index::create()
.name(
concat!(
"idx-",
stringify!($table),
"-",
stringify!($col),
).to_lowercase()
)
.table($table::Table)
.col($table::$col)
.to_owned(),
)
.await?;
}
};
}

#[derive(Iden)]
enum Announcement {
Table,
Expand Down Expand Up @@ -509,6 +534,57 @@ impl MigrationTrait for Migration {
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx-problem-text")
.table(Problem::Table)
.col(Problem::Tags)
.col(Problem::Title)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx-education-text")
.table(Education::Table)
.col(Education::Tags)
.col(Education::Title)
.to_owned(),
)
.await?;

index!(manager, Problem, Public);
index!(manager, Problem, SubmitCount);
index!(manager, Problem, AcRate);
index!(manager, Problem, AcceptCount);
index!(manager, Problem, Difficulty);
index!(manager, Submit, Committed);
index!(manager, Submit, Time);
index!(manager, Submit, Memory);
index!(manager, Contest, Hoster);
index!(manager, Contest, Public);
index!(manager, Contest, End);
index!(manager, Contest, Begin);
index!(manager, User, Score);
index!(manager, User, Username);
index!(manager, Token, Rand);

manager
.get_connection()
.execute(
Statement::from_string(DatabaseBackend::Sqlite, "PRAGMA journal_mode = WAL")
.to_owned(),
)
.await?;
manager
.get_connection()
.execute(
Statement::from_string(DatabaseBackend::Sqlite, "PRAGMA synchronous = NORMAL")
.to_owned(),
)
.await?;

Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion backend/src/controller/code.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::grpc::backend::StateCode as BackendCode;
use crate::grpc::judger::JudgerCode;

#[repr(u32)]
/// Stablized JudgeResponse Code, store in database
#[repr(C)]
pub enum Code {
Accepted = 1,
WrongAnswer = 2,
Expand Down
10 changes: 7 additions & 3 deletions backend/src/controller/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl CryptoController {

let signing_key = SigningKey::random(&mut OsRng);

let verifying_key = signing_key.verifying_key().clone();
let verifying_key = *signing_key.verifying_key();

Self {
salt,
Expand All @@ -86,6 +86,7 @@ impl CryptoController {
let hashed = hasher.finalize();
HashValue(hashed.to_vec())
}
/// serialize and sign the object with blake2b512, append the signature and return
#[tracing::instrument(level = "debug", skip_all)]
pub fn encode<M: Serialize>(&self, obj: M) -> Result<Vec<u8>> {
let raw = bincode::serialize(&obj)?;
Expand All @@ -98,6 +99,11 @@ impl CryptoController {
};
Ok(bincode::serialize(&signed)?)
}
/// extract signature and object of encoded bytes(serde will handle it)
///
/// check signature and return the object
///
/// Error if signature invaild
#[tracing::instrument(level = "debug", skip_all)]
pub fn decode<M: DeserializeOwned>(&self, raw: Vec<u8>) -> Result<M> {
let raw: Signed = bincode::deserialize(&raw)?;
Expand All @@ -111,5 +117,3 @@ impl CryptoController {
Ok(obj)
}
}

// #[cfg(feature = "unsecured-log")]
20 changes: 12 additions & 8 deletions backend/src/controller/duplicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,35 @@ impl DupController {
dup_str: Cache::new(150),
}
}
pub fn store_i32(&self, user_id: i32, uuid: Uuid, result: i32) {
/// store a request_id with result i32
pub fn store_i32(&self, spliter: i32, uuid: Uuid, result: i32) {
tracing::trace!(request_id=?uuid);
#[cfg(feature = "single-instance")]
self.dup_i32.insert((user_id, uuid), result);
self.dup_i32.insert((spliter, uuid), result);
}
pub fn store_str(&self, user_id: i32, uuid: Uuid, result: String) {
/// store a request_id with result String
pub fn store_str(&self, spliter: i32, uuid: Uuid, result: String) {
tracing::trace!(request_id=?uuid);
#[cfg(feature = "single-instance")]
self.dup_str.insert((user_id, uuid), result);
self.dup_str.insert((spliter, uuid), result);
}
/// attempt to get result of i32
#[tracing::instrument(level = "debug", skip(self))]
pub fn check_i32(&self, user_id: i32, uuid: &Uuid) -> Option<i32> {
pub fn check_i32(&self, spliter: i32, uuid: &Uuid) -> Option<i32> {
tracing::trace!(request_id=?uuid);
#[cfg(feature = "single-instance")]
if let Some(x) = self.dup_i32.get(&(user_id, *uuid)) {
if let Some(x) = self.dup_i32.get(&(spliter, *uuid)) {
log::debug!("duplicated request_id: {}, result: {}", uuid, x);
return Some(x);
}
None
}
/// attempt to get result of String
#[tracing::instrument(level = "debug", skip(self))]
pub fn check_str(&self, user_id: i32, uuid: &Uuid) -> Option<String> {
pub fn check_str(&self, spliter: i32, uuid: &Uuid) -> Option<String> {
tracing::trace!(request_id=?uuid);
#[cfg(feature = "single-instance")]
if let Some(x) = self.dup_str.get(&(user_id, *uuid)) {
if let Some(x) = self.dup_str.get(&(spliter, *uuid)) {
log::debug!("duplicated request_id: {}, result: {}", uuid, x);
return Some(x);
}
Expand Down
6 changes: 6 additions & 0 deletions backend/src/controller/imgur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashMap;

use reqwest::Client;
use serde::Serialize;
use tracing::instrument;

use crate::init::config;

Expand All @@ -22,6 +23,9 @@ impl From<Error> for tonic::Status {
}
}

/// json serialization for imgur api
///
/// Read Imgur API Docs for more
#[derive(Serialize)]
struct AccessTokenRequest<'a> {
refresh_token: &'a str,
Expand All @@ -44,6 +48,8 @@ impl ImgurController {
config: config.clone(),
}
}
/// upload image
#[instrument(skip_all, level = "debug")]
pub async fn upload(&self, image: Vec<u8>) -> Result<String, Error> {
let res = self
.client
Expand Down
20 changes: 14 additions & 6 deletions backend/src/controller/judger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub enum Error {
JudgerError(Status),
#[error("payload.`{0}` is not a vaild argument")]
BadArgument(&'static str),
#[error("language not found")]
LangNotFound,
#[error("`{0}`")]
Database(#[from] sea_orm::error::DbErr),
#[error("`{0}`")]
Expand All @@ -92,6 +94,7 @@ impl From<Error> for Status {
match value {
Error::JudgerResourceExhausted => Status::resource_exhausted("no available judger"),
Error::BadArgument(x) => Status::invalid_argument(format!("bad argument: {}", x)),
Error::LangNotFound => Status::not_found("languaue not found"),
Error::JudgerError(x) => report_internal!(info, "`{}`", x),
Error::Database(x) => report_internal!(warn, "{}", x),
Error::TransportLayer(x) => report_internal!(info, "{}", x),
Expand Down Expand Up @@ -158,7 +161,7 @@ pub struct JudgerController {
impl JudgerController {
#[tracing::instrument(parent=span, name="judger_construct",level = "info",skip_all)]
pub async fn new(config: Vec<config::Judger>, span: &Span) -> Result<Self, Error> {
let router = Router::new(config, span).await?;
let router = Router::new(config, span)?;
Ok(JudgerController {
router,
pubsub: Arc::new(PubSub::default()),
Expand Down Expand Up @@ -212,15 +215,21 @@ impl JudgerController {
let task = res.task.unwrap();
match task {
judge_response::Task::Case(case) => {
tracing::debug!(case = case, "recv_case");
if ps_guard.send(Ok(case.into())).is_err() {
tracing::trace!("client_disconnected");
}
if case != (running_case + 1) {
tracing::warn!("judger_mismatch_proto");
tracing::warn!(
skip_case = running_case + 1,
recv_case = case,
"judger_mismatch_proto"
);
}
running_case += 1;
}
judge_response::Task::Result(case) => {
tracing::debug!(status = case.status().as_str_name(), "recv_result");
if let Some(score) = scores.pop() {
if ps_guard.send(Ok(case.clone().into())).is_err() {
tracing::trace!("client_disconnected");
Expand All @@ -246,10 +255,9 @@ impl JudgerController {
model.time = ActiveValue::Set(Some(time.try_into().unwrap_or(i64::MAX)));
model.memory = ActiveValue::Set(Some(mem.try_into().unwrap_or(i64::MAX)));

if let Err(err) = model.update(DB.get().unwrap()).in_current_span().await {
tracing::warn!(err=?err,"database_disconnect");
} else {
tracing::debug!("submit_committed");
match model.update(DB.get().unwrap()).in_current_span().await {
Err(err) => tracing::warn!(err=?err,"database_disconnect"),
_ => tracing::debug!("submit_committed"),
}
}
pub async fn submit(self: &Arc<Self>, submit: Submit) -> Result<i32, Error> {
Expand Down
6 changes: 4 additions & 2 deletions backend/src/controller/judger/route/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ use super::{ConnectionDetail, Error, Routable, RouteStatus};
use crate::init::config::Judger;
use tonic::transport::Uri;

pub struct StaticRouter {
/// Upstream source for static(only emit once)
pub struct StaticRouter<const REUSE: bool> {
uri: Option<String>,
secret: Option<String>,
}

#[tonic::async_trait]
impl Routable for StaticRouter {
impl<const REUSE: bool> Routable for StaticRouter<REUSE> {
async fn route(&mut self) -> Result<RouteStatus, Error> {
Ok(match self.uri.take() {
Some(x) => RouteStatus::NewConnection(ConnectionDetail {
uri: x,
secret: self.secret.clone(),
reuse: REUSE,
}),
None => RouteStatus::Never,
})
Expand Down
Loading

0 comments on commit 80edf5e

Please sign in to comment.