From 539dc72ae927f5a26a569f04e50f9b21fab4b973 Mon Sep 17 00:00:00 2001 From: "Eason(G Ray)" <30045503+Eason0729@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:10:38 +0800 Subject: [PATCH] refactor(Backend): :heavy_minus_sign: use grpc crate for backend --- Cargo.lock | 6 +- backend/Cargo.toml | 13 ++-- backend/build.rs | 41 ------------ backend/src/controller/imgur.rs | 22 +++---- backend/src/controller/judger/mod.rs | 14 +--- backend/src/controller/judger/route/mod.rs | 6 +- backend/src/endpoint/announcement.rs | 21 ++---- backend/src/endpoint/chat.rs | 19 +----- backend/src/endpoint/contest.rs | 20 ++---- backend/src/endpoint/education.rs | 18 +---- backend/src/endpoint/imgur.rs | 6 +- backend/src/endpoint/mod.rs | 20 +++--- backend/src/endpoint/playground.rs | 30 ++------- backend/src/endpoint/problem.rs | 18 +---- backend/src/endpoint/submit.rs | 33 ++-------- backend/src/endpoint/testcase.rs | 17 +---- backend/src/endpoint/token.rs | 14 ++-- backend/src/endpoint/user.rs | 18 +---- backend/src/entity/announcement.rs | 2 +- backend/src/entity/contest.rs | 3 +- backend/src/entity/problem.rs | 4 +- backend/src/entity/user.rs | 2 +- backend/src/grpc.rs | 45 ------------- backend/src/init/config.rs | 7 +- backend/src/main.rs | 4 +- backend/src/server.rs | 76 +++++++++++++--------- backend/src/util/auth.rs | 2 +- backend/src/util/code.rs | 4 +- backend/src/util/error.rs | 2 +- backend/src/util/mod.rs | 1 + backend/src/util/time.rs | 13 ++++ grpc/Cargo.toml | 1 + grpc/src/backend.rs | 10 +++ grpc/src/bridge.rs | 32 +++++++++ grpc/src/ids.rs | 29 +++++++++ grpc/src/judger.rs | 27 ++++++++ grpc/src/lib.rs | 16 +++-- judger/Cargo.toml | 2 +- 38 files changed, 260 insertions(+), 358 deletions(-) delete mode 100644 backend/build.rs delete mode 100644 backend/src/grpc.rs create mode 100644 backend/src/util/time.rs create mode 100644 grpc/src/backend.rs create mode 100644 grpc/src/bridge.rs create mode 100644 grpc/src/ids.rs create mode 100644 grpc/src/judger.rs diff --git a/Cargo.lock b/Cargo.lock index 85321d83..7d137197 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,7 @@ dependencies = [ "derive_builder", "futures", "governor", + "grpc", "hickory-resolver", "http 0.2.12", "ip_network", @@ -690,8 +691,7 @@ dependencies = [ "opentelemetry_sdk", "paste", "postcard", - "prost 0.12.6", - "prost-types", + "prost-wkt-types", "quick_cache", "rand", "rand_hc", @@ -708,7 +708,6 @@ dependencies = [ "tokio-stream", "toml 0.7.8", "tonic 0.11.0", - "tonic-build", "tonic-web", "tower-http", "tracing", @@ -2308,6 +2307,7 @@ dependencies = [ name = "grpc" version = "0.1.0" dependencies = [ + "paste", "prost 0.12.6", "prost-wkt", "prost-wkt-build", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 0b8b3a1b..edfabc1b 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -12,9 +12,7 @@ codegen-backend = "cranelift" tikv-jemallocator = { version = "0.5", optional = true } log = "0.4.18" paste = "1.0.12" -prost = { workspace = true } toml = { workspace = true } -prost-types = { workspace = true } thiserror = "1.0.44" derive_builder = { workspace = true } futures = "0.3.29" @@ -41,6 +39,11 @@ sea-orm-cli = { version = "0.12.12", optional = true } governor = "0.6.0" http = "^0.2" lazy_static = "1.5.0" +prost-wkt-types = { workspace = true } + +[dependencies.grpc] +path = "../grpc" +features = ["server", "client", "backend", "judger", "transport", "serde"] [dependencies.postcard] version = "^1.0" @@ -66,7 +69,7 @@ features = ["serde"] [dependencies.reqwest] version = "0.11.22" default-features = false -features = ["rustls-tls", "json","multipart"] +features = ["rustls-tls", "json", "multipart"] [dependencies.k256] version = "0.13.2" @@ -116,10 +119,6 @@ version = "0.12.11" optional = true features = ["runtime-tokio-rustls", "sqlx-sqlite", "with-chrono"] -[build-dependencies.tonic-build] -workspace = true -features = ["default"] - [features] default = ["debug"] standalone = ["dep:migration", "dep:sea-orm-migration", "dep:sea-orm-cli"] diff --git a/backend/build.rs b/backend/build.rs deleted file mode 100644 index 97eda924..00000000 --- a/backend/build.rs +++ /dev/null @@ -1,41 +0,0 @@ -fn main() -> Result<(), Box> { - tonic_build::configure() - .build_client(false) - .type_attribute( - "oj.backend.SortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.SubmitSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.ProblemSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.TestcaseSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.ContestSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.UserSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .type_attribute( - "oj.backend.AnnouncementSortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .compile(&["../grpc/proto/backend.proto"], &["../grpc/proto"])?; - tonic_build::configure() - .build_server(false) - .type_attribute( - "oj.backend.SortBy", - "#[derive(serde::Serialize, serde::Deserialize)]", - ) - .compile(&["../grpc/proto/judger.proto"], &["../grpc/proto"])?; - Ok(()) -} diff --git a/backend/src/controller/imgur.rs b/backend/src/controller/imgur.rs index f5b426ad..43759fdb 100644 --- a/backend/src/controller/imgur.rs +++ b/backend/src/controller/imgur.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use reqwest::{multipart, Client}; -use serde::Serialize; use tracing::instrument; use crate::{init::config, report_internal}; @@ -25,16 +24,17 @@ impl From for tonic::Status { } } -/// json serialization for imgur api -/// -/// Read Imgur API Docs for more -#[derive(Serialize)] -struct AccessTokenRequest<'a> { - refresh_token: &'a str, - client_id: &'a str, - client_secret: &'a str, - grant_type: &'static str, -} +// FIXME: use token to delete image +// /// json serialization for imgur api +// /// +// /// Read Imgur API Docs for more +// #[derive(Serialize)] +// struct AccessTokenRequest<'a> { +// refresh_token: &'a str, +// client_id: &'a str, +// client_secret: &'a str, +// grant_type: &'static str, +// } pub struct ImgurController { client: Client, diff --git a/backend/src/controller/judger/mod.rs b/backend/src/controller/judger/mod.rs index a1f74373..66534487 100644 --- a/backend/src/controller/judger/mod.rs +++ b/backend/src/controller/judger/mod.rs @@ -12,10 +12,10 @@ use std::{ use tokio_stream::StreamExt; use crate::{ - grpc::{backend::StateCode as BackendCode, TonicStream}, init::{config, logger::PACKAGE_NAME}, - report_internal, + report_internal, TonicStream, }; +use grpc::backend::StateCode as BackendCode; use opentelemetry::{global, metrics::ObservableGauge}; use sea_orm::{ActiveModelTrait, ActiveValue, DatabaseConnection, EntityTrait, QueryOrder}; use thiserror::Error; @@ -23,7 +23,7 @@ use tonic::Status; use tracing::{instrument, Instrument, Span}; use uuid::Uuid; -use crate::grpc::{ +use grpc::{ backend::{submit_status, PlaygroundResult, SubmitStatus}, judger::*, }; @@ -95,14 +95,6 @@ pub struct Submit { code: Vec, } -impl From for SubmitStatus { - fn from(value: i32) -> Self { - SubmitStatus { - task: Some(submit_status::Task::Case(value)), - } - } -} - impl From for SubmitStatus { fn from(value: Code) -> Self { SubmitStatus { diff --git a/backend/src/controller/judger/route/mod.rs b/backend/src/controller/judger/route/mod.rs index 44a20b8f..bb63fdac 100644 --- a/backend/src/controller/judger/route/mod.rs +++ b/backend/src/controller/judger/route/mod.rs @@ -17,10 +17,8 @@ use tonic::{service::Interceptor, *}; use tracing::{debug_span, instrument, span, Instrument, Level, Span}; use uuid::Uuid; -use crate::{ - grpc::judger::{judger_client::*, *}, - init::config::{self, Judger as JudgerConfig}, -}; +use crate::init::config::{self, Judger as JudgerConfig}; +use grpc::judger::{judger_client::*, *}; // TODO: add tracing diff --git a/backend/src/endpoint/announcement.rs b/backend/src/endpoint/announcement.rs index 553f964d..4a1da00c 100644 --- a/backend/src/endpoint/announcement.rs +++ b/backend/src/endpoint/announcement.rs @@ -1,24 +1,13 @@ use super::tools::*; -use crate::grpc::backend::announcement_set_server::*; -use crate::grpc::backend::*; -use crate::grpc::into_prost; +use crate::util::time::into_prost; +use grpc::backend::announcement_set_server::*; +use grpc::backend::*; use crate::entity::announcement::*; use crate::entity::*; -use crate::NonZeroU32; - -impl From for AnnouncementId { - fn from(value: i32) -> Self { - Self { id: value } - } -} -impl From for i32 { - fn from(value: AnnouncementId) -> Self { - value.id - } -} +use crate::NonZeroU32; impl From for AnnouncementFullInfo { fn from(value: Model) -> Self { @@ -56,7 +45,7 @@ impl From for AnnouncementInfo { } #[async_trait] -impl AnnouncementSet for Arc { +impl AnnouncementSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/endpoint/chat.rs b/backend/src/endpoint/chat.rs index 5ec912f6..373c5064 100644 --- a/backend/src/endpoint/chat.rs +++ b/backend/src/endpoint/chat.rs @@ -1,22 +1,9 @@ use super::tools::*; -use crate::grpc::backend::chat_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::chat_set_server::*; +use grpc::backend::*; use crate::entity::chat::*; -use crate::grpc::into_prost; - -impl From for ChatId { - fn from(value: i32) -> Self { - ChatId { id: value } - } -} - -impl From for i32 { - fn from(value: ChatId) -> Self { - value.id - } -} impl From for ChatInfo { fn from(value: Model) -> Self { @@ -31,7 +18,7 @@ impl From for ChatInfo { } #[tonic::async_trait] -impl ChatSet for Arc { +impl ChatSet for ArcServer { async fn create(&self, req: Request) -> Result, Status> { let (auth, req) = self .parse_request_n(req, NonZeroU32!(5)) diff --git a/backend/src/endpoint/contest.rs b/backend/src/endpoint/contest.rs index 4bc0b20b..dce1d4cd 100644 --- a/backend/src/endpoint/contest.rs +++ b/backend/src/endpoint/contest.rs @@ -1,21 +1,9 @@ use super::tools::*; use crate::entity::{contest::*, *}; -use crate::grpc::backend::contest_set_server::*; -use crate::grpc::backend::*; -use crate::grpc::into_chrono; -use crate::grpc::into_prost; - -impl From for ContestId { - fn from(value: i32) -> Self { - Self { id: value } - } -} -impl From for i32 { - fn from(value: ContestId) -> Self { - value.id - } -} + +use grpc::backend::contest_set_server::*; +use grpc::backend::*; impl From for ContestFullInfo { fn from(value: Model) -> Self { @@ -61,7 +49,7 @@ impl From for ContestInfo { } #[async_trait] -impl ContestSet for Arc { +impl ContestSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/endpoint/education.rs b/backend/src/endpoint/education.rs index e07c7acc..cca7e957 100644 --- a/backend/src/endpoint/education.rs +++ b/backend/src/endpoint/education.rs @@ -1,22 +1,10 @@ use super::tools::*; -use crate::grpc::backend::education_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::education_set_server::*; +use grpc::backend::*; use crate::entity::{education::Paginator, education::*, *}; -impl From for EducationId { - fn from(value: i32) -> Self { - Self { id: value } - } -} - -impl From for i32 { - fn from(value: EducationId) -> Self { - value.id - } -} - impl From for EducationFullInfo { fn from(value: Model) -> Self { EducationFullInfo { @@ -39,7 +27,7 @@ impl From for EducationInfo { } #[async_trait] -impl EducationSet for Arc { +impl EducationSet for ArcServer { async fn list( &self, req: Request, diff --git a/backend/src/endpoint/imgur.rs b/backend/src/endpoint/imgur.rs index 6f450886..4969217c 100644 --- a/backend/src/endpoint/imgur.rs +++ b/backend/src/endpoint/imgur.rs @@ -1,10 +1,10 @@ use super::tools::*; -use crate::grpc::backend::imgur_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::imgur_set_server::*; +use grpc::backend::*; #[async_trait] -impl ImgurSet for Arc { +impl ImgurSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn upload( &self, diff --git a/backend/src/endpoint/mod.rs b/backend/src/endpoint/mod.rs index 419068b6..733fa9f8 100644 --- a/backend/src/endpoint/mod.rs +++ b/backend/src/endpoint/mod.rs @@ -20,26 +20,26 @@ mod tools { pub const SHORT_ART_SIZE: usize = 128; /// longest allowed size for long string pub const LONG_ART_SIZE: usize = 65536; - pub use crate::entity::util::paginator::{Pager, Remain}; - - pub use crate::grpc::TonicStream; pub use crate::NonZeroU32; + pub use sea_orm::*; pub use std::ops::Deref; + pub use tonic::*; + pub use tracing::*; + pub use uuid::Uuid; - pub use crate::entity::util::filter::*; + pub use crate::entity::util::{ + filter::*, + paginator::{Pager, Remain}, + }; pub use crate::util::{ auth::RoleLv, error::{atomic_fail, Error}, + time::*, }; pub use crate::{ check_exist_length, check_length, fill_active_model, fill_exist_active_model, - parse_pager_param, server::Server, + parse_pager_param, server::ArcServer, TonicStream, }; - pub use sea_orm::*; - pub use std::sync::Arc; - pub use tonic::*; - pub use tracing::*; - pub use uuid::Uuid; } // FIXME: currently we report transaction error as internal error, diff --git a/backend/src/endpoint/playground.rs b/backend/src/endpoint/playground.rs index cf8adcdb..7f91d790 100644 --- a/backend/src/endpoint/playground.rs +++ b/backend/src/endpoint/playground.rs @@ -1,17 +1,14 @@ use super::tools::*; use crate::controller::judger::PlaygroundPayload; -use crate::grpc::backend; -use crate::grpc::backend::playground_set_server::*; -use crate::grpc::backend::*; -use crate::grpc::judger; -use crate::grpc::judger::exec_result; -use crate::grpc::judger::ExecResult; + +use grpc::backend::playground_set_server::*; +use grpc::backend::*; const PLAYGROUND_CODE_LEN: usize = 32 * 1024; #[async_trait] -impl PlaygroundSet for Arc { +impl PlaygroundSet for ArcServer { #[doc = " Server streaming response type for the Run method."] type RunStream = TonicStream; @@ -46,22 +43,3 @@ impl PlaygroundSet for Arc { )) } } - -impl From for PlaygroundResult { - fn from(value: ExecResult) -> Self { - PlaygroundResult { - result: Some(match value.result.unwrap() { - exec_result::Result::Output(x) => playground_result::Result::Output(x), - exec_result::Result::Log(x) => playground_result::Result::Compile(x.into()), - }), - } - } -} -impl From for backend::Log { - fn from(value: judger::Log) -> Self { - backend::Log { - level: value.level, - msg: value.msg, - } - } -} diff --git a/backend/src/endpoint/problem.rs b/backend/src/endpoint/problem.rs index a3af3ac3..5c2bb340 100644 --- a/backend/src/endpoint/problem.rs +++ b/backend/src/endpoint/problem.rs @@ -1,21 +1,9 @@ use super::tools::*; -use crate::grpc::backend::problem_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::problem_set_server::*; +use grpc::backend::*; use crate::entity::{problem::*, *}; -impl From for ProblemId { - fn from(value: i32) -> Self { - ProblemId { id: value } - } -} - -impl From for i32 { - fn from(value: ProblemId) -> Self { - value.id - } -} - impl From for ProblemInfo { fn from(value: PartialModel) -> Self { ProblemInfo { @@ -50,7 +38,7 @@ impl From for ProblemFullInfo { } #[async_trait] -impl ProblemSet for Arc { +impl ProblemSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/endpoint/submit.rs b/backend/src/endpoint/submit.rs index f1ca8412..34469b86 100644 --- a/backend/src/endpoint/submit.rs +++ b/backend/src/endpoint/submit.rs @@ -1,41 +1,16 @@ use super::tools::*; use crate::controller::judger::SubmitBuilder; -use crate::grpc::backend::submit_set_server::*; -use crate::grpc::backend::StateCode as BackendCode; -use crate::grpc::backend::*; -use crate::grpc::into_prost; -use crate::grpc::judger::LangInfo; use crate::util::code::Code; +use grpc::backend::submit_set_server::*; +use grpc::backend::StateCode as BackendCode; +use grpc::backend::*; use crate::entity::{submit::*, *}; use tokio_stream::wrappers::ReceiverStream; const SUBMIT_CODE_LEN: usize = 32 * 1024; -impl From for SubmitId { - fn from(value: i32) -> Self { - SubmitId { id: value } - } -} - -impl From for i32 { - fn from(value: SubmitId) -> Self { - value.id - } -} - -impl From for Language { - fn from(value: LangInfo) -> Self { - Language { - lang_uid: value.lang_uid, - lang_name: value.lang_name, - info: value.info, - lang_ext: value.lang_ext, - } - } -} - impl From for SubmitInfo { fn from(value: Model) -> Self { // TODO: solve devation and uncommitted submit! @@ -73,7 +48,7 @@ impl From for SubmitInfo { } #[async_trait] -impl SubmitSet for Arc { +impl SubmitSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/endpoint/testcase.rs b/backend/src/endpoint/testcase.rs index e38970ae..657de3fa 100644 --- a/backend/src/endpoint/testcase.rs +++ b/backend/src/endpoint/testcase.rs @@ -1,21 +1,10 @@ use super::tools::*; -use crate::grpc::backend::testcase_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::testcase_set_server::*; +use grpc::backend::*; use crate::entity::{test::*, *}; -impl From for TestcaseId { - fn from(value: i32) -> Self { - Self { id: value } - } -} -impl From for i32 { - fn from(value: TestcaseId) -> Self { - value.id - } -} - impl From for TestcaseFullInfo { fn from(value: Model) -> Self { TestcaseFullInfo { @@ -37,7 +26,7 @@ impl From for TestcaseInfo { } #[async_trait] -impl TestcaseSet for Arc { +impl TestcaseSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/endpoint/token.rs b/backend/src/endpoint/token.rs index 1ce66254..9f5744cf 100644 --- a/backend/src/endpoint/token.rs +++ b/backend/src/endpoint/token.rs @@ -2,20 +2,14 @@ use std::time::Duration; use super::tools::*; -use crate::grpc::backend::token_set_server::*; -use crate::grpc::{backend::*, into_chrono, into_prost}; +use grpc::backend::token_set_server::*; +use grpc::backend::*; use crate::entity::token::*; use crate::entity::*; const TOKEN_LIMIT: u64 = 16; -impl From for Token { - fn from(value: String) -> Self { - Token { signature: value } - } -} - impl From for Token { fn from(value: Model) -> Self { Token { @@ -28,7 +22,7 @@ impl From for Token { } #[async_trait] -impl TokenSet for Arc { +impl TokenSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list(&self, req: Request) -> Result, Status> { let (auth, req) = self @@ -95,7 +89,7 @@ impl TokenSet for Arc { #[instrument(skip_all, level = "debug")] async fn refresh( &self, - req: Request, + req: Request, ) -> Result, Status> { let (meta, _, payload) = req.into_parts(); diff --git a/backend/src/endpoint/user.rs b/backend/src/endpoint/user.rs index f251b1e2..9abf467c 100644 --- a/backend/src/endpoint/user.rs +++ b/backend/src/endpoint/user.rs @@ -1,23 +1,11 @@ use super::tools::*; -use crate::grpc::backend::user_set_server::*; -use crate::grpc::backend::*; +use grpc::backend::user_set_server::*; +use grpc::backend::*; use crate::entity::user; use crate::entity::user::*; -impl From for UserId { - fn from(value: i32) -> Self { - Self { id: value } - } -} - -impl From for i32 { - fn from(value: UserId) -> Self { - value.id - } -} - impl From for UserInfo { fn from(value: Model) -> Self { UserInfo { @@ -30,7 +18,7 @@ impl From for UserInfo { } #[async_trait] -impl UserSet for Arc { +impl UserSet for ArcServer { #[instrument(skip_all, level = "debug")] async fn list( &self, diff --git a/backend/src/entity/announcement.rs b/backend/src/entity/announcement.rs index 61b5bb85..26257e22 100644 --- a/backend/src/entity/announcement.rs +++ b/backend/src/entity/announcement.rs @@ -1,6 +1,6 @@ use tracing::instrument; -use crate::grpc::backend::AnnouncementSortBy; +use grpc::backend::AnnouncementSortBy; use super::*; diff --git a/backend/src/entity/contest.rs b/backend/src/entity/contest.rs index cab6a048..71540f92 100644 --- a/backend/src/entity/contest.rs +++ b/backend/src/entity/contest.rs @@ -4,7 +4,8 @@ use chrono::Local; use sea_orm::Statement; use tracing::{instrument, Instrument}; -use crate::{grpc::backend::ContestSortBy, union}; +use crate::union; +use grpc::backend::ContestSortBy; use super::*; diff --git a/backend/src/entity/problem.rs b/backend/src/entity/problem.rs index cf15b14f..8330951c 100644 --- a/backend/src/entity/problem.rs +++ b/backend/src/entity/problem.rs @@ -6,9 +6,9 @@ use std::ops::Deref; use sea_orm::Statement; use tracing::{instrument, Instrument}; -use crate::{grpc::backend::ProblemSortBy, union}; - use super::*; +use crate::union; +use grpc::backend::ProblemSortBy; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] #[sea_orm(table_name = "problem")] diff --git a/backend/src/entity/user.rs b/backend/src/entity/user.rs index 0aad0a13..a03768e9 100644 --- a/backend/src/entity/user.rs +++ b/backend/src/entity/user.rs @@ -1,7 +1,7 @@ use sea_orm::{QueryOrder, QuerySelect}; use tracing::instrument; -use crate::grpc::backend::UserSortBy; +use grpc::backend::UserSortBy; use self::util::paginator::Remain; diff --git a/backend/src/grpc.rs b/backend/src/grpc.rs deleted file mode 100644 index 3698c1f9..00000000 --- a/backend/src/grpc.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::hash::Hash; - -pub mod judger { - tonic::include_proto!("oj.judger"); -} -pub mod backend { - tonic::include_proto!("oj.backend"); -} -/// convert chrono's time to prost_types's -pub fn into_prost(time: chrono::NaiveDateTime) -> prost_types::Timestamp { - prost_types::Timestamp { - seconds: time.and_utc().timestamp(), - nanos: time.and_utc().timestamp_subsec_nanos() as i32, - } -} -/// convert prost_types's time to chrono's -pub fn into_chrono(time: prost_types::Timestamp) -> chrono::NaiveDateTime { - match chrono::DateTime::from_timestamp(time.seconds, time.nanos as u32) { - Some(x) => x.naive_utc(), - None => chrono::NaiveDateTime::default(), - } -} -/// server side stream in tonic -pub type TonicStream = - std::pin::Pin> + Send>>; - -impl Hash for judger::LangInfo { - fn hash(&self, state: &mut H) { - self.lang_uid.hash(state); - } -} - -impl PartialOrd for judger::LangInfo { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.lang_uid.cmp(&other.lang_uid)) - } -} - -impl Ord for judger::LangInfo { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.lang_uid.cmp(&other.lang_uid) - } -} - -impl Eq for judger::LangInfo {} diff --git a/backend/src/init/config.rs b/backend/src/init/config.rs index d3e6ac7e..b10ca23a 100644 --- a/backend/src/init/config.rs +++ b/backend/src/init/config.rs @@ -119,7 +119,7 @@ impl Default for Imgur { } pub async fn init() -> super::Result { - let config_path=CONFIG_PATH.as_path(); + let config_path = CONFIG_PATH.as_path(); if fs::metadata(config_path).await.is_ok() { let mut buf = Vec::new(); let mut config = fs::File::open(config_path) @@ -134,7 +134,10 @@ pub async fn init() -> super::Result { let config: GlobalConfig = toml::from_str(config).map_err(Error::ConfigParse)?; Ok(config) } else { - println!("Unable to find {:?}, generating default config", config_path); + println!( + "Unable to find {:?}, generating default config", + config_path + ); let config: GlobalConfig = toml::from_str("").unwrap(); let config_txt = toml::to_string(&config).unwrap(); diff --git a/backend/src/main.rs b/backend/src/main.rs index b3de2f8c..6556f100 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,7 +1,6 @@ pub mod controller; pub mod endpoint; pub mod entity; -pub mod grpc; pub mod init; pub mod macro_tool; pub mod server; @@ -11,6 +10,9 @@ pub mod util; #[global_allocator] static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; +pub type TonicStream = + std::pin::Pin> + Send>>; + #[tokio::main] async fn main() { let server = server::Server::new().await.unwrap(); diff --git a/backend/src/server.rs b/backend/src/server.rs index 3a5aeb21..2d01e2f1 100644 --- a/backend/src/server.rs +++ b/backend/src/server.rs @@ -1,28 +1,27 @@ -use std::sync::Arc; - -use http::header::HeaderName; -use sea_orm::DatabaseConnection; -use spin::Mutex; -use tonic::transport::{self, Identity, ServerTlsConfig}; -use tonic_web::GrpcWebLayer; -use tower_http::cors::{AllowOrigin, Any, CorsLayer}; -use tracing::{span, Instrument, Level}; +use std::{ops::Deref, sync::Arc}; use crate::{ controller::*, - grpc::backend::{ - announcement_set_server::AnnouncementSetServer, chat_set_server::ChatSetServer, - contest_set_server::ContestSetServer, education_set_server::EducationSetServer, - problem_set_server::ProblemSetServer, submit_set_server::SubmitSetServer, - testcase_set_server::TestcaseSetServer, token_set_server::TokenSetServer, - user_set_server::UserSetServer, - }, init::{ config::{self, GlobalConfig}, logger::{self, OtelGuard}, Error, }, }; +use grpc::backend::{ + announcement_set_server::AnnouncementSetServer, chat_set_server::ChatSetServer, + contest_set_server::ContestSetServer, education_set_server::EducationSetServer, + problem_set_server::ProblemSetServer, submit_set_server::SubmitSetServer, + testcase_set_server::TestcaseSetServer, token_set_server::TokenSetServer, + user_set_server::UserSetServer, +}; +use http::header::HeaderName; +use sea_orm::DatabaseConnection; +use spin::Mutex; +use tonic::transport::{self, Identity, ServerTlsConfig}; +use tonic_web::GrpcWebLayer; +use tower_http::cors::{AllowOrigin, Any, CorsLayer}; +use tracing::{span, Instrument, Level}; const MAX_FRAME_SIZE: u32 = 1024 * 1024 * 8; @@ -54,6 +53,17 @@ pub struct Server { _otel_guard: OtelGuard, } +#[derive(Clone)] +pub struct ArcServer(Arc); + +impl Deref for ArcServer { + type Target = Server; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl Server { /// Create a new server /// @@ -112,6 +122,7 @@ impl Server { } /// Start the server pub async fn start(self: Arc) { + let self_ = ArcServer(self); let cors = CorsLayer::new() .allow_headers( DEFAULT_ALLOW_HEADERS @@ -130,7 +141,7 @@ impl Server { .allow_origin(AllowOrigin::mirror_request()) .allow_methods(Any); - let server = match self.identity.lock().take() { + let server = match self_.0.identity.lock().take() { Some(identity) => transport::Server::builder() .tls_config(ServerTlsConfig::new().identity(identity)) .unwrap(), @@ -141,20 +152,23 @@ impl Server { .layer(cors) .layer(GrpcWebLayer::new()) .max_frame_size(Some(MAX_FRAME_SIZE)) - .add_service(ProblemSetServer::new(self.clone())) - .add_service(EducationSetServer::new(self.clone())) - .add_service(UserSetServer::new(self.clone())) - .add_service(TokenSetServer::new(self.clone())) - .add_service(ContestSetServer::new(self.clone())) - .add_service(TestcaseSetServer::new(self.clone())) - .add_service(SubmitSetServer::new(self.clone())) - .add_service(ChatSetServer::new(self.clone())) - .add_service(AnnouncementSetServer::new(self.clone())) - .serve_with_shutdown(self.config.bind_address.clone().parse().unwrap(), async { - if tokio::signal::ctrl_c().await.is_err() { - tracing::warn!("graceful_shutdown"); - } - }) + .add_service(ProblemSetServer::new(self_.clone())) + .add_service(EducationSetServer::new(self_.clone())) + .add_service(UserSetServer::new(self_.clone())) + .add_service(TokenSetServer::new(self_.clone())) + .add_service(ContestSetServer::new(self_.clone())) + .add_service(TestcaseSetServer::new(self_.clone())) + .add_service(SubmitSetServer::new(self_.clone())) + .add_service(ChatSetServer::new(self_.clone())) + .add_service(AnnouncementSetServer::new(self_.clone())) + .serve_with_shutdown( + self_.0.config.bind_address.clone().parse().unwrap(), + async { + if tokio::signal::ctrl_c().await.is_err() { + tracing::warn!("graceful_shutdown"); + } + }, + ) .await .unwrap(); } diff --git a/backend/src/util/auth.rs b/backend/src/util/auth.rs index d2c5ff22..cf8bd428 100644 --- a/backend/src/util/auth.rs +++ b/backend/src/util/auth.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::grpc::backend::Role; +use grpc::backend::Role; use super::error::Error; diff --git a/backend/src/util/code.rs b/backend/src/util/code.rs index 47ac954d..26cf4218 100644 --- a/backend/src/util/code.rs +++ b/backend/src/util/code.rs @@ -1,5 +1,5 @@ -use crate::grpc::backend::StateCode as BackendCode; -use crate::grpc::judger::JudgerCode; +use grpc::backend::StateCode as BackendCode; +use grpc::judger::JudgerCode; /// Stablized JudgeResponse Code, store in database #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/backend/src/util/error.rs b/backend/src/util/error.rs index 12ceacfc..b0bd71d2 100644 --- a/backend/src/util/error.rs +++ b/backend/src/util/error.rs @@ -135,7 +135,7 @@ impl Tracing { log_id, } } - pub fn report(self)->String{ + pub fn report(self) -> String { format!( "trace_id: {}, span_id: {}, log_id: {}", self.trace_id, self.span_id, self.log_id diff --git a/backend/src/util/mod.rs b/backend/src/util/mod.rs index 36e77244..d673ca6d 100644 --- a/backend/src/util/mod.rs +++ b/backend/src/util/mod.rs @@ -2,3 +2,4 @@ pub mod auth; pub mod code; pub mod error; pub mod parse; +pub mod time; diff --git a/backend/src/util/time.rs b/backend/src/util/time.rs new file mode 100644 index 00000000..c419afd0 --- /dev/null +++ b/backend/src/util/time.rs @@ -0,0 +1,13 @@ +pub fn into_prost(time: chrono::NaiveDateTime) -> prost_wkt_types::Timestamp { + prost_wkt_types::Timestamp { + seconds: time.and_utc().timestamp(), + nanos: time.and_utc().timestamp_subsec_nanos() as i32, + } +} +/// convert prost_types's time to chrono's +pub fn into_chrono(time: prost_wkt_types::Timestamp) -> chrono::NaiveDateTime { + match chrono::DateTime::from_timestamp(time.seconds, time.nanos as u32) { + Some(x) => x.naive_utc(), + None => chrono::NaiveDateTime::default(), + } +} diff --git a/grpc/Cargo.toml b/grpc/Cargo.toml index 8781572f..b6fc2d82 100644 --- a/grpc/Cargo.toml +++ b/grpc/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +paste = "1.0.15" prost = { workspace = true } prost-wkt = { workspace = true } prost-wkt-types = { workspace = true } diff --git a/grpc/src/backend.rs b/grpc/src/backend.rs new file mode 100644 index 00000000..f78f901d --- /dev/null +++ b/grpc/src/backend.rs @@ -0,0 +1,10 @@ +pub mod backend { + tonic::include_proto!("oj.backend"); +} +pub use backend::*; + +impl From for backend::Token { + fn from(value: String) -> Self { + Token { signature: value } + } +} diff --git a/grpc/src/bridge.rs b/grpc/src/bridge.rs new file mode 100644 index 00000000..2d41e21b --- /dev/null +++ b/grpc/src/bridge.rs @@ -0,0 +1,32 @@ +use crate::backend::{self, playground_result, PlaygroundResult}; +use crate::judger::{self, exec_result, ExecResult}; + +impl From for PlaygroundResult { + fn from(value: ExecResult) -> Self { + PlaygroundResult { + result: Some(match value.result.unwrap() { + exec_result::Result::Output(x) => playground_result::Result::Output(x), + exec_result::Result::Log(x) => playground_result::Result::Compile(x.into()), + }), + } + } +} +impl From for backend::Log { + fn from(value: judger::Log) -> Self { + backend::Log { + level: value.level, + msg: value.msg, + } + } +} + +impl From for backend::Language { + fn from(value: judger::LangInfo) -> Self { + backend::Language { + lang_uid: value.lang_uid, + lang_name: value.lang_name, + info: value.info, + lang_ext: value.lang_ext, + } + } +} diff --git a/grpc/src/ids.rs b/grpc/src/ids.rs new file mode 100644 index 00000000..fae1610c --- /dev/null +++ b/grpc/src/ids.rs @@ -0,0 +1,29 @@ +use crate::backend::*; +use paste::paste; + +macro_rules! impl_ids { + ($entity:ident) => { + paste! { + impl From for [<$entity Id>] { + fn from(value: i32) -> Self { + Self { id: value } + } + } + + impl From<[<$entity Id>]> for i32 { + fn from(value: [<$entity Id>]) -> Self { + value.id + } + } + } + }; +} + +impl_ids!(Problem); +impl_ids!(Announcement); +impl_ids!(Contest); +impl_ids!(Chat); +impl_ids!(Testcase); +impl_ids!(Education); +impl_ids!(Submit); +impl_ids!(User); diff --git a/grpc/src/judger.rs b/grpc/src/judger.rs new file mode 100644 index 00000000..ecbe4ccb --- /dev/null +++ b/grpc/src/judger.rs @@ -0,0 +1,27 @@ +#[cfg(feature = "judger")] +#[allow(clippy::all, non_local_definitions)] +pub mod judger { + tonic::include_proto!("oj.judger"); +} + +pub use judger::*; + +impl std::hash::Hash for judger::LangInfo { + fn hash(&self, state: &mut H) { + self.lang_uid.hash(state); + } +} + +impl PartialOrd for judger::LangInfo { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.lang_uid.cmp(&other.lang_uid)) + } +} + +impl Ord for judger::LangInfo { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.lang_uid.cmp(&other.lang_uid) + } +} + +impl Eq for judger::LangInfo {} diff --git a/grpc/src/lib.rs b/grpc/src/lib.rs index 8deda762..137736a7 100644 --- a/grpc/src/lib.rs +++ b/grpc/src/lib.rs @@ -1,11 +1,13 @@ #[cfg(feature = "backend")] -#[allow(clippy::all, non_local_definitions)] -pub mod backend { - tonic::include_proto!("oj.backend"); -} +mod ids; +#[cfg(feature = "backend")] #[cfg(feature = "judger")] +mod bridge; + +#[cfg(feature = "backend")] #[allow(clippy::all, non_local_definitions)] -pub mod judger { - tonic::include_proto!("oj.judger"); -} +pub mod backend; + +#[cfg(feature = "judger")] +pub mod judger; diff --git a/judger/Cargo.toml b/judger/Cargo.toml index 878c079e..5faedc7f 100644 --- a/judger/Cargo.toml +++ b/judger/Cargo.toml @@ -22,7 +22,7 @@ async-stream = "0.3.5" [dependencies.grpc] path = "../grpc" -features = ["backend"] +features = ["judger", "server"] default-features = false [dependencies.log]