diff --git a/.github/workflows/checker.yaml b/.github/workflows/checker.yaml index 064a5666d..3ae96c692 100644 --- a/.github/workflows/checker.yaml +++ b/.github/workflows/checker.yaml @@ -21,7 +21,7 @@ jobs: - name: Rust toolchain Stable uses: actions-rs/toolchain@v1 with: - toolchain: 1.78.0 + toolchain: 1.80.1 components: clippy default: true - name: Rust toolchain Nightly diff --git a/Cargo.toml b/Cargo.toml index df9906005..bc78e62e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,11 +26,16 @@ debug = 1 members = [ "libs/*", "persistence/persistence", + "persistence/dao/*", + "persistence/database/*", + "persistence/migrate/*", + "persistence/models/*", "./macros/*", "./middle-server/*", "./logic/*", "./global/*", "./service/*", + "http_service/ceobe_operation/*", ] [workspace.dependencies] @@ -48,7 +53,8 @@ once_cell = "1" reqwest = { version = "0.12", default-features = false, features = [ "rustls-tls", ] } -resp-result = { version = "0.7", package = "axum-resp-result"} +axum-resp-result = { version = "0.7.1"} + sea-orm = { version = "0.12", default-features = false, features = [ "sqlx-mysql", "runtime-tokio-rustls", @@ -103,6 +109,10 @@ hex = "0.4" serde_qs = "0.13.0" request-clients = { version = "0.1.0", path = "middle-server/request-clients" } mime = "0.3.16" +serve-utils = {version = "0.1.0", path="libs/serve_utils"} +tower = { version = "0.4", features = ["limit"] } +status-err={path = "./libs/status-err"} + [dependencies] @@ -134,7 +144,7 @@ reqwest = { workspace = true } sha2 = { workspace = true } tap = { workspace = true } thiserror = { workspace = true } -tower = { version = "0.4", features = ["limit"] } +tower.workspace = true tower-http = { version = "0.5", features = ["trace", "catch-panic", "set-header", "compression-full", "auth", "add-extension", "cors"] } typed-builder = { workspace = true } url = { workspace = true } @@ -156,6 +166,9 @@ bitmap-convert.workspace = true bitmaps.workspace = true persistence = { workspace = true, features = ["prelude", "migrate"] } tencent-cloud-server.workspace = true +semver = { version = "1.0.23", features = ["serde"] } +release_version_service = { version = "0.1.0", path = "http_service/ceobe_operation/release_version_service" } +serve_utils = { version = "0.1.0", path = "libs/serve_utils" } mimalloc = "0.1.43" @@ -179,9 +192,9 @@ path = "./libs/range-limit" path = "./libs/logger" [dependencies.status-err] -path = "./libs/status-err" +workspace = true -[dependencies.resp-result] +[dependencies.axum-resp-result] workspace = true [dependencies.checker] diff --git a/README.md b/README.md index 810518360..7484c1700 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,17 @@ | `database`/`db` | `logger` | 否 | `bool` | 是否开始数据库操作日志 | 默认关闭 | | `logger`/`log` | `to_stdout` | 否 | `bool` | 同时将日志输出到 Stdout | 默认为 true | | `logger`/`log` | `to_file` | 否 | `String` | 同时将日志输出的文件 | 有值将会同时将日志输出到指定文件 | - | `logger`/`log` | `level` | 是 | `off` 或者
`error`或者
`warm` 或者
`info` 或者
`debug` 或者
`trace` | 日志输出过滤等级 | 无 | + | `logger`/`log` | `level` | 是 | `off` 或者
`error`或者
`warm` 或者
`info` 或者
`debug` + 或者
`trace` | 日志输出过滤等级 | 无 | | `resp_result`/ `rresult` | `body` | 是 | `String` | 响应成功时的响应体字段名称 | 无 | | `resp_result`/ `rresult` | `err-msg` | 是 | `String` | 响应失败时异常字段名称 | 无 | | `resp_result`/ `rresult` | `fix-field` | 是 | `bool` | 响应体固定字段 | 如果无需该字段值将为`null` | - | `resp_result`/ `rresult` | `bool-status` | 否 | `Option` | 使用一个 `bool` 类型标记响应成功与否 | 该字段缺省表示不使用 | - | `resp_result`/ `rresult` | `body-extra-err` | 否 | `Option` | 额外的异常信息在响应体中字段 | 该字段缺省表示不使用 | - | `resp_result`/ `rresult` | `header-extra-err` | 否 | `Option` | 额外的异常信息在响应头中的字段名称 | 该字段缺省表示不使用 | + | `resp_result`/ `rresult` | `bool-status` | 否 | `Option` | 使用一个 `bool` 类型标记响应成功与否 | + 该字段缺省表示不使用 | + | `resp_result`/ `rresult` | `body-extra-err` | 否 | `Option` | 额外的异常信息在响应体中字段 | + 该字段缺省表示不使用 | + | `resp_result`/ `rresult` | `header-extra-err` | 否 | `Option` | 额外的异常信息在响应头中的字段名称 | + 该字段缺省表示不使用 | | `mongodb`/ `mongo` | `username` | 是 | `String` | Mongodb 进行数据库连接使用的用户 | 该用户需要完整 Admin 权限 | | `mongodb`/ `mongo` | `password` | 是 | `String` | Mongodb 进行数据库连接使用的用户密码 | 无 | | `mongodb`/ `mongo` | `host` | 否 | `String` | Mongodb 进行数据库连接使用的 host | 默认为`localhost` | @@ -117,20 +121,20 @@ | `M` | 数据未变更 | | `A` | 权限认证异常 | | `Q` | 七牛云上传异常 | - | `L` | 日志报告异常 | + | `L` | 日志报告异常 | - 服务异常 | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :--------------------- | + | :--: | :----: | :------: | :--------------------- | | `F` | 0001 | 500 | 服务器发生未预期 Panic | | `F` | 0002 | 500 | 管道发生未预期关闭 | - Io 异常 | 前缀 | 异常码 | httpCode | 说明 | - | :--: |:----:| :------: |:------------------| + | :--: |:----:| :------: |:------------------| | `I` | 0001 | 500 | `std::io::Error` | - | `I` | 0002 | 500 | `core::fmt::Error`| + | `I` | 0002 | 500 | `core::fmt::Error`| - 类型转换异常 | 前缀 | 异常码 | httpCode | 说明 | @@ -144,37 +148,38 @@ | `P` | 0007 | 500 | 非法 Http 请求头内容 | | `P` | 0008 | 500 | UUID解析异常 | -- 数据校验异常 - - | 前缀 | 异常码 | httpCode | 说明 | - | :--: |:----:| :------: |:------------------------------------| - | `C` | 0001 | 400 | 范围检查未通过 | - | `C` | 0002 | 400 | 饼学大厦 id 格式不是 {int}.{int} | - | `C` | 0003 | 400 | 错误的 Fraction 值范围(0~5) | - | `C` | 0004 | 400 | `Json` 序列化/反序列化异常 | - | `C` | 0005 | 400 | `Path` 数据加载异常 | - | `C` | 0006 | 400 | 未知的预期确信度等级 | - | `C` | 0007 | 400 | `Query` 加载异常 | - | `C` | 0008 | 409 | 饼学大厦的 Id 已经存在 | - | `C` | 0009 | 400 | BV 号格式错误 | - | `C` | 000A | 400 | 版本号格式错误 | - | `C` | 000B | 409 | 版本号已经被使用 | - | `C` | 000C | 400 | `Bincode` 序列化/反序列化异常 | - | `C` | 000D | 500 | 存在多个可用的资源全可用的记录 | - | `C` | 000E | 400 | 预期为 0 值取得非 0 值 | - | `C` | 000F | 400 | 获取`MultiPart`异常 | - | `C` | 0010 | 400 | 解析`MultiPart`异常 | - | `C` | 0011 | 400 | `MultiPart` Field 不存在 | - | `C` | 0012 | 500 | 平台下存在数据源,无法删除平台 | - | `C` | 0013 | 400 | 未找到平台 | - | `C` | 0014 | 400 | `{origin}` 无法被 `{RHS}` 整除,余数`{rem}` | - | `C` | 0015 | 400 | Json 对象不符合预期 | -- | `C` | 0016 | 400 | Bson 序列化异常 | + 数据校验异常 + + | 前缀 | 异常码 | httpCode | 说明 | + |:-----:|:----:|:--------:|:------------------------------------| + | `C` | 0001 | 400 | 范围检查未通过 | + | `C` | 0002 | 400 | 饼学大厦 id 格式不是 {int}.{int} | + | `C` | 0003 | 400 | 错误的 Fraction 值范围(0~5) | + | `C` | 0004 | 400 | `Json` 序列化/反序列化异常 | + | `C` | 0005 | 400 | `Path` 数据加载异常 | + | `C` | 0006 | 400 | 未知的预期确信度等级 | + | `C` | 0007 | 400 | `Query` 加载异常 | + | `C` | 0008 | 409 | 饼学大厦的 Id 已经存在 | + | `C` | 0009 | 400 | BV 号格式错误 | + | `C` | 000A | 400 | 版本号格式错误 | + | `C` | 000B | 409 | 版本号已经被使用 | + | `C` | 000C | 400 | `Bincode` 序列化/反序列化异常 | + | `C` | 000D | 500 | 存在多个可用的资源全可用的记录 | + | `C` | 000E | 400 | 预期为 0 值取得非 0 值 | + | `C` | 000F | 400 | 获取`MultiPart`异常 | + | `C` | 0010 | 400 | 解析`MultiPart`异常 | + | `C` | 0011 | 400 | `MultiPart` Field 不存在 | + | `C` | 0012 | 500 | 平台下存在数据源,无法删除平台 | + | `C` | 0013 | 400 | 未找到平台 | + | `C` | 0014 | 400 | `{origin}` 无法被 `{RHS}` 整除,余数`{rem}` | + | `C` | 0015 | 400 | Json 对象不符合预期 | + | `C` | 0016 | 400 | Bson 序列化异常 | + | `C` | 0017 | 409 | 版本号过旧 | - 数据库异常(SeaOrm) | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :------------------- | + | :--: | :----: | :------: | :------------------- | | `D` | 0001 | 500 | 数据库连接失败 | | `D` | 0002 | 500 | 数据库请求操作失败 | | `D` | 0003 | 500 | 数据库查询失败 | @@ -187,7 +192,7 @@ - 数据库异常(MongoDb) | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :----------------------- | + | :--: | :----: | :------: | :----------------------- | | `G` | 0001 | 500 | 非法参数 | | `G` | 0002 | 500 | 权限不足 | | `G` | 0003 | 500 | `Bson`反序列化失败 | @@ -211,7 +216,7 @@ - Redis 异常 | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :------------------------------- | + | :--: | :----: | :------: | :------------------------------- | | `R` | 0001 | 500 | 无效响应 | | `R` | 0002 | 500 | 权限不足 | | `R` | 0003 | 500 | 类型不匹配 | @@ -233,7 +238,7 @@ - 数据未变更 | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :----------------------------- | + | :--: | :----: | :------: | :----------------------------- | | `M` | 0001 | 304 | Ceobe 在当前提供时间戳下无更新 | - 资源查找异常 @@ -251,7 +256,7 @@ - 权限认证异常 | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :------------------- | + | :--: | :----: | :------: | :------------------- | | `A` | 0001 | 401 | 缺少 Token 字段 | | `A` | 0002 | 401 | 权限不足 | | `A` | 0003 | 404 | Token 对应信息不存在 | @@ -266,13 +271,13 @@ - 七牛云上传异常 | 前缀 | 异常码 | httpCode | 说明 | - | :--: | :----: | :------: | :------------------- | + | :--: | :----: | :------: | :------------------- | | `Q` | 0001 | 500 | 上传七牛云时出现异常 | - 日志报告异常 |前缀 | 异常码 | httpCode | 说明| - | :--: | :----: | :------: | :------------------- | + | :--: | :----: | :------: | :------------------- | | `L` | 0001 | 500 | 与Grpc服务端建立连接失败 | | `L` | 0002 | 500 | Grpc service 返回异常响应 | | `L` | 0003 | 500 | 发送日志时收到失败响应 | diff --git a/global/redis_global/src/type_bind/hash.rs b/global/redis_global/src/type_bind/hash.rs index d4e9c7b8a..7c07eac85 100644 --- a/global/redis_global/src/type_bind/hash.rs +++ b/global/redis_global/src/type_bind/hash.rs @@ -40,12 +40,11 @@ where self.redis.hexists(&*self.key, field).await } - pub async fn set<'arg, RV, F>( + pub async fn set<'arg, F>( &mut self, field: F, value: T::Input, - ) -> RedisResult + ) -> RedisResult<()> where F: ToRedisArgs + Send + Sync + 'arg, - RV: FromRedisValue, { self.redis.hset(&*self.key, field, value).await } @@ -97,10 +96,9 @@ where /// /// ## 参考 /// - [`AsyncCommands::hdel`] - pub async fn remove<'arg, RV, F>(&mut self, field: F) -> RedisResult + pub async fn remove<'arg, F>(&mut self, field: F) -> RedisResult<()> where F: ToRedisArgs + Send + Sync + 'arg, - RV: FromRedisValue, { self.redis.hdel(&*self.key, field).await } diff --git a/global/redis_global/src/type_bind/normal.rs b/global/redis_global/src/type_bind/normal.rs index 15b8dd02d..56103e628 100644 --- a/global/redis_global/src/type_bind/normal.rs +++ b/global/redis_global/src/type_bind/normal.rs @@ -53,12 +53,10 @@ where /// /// ## 参考 /// - [`AsyncCommands::set_nx`] - pub async fn set_if_not_exist( + pub async fn set_if_not_exist( &mut self, value: T::Input, - ) -> RedisResult - where - RV: FromRedisValue, - { + ) -> RedisResult<()> +where { self.redis.set_nx(&*self.key, value).await } @@ -66,12 +64,9 @@ where /// /// ## 参考 /// - [`AsyncCommands::set_ex`] - pub async fn set_with_expire( + pub async fn set_with_expire( &mut self, value: T::Input, duration: Duration, - ) -> RedisResult - where - RV: FromRedisValue, - { + ) -> RedisResult<()> { self.redis .set_ex(&*self.key, value, duration.as_secs() as _) .await diff --git a/http_service/ceobe_operation/release_version_service/Cargo.toml b/http_service/ceobe_operation/release_version_service/Cargo.toml new file mode 100644 index 000000000..b35827cdd --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "release_version_service" +version = "0.1.0" +edition = "2021" + +[dependencies] +persistence = { workspace = true, features = ["model-ceobe-operate", "help-crates"] } +semver = "1.0.23" +serve_utils = { version = "0.1.0", path = "../../../libs/serve_utils" } +serde = { version = "1.0.201", features = ["derive"] } +thiserror.workspace = true +status-err.workspace = true +http.workspace = true +axum-resp-result.workspace = true +tracing.workspace = true +serde_json.workspace = true +tencent-cloud-server.workspace = true +checker = { version = "0.1.0", path = "../../../libs/checker" } +page_size.workspace = true +ceobe_operation_logic = { version = "0.1.0", path = "../../../logic/ceobe_operation_logic" } diff --git a/http_service/ceobe_operation/release_version_service/src/error.rs b/http_service/ceobe_operation/release_version_service/src/error.rs new file mode 100644 index 000000000..639bd0c1e --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/error.rs @@ -0,0 +1,23 @@ +use checker::prefabs::num_check::NonZeroUnsignedError; +use serve_utils::{ + axum::extract::rejection::{JsonRejection, QueryRejection}, + status_err::StatusErr, + ControllerError, ThisError, +}; + +#[derive(Debug, ThisError, StatusErr)] +#[status_err(resp_err)] +pub enum Error { + #[error(transparent)] + Query(#[from] QueryRejection), + #[error(transparent)] + Json(#[from] JsonRejection), + #[error(transparent)] + InvalidPaginator(#[from] NonZeroUnsignedError), + #[error(transparent)] + Logic(#[from] ceobe_operation_logic::release_version::Error), +} + +impl ControllerError for crate::ReleaseVersionController { + type Error = Error; +} diff --git a/http_service/ceobe_operation/release_version_service/src/handlers.rs b/http_service/ceobe_operation/release_version_service/src/handlers.rs new file mode 100644 index 000000000..cc386a7d5 --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/handlers.rs @@ -0,0 +1,49 @@ +use persistence::operate::FromRef; +use serve_utils::{ + axum::{ + routing::{get, post}, + Router, + }, + endpoint::{AdminEnd, CDN}, + ControllerRoute, HandlerMapReject, HandlerResult, +}; +use tencent_cloud_server::axum_starter::{ + PartTencentCloudManagerState, RequestClient, +}; + +mod admin_end; +mod cdn; + +pub(crate) type Result = HandlerResult; +pub(crate) type MapRejecter = + HandlerMapReject; + +impl ControllerRoute for crate::ReleaseVersionController +where + S: Send + Clone + Sync + 'static, + PartTencentCloudManagerState: FromRef, + RequestClient: FromRef, +{ + const BASE_URI: &'static str = "/version"; + + fn route(self) -> Router { + Router::new().route("/fetch", get(Self::fetch_version)) + } +} + +impl ControllerRoute for crate::ReleaseVersionController +where + S: Send + Clone + Sync + 'static, + PartTencentCloudManagerState: FromRef, + RequestClient: FromRef, +{ + const BASE_URI: &'static str = "/releaseVersion"; + + fn route(self) -> Router { + Router::new() + .route("/markDelete", post(Self::make_delete_version)) + .route("/create", post(Self::new_version)) + .route("/all", get(Self::all_version)) + .route("/modify", post(Self::modify_description)) + } +} diff --git a/http_service/ceobe_operation/release_version_service/src/handlers/admin_end.rs b/http_service/ceobe_operation/release_version_service/src/handlers/admin_end.rs new file mode 100644 index 000000000..936e71245 --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/handlers/admin_end.rs @@ -0,0 +1,92 @@ +use ceobe_operation_logic::{ + release_version::ReleaseVersionLogic, CeobeOperationLogic, +}; +use checker::{ + prefabs::option_checker::OptionChecker, CheckExtract, QueryCheckExtract, +}; +use page_size::{request::PageSizeChecker, response::ListWithPageInfo}; +use persistence::ceobe_operate::models::version::models::ReleaseVersion; +use serve_utils::{ + axum::{extract::Query, Json}, + axum_resp_result::{resp_result, MapReject}, + tracing::instrument, + ValueField, +}; + +use crate::{ + error::Error, + handlers::{MapRejecter, Result}, + view::{ + QueryReleaseVersion, QueryVersionFilter, QueryVersionUpdate, + UpdatePayload, + }, +}; + +impl crate::ReleaseVersionController { + #[resp_result] + #[instrument(skip_all,fields(version = %arg_1.0))] + pub async fn make_delete_version( + logic: CeobeOperationLogic, + MapReject(QueryReleaseVersion { + version: ValueField(version), + platform, + }): MapRejecter< + Query>>, + >, + ) -> Result<()> { + logic.mark_deleted(&version, &platform).await?; + Ok(()) + } + + #[resp_result] + #[instrument(skip_all)] + pub async fn all_version( + logic: CeobeOperationLogic, + CheckExtract(paginator): QueryCheckExtract< + OptionChecker, + Error, + >, + MapReject(filter): MapRejecter>>, + ) -> Result> { + let QueryVersionFilter { platform, deleted } = + filter.unwrap_or_default(); + let ret = logic.all(paginator, platform, deleted).await?; + + Ok(ret) + } + + #[resp_result] + #[instrument(skip_all,fields(version = %(arg_1.0.version)))] + pub async fn new_version( + logic: CeobeOperationLogic, + MapReject(release): MapRejecter>, + ) -> Result<()> { + logic.create_new(release).await?; + Ok(()) + } + + #[resp_result] + #[instrument(skip_all,fields( + version = %(arg_1.0.version), + ))] + pub async fn modify_description( + logic: CeobeOperationLogic, + MapReject(QueryVersionUpdate { + version: + QueryReleaseVersion { + version: ValueField(version), + platform, + }, + set: + UpdatePayload { + description, + download_source, + }, + }): MapRejecter>, + ) -> Result<()> { + logic + .update(version, platform, description, download_source) + .await?; + Ok(()) + } +} diff --git a/http_service/ceobe_operation/release_version_service/src/handlers/cdn.rs b/http_service/ceobe_operation/release_version_service/src/handlers/cdn.rs new file mode 100644 index 000000000..8e57544e9 --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/handlers/cdn.rs @@ -0,0 +1,28 @@ +use ceobe_operation_logic::{ + release_version::ReleaseVersionLogic, CeobeOperationLogic, +}; +use persistence::ceobe_operate::models::version::models::ReleaseVersion; +use serve_utils::{ + axum::extract::Query, + axum_resp_result::{resp_result, MapReject}, + tracing::instrument, + OptionField, +}; + +use super::{MapRejecter, Result}; +use crate::view::QueryReleaseVersion; +impl crate::ReleaseVersionController { + #[resp_result] + #[instrument(skip_all,fields(version = %arg_1.0))] + pub async fn fetch_version( + logic: CeobeOperationLogic, + MapReject(QueryReleaseVersion { + version: OptionField(version), + platform, + }): MapRejecter>, + ) -> Result { + let release_info = logic.fetch(version, platform).await?; + + Ok(release_info) + } +} diff --git a/http_service/ceobe_operation/release_version_service/src/lib.rs b/http_service/ceobe_operation/release_version_service/src/lib.rs new file mode 100644 index 000000000..f5e8bb2aa --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/lib.rs @@ -0,0 +1,5 @@ +mod error; +mod handlers; +mod view; + +pub struct ReleaseVersionController; diff --git a/http_service/ceobe_operation/release_version_service/src/view.rs b/http_service/ceobe_operation/release_version_service/src/view.rs new file mode 100644 index 000000000..42fe11c37 --- /dev/null +++ b/http_service/ceobe_operation/release_version_service/src/view.rs @@ -0,0 +1,87 @@ +use std::fmt::{Display, Formatter}; + +use persistence::ceobe_operate::models::version::models::{ + DownloadSourceItem, ReleasePlatform, +}; +use semver::Version; +use serde::Deserialize; +use serve_utils::{OptionField, OptionViewField, ValueField}; + +#[derive(Deserialize, Clone, Debug)] +pub struct QueryReleaseVersion< + Version: OptionViewField = OptionField, +> { + #[serde(skip_serializing_if = "OptionViewField::skip_serde")] + pub version: Version, + pub platform: ReleasePlatform, +} + +impl Display for QueryReleaseVersion> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}->{}", self.platform, self.version.0) + } +} + +impl Display for QueryReleaseVersion> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self.version.0 { + None => { + write!(f, "{}", self.platform) + } + Some(ver) => { + write!(f, "{}->{}", self.platform, ver) + } + } + } +} + +#[derive(Debug, Deserialize, Default)] +pub struct QueryVersionFilter { + pub platform: Option, + pub deleted: bool, +} + +impl Display for QueryVersionFilter { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self.platform { + None => { + write!(f, "{{deleted: {} }}", self.deleted) + } + Some(plat) => { + write!(f, "{{deleted: {}, platform: {}}}", self.deleted, plat) + } + } + } +} + +#[derive(Debug, Deserialize)] +pub struct QueryVersionUpdate { + #[serde(flatten)] + pub version: QueryReleaseVersion>, + #[serde(flatten)] + pub set: UpdatePayload, +} +#[derive(Debug, Deserialize, Default)] +pub struct UpdatePayload { + pub description: Option, + pub download_source: Vec, +} + +#[cfg(test)] +mod test { + + use serve_utils::SkipField; + + use crate::view::QueryReleaseVersion; + + #[test] + fn test_de() { + let js = serde_json::json!({ + "platform":"desktop" + }); + let v = serde_json::from_value::>(js) + .expect("Err"); + + println!("{v:?}") + } +} diff --git a/libs/checker/Cargo.toml b/libs/checker/Cargo.toml index 12a39d857..7ee093192 100644 --- a/libs/checker/Cargo.toml +++ b/libs/checker/Cargo.toml @@ -14,7 +14,7 @@ check-obj-macro = { path = "../../macros/check-obj-macro" } num-traits = "0.2" async-trait = { workspace = true } axum = { workspace = true } -resp-result = { workspace = true } +axum-resp-result.workspace = true serde_json = { workspace = true } thiserror = { workspace = true } smallvec = { workspace = true } diff --git a/libs/checker/src/check_prehandle.rs b/libs/checker/src/check_prehandle.rs index 0ca2c3741..028edbeb1 100644 --- a/libs/checker/src/check_prehandle.rs +++ b/libs/checker/src/check_prehandle.rs @@ -6,7 +6,9 @@ use axum::{ http::request::Parts, Form, Json, }; -use resp_result::{FromRequestFamily, Nil, RespError, RespResult, ToInner}; +use axum_resp_result::{ + FromRequestFamily, Nil, RespError, RespResult, ToInner, +}; use crate::{Checker as DataChecker, LiteArgs}; @@ -110,6 +112,15 @@ where type Checker = C; } +impl ToInner for CheckExtract +where + C: CheckFetchFamily + Sized, +{ + type Inner = ::Checked; + + fn to_inner(self) -> Self::Inner { self.0 } +} + pub type JsonCheckExtract = CheckExtract::Unchecked>, C, E>; diff --git a/libs/modify-cache/Cargo.toml b/libs/modify-cache/Cargo.toml index e8deb44be..ad14cf11d 100644 --- a/libs/modify-cache/Cargo.toml +++ b/libs/modify-cache/Cargo.toml @@ -16,7 +16,7 @@ chrono = { workspace = true } http = "1" axum = { workspace = true, features = ["original-uri"] } async-trait = { workspace = true } -resp-result = { workspace = true } +axum-resp-result = { workspace = true } # utils thiserror = { workspace = true } base64 = "0.13" diff --git a/libs/modify-cache/src/cache_ctrl/control.rs b/libs/modify-cache/src/cache_ctrl/control.rs index f90b3a762..70b76e4e4 100644 --- a/libs/modify-cache/src/cache_ctrl/control.rs +++ b/libs/modify-cache/src/cache_ctrl/control.rs @@ -1,7 +1,7 @@ use std::{ops::Add, time::Duration}; +use axum_resp_result::{ExtraFlag, ExtraFlags}; use http::{header::CACHE_CONTROL, HeaderValue}; -use resp_result::{ExtraFlag, ExtraFlags}; #[derive(Debug, Default)] /// 可缓存性 diff --git a/libs/modify-cache/src/cache_ctrl/mod.rs b/libs/modify-cache/src/cache_ctrl/mod.rs index 992b30b6d..3787b8970 100644 --- a/libs/modify-cache/src/cache_ctrl/mod.rs +++ b/libs/modify-cache/src/cache_ctrl/mod.rs @@ -1,10 +1,10 @@ use std::{borrow::Cow, ops::Add}; +use axum_resp_result::{ExtraFlag, ExtraFlags}; use http::{ header::{HeaderName, CONTENT_LOCATION, VARY}, Uri, }; -use resp_result::{ExtraFlag, ExtraFlags}; use self::control::CacheControl; diff --git a/libs/modify-cache/src/check_modify.rs b/libs/modify-cache/src/check_modify.rs index 7478b5235..7ac06d878 100644 --- a/libs/modify-cache/src/check_modify.rs +++ b/libs/modify-cache/src/check_modify.rs @@ -2,13 +2,13 @@ use std::convert::Infallible; use async_trait::async_trait; use axum::extract::{FromRequestParts, OriginalUri}; +use axum_resp_result::{ExtraFlag, ExtraFlags}; use http::{ header::{CONTENT_TYPE, ETAG, LAST_MODIFIED}, method::Method, request::Parts, StatusCode, }; -use resp_result::{ExtraFlag, ExtraFlags}; use tracing::warn; use crate::{ diff --git a/libs/modify-cache/src/headers.rs b/libs/modify-cache/src/headers.rs index 4099df3c7..f7f397bef 100644 --- a/libs/modify-cache/src/headers.rs +++ b/libs/modify-cache/src/headers.rs @@ -9,9 +9,11 @@ use nom::{ IResult, }; +#[derive(Default, Debug)] pub enum ControlHeaders { IfNoneMatch(HashSet), IfModifySince(NaiveDateTime), + #[default] None, } /// function action diff --git a/libs/page_size/src/response/mod.rs b/libs/page_size/src/response/mod.rs index 695fc0bf0..de203e5db 100644 --- a/libs/page_size/src/response/mod.rs +++ b/libs/page_size/src/response/mod.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use serde::Serialize; +use serde::{ser::SerializeStruct, Serialize}; use crate::request::Paginator; @@ -13,13 +13,34 @@ pub struct PageInfo { } /// 列表与分页信息 -#[derive(Serialize, Debug)] +#[derive(Debug)] pub struct ListWithPageInfo where T: Serialize, { list: Vec, - page_size: PageInfo, + page_size: Option, +} + +impl Serialize for ListWithPageInfo +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match &self.page_size { + Some(page) => { + let mut struc = + serializer.serialize_struct("ListWithPageInfo", 2)?; + struc.serialize_field("list", &self.list)?; + struc.serialize_field("page_size", page)?; + struc.end() + } + None => as Serialize>::serialize(&self.list, serializer), + } + } } pub trait GenerateListWithPageInfo: IntoIterator @@ -29,6 +50,8 @@ where fn with_page_info( self, page_size: Paginator, count: u64, ) -> ListWithPageInfo; + + fn with_plain(self) -> ListWithPageInfo; } impl GenerateListWithPageInfo for T @@ -42,12 +65,68 @@ where ) -> ListWithPageInfo { ListWithPageInfo { list: self.into_iter().collect(), - page_size: PageInfo { + page_size: Some(PageInfo { page_size, total_count: count, total_page: (count as f64 / *page_size.size.deref() as f64) .ceil() as u64, - }, + }), } } + + fn with_plain(self) -> ListWithPageInfo { + ListWithPageInfo { + list: self.into_iter().collect(), + page_size: None, + } + } +} + +#[cfg(test)] +mod test { + use checker::{prefabs::num_check::NonZeroUnsignedChecker, Checker}; + use serde_json::json; + + use super::GenerateListWithPageInfo; + use crate::request::Paginator; + #[test] + fn test_serde_paginator() { + let a = Some("AAA"); + let page = a.with_page_info( + Paginator::builder() + .page( + NonZeroUnsignedChecker::check(Default::default(), 11) + .into_inner() + .unwrap(), + ) + .size( + NonZeroUnsignedChecker::check(Default::default(), 2) + .into_inner() + .unwrap(), + ) + .build(), + 25, + ); + + let value = serde_json::to_value(&page).unwrap(); + + assert_eq!( + value, + json!({ + "list":["AAA"], + "page_size":{ + + "page":11, + "size":2, + "total_count":25, + "total_page":13 + + } + }) + ); + + let no_page = Some("AAA").with_plain(); + let value = serde_json::to_value(&no_page).unwrap(); + assert_eq!(value, json!(["AAA"])) + } } diff --git a/libs/serve_utils/Cargo.toml b/libs/serve_utils/Cargo.toml new file mode 100644 index 000000000..ef2527624 --- /dev/null +++ b/libs/serve_utils/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "serve_utils" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum.workspace = true +axum-core.workspace = true +axum-resp-result.workspace = true +serde.workspace = true +status-err = { version = "0.1.0", path = "../status-err" } +thiserror.workspace = true +tower.workspace = true +tracing.workspace = true diff --git a/libs/serve_utils/src/controller_trait.rs b/libs/serve_utils/src/controller_trait.rs new file mode 100644 index 000000000..4fc432089 --- /dev/null +++ b/libs/serve_utils/src/controller_trait.rs @@ -0,0 +1,62 @@ +use std::{convert::Infallible, marker::PhantomData}; + +use axum::{routing::Route, Router}; +use axum_core::{extract::Request, response::IntoResponse}; +use axum_resp_result::MapReject; +use tower::{Layer, Service}; + +use crate::EndpointType; + +pub trait ControllerRoute +where + S: Clone + Send + Sync + 'static, + E: EndpointType, + Self: Sized, +{ + const BASE_URI: &'static str; + + fn route(self) -> Router { Router::new() } + + fn layer(self, layer: L) -> LayeredController + where + L: Layer + Clone + Send + 'static, + L::Service: Service + Clone + Send + 'static, + >::Response: IntoResponse + 'static, + >::Error: Into + 'static, + >::Future: Send + 'static, + { + LayeredController::new(ControllerRoute::route(self).layer(layer)) + } +} + +pub struct LayeredController { + inner: Router, + __phantom: PhantomData, +} + +impl LayeredController { + fn new(router: Router) -> Self { + Self { + inner: router, + __phantom: Default::default(), + } + } +} + +impl ControllerRoute for LayeredController +where + S: Clone + Send + Sync + 'static, + C: ControllerRoute, + E: EndpointType, +{ + const BASE_URI: &'static str = >::BASE_URI; + + fn route(self) -> Router { self.inner } +} + +pub trait ControllerError { + type Error; +} + +pub type HandlerResult = Result::Error>; +pub type HandlerMapReject = MapReject::Error>; diff --git a/libs/serve_utils/src/endpoint_type.rs b/libs/serve_utils/src/endpoint_type.rs new file mode 100644 index 000000000..e5352b344 --- /dev/null +++ b/libs/serve_utils/src/endpoint_type.rs @@ -0,0 +1,18 @@ +pub trait EndpointType: Default {} + +#[derive(Default)] +pub struct UserEnd; + +impl EndpointType for UserEnd {} +#[derive(Default)] +pub struct AdminEnd; + +impl EndpointType for AdminEnd {} +#[derive(Default)] +pub struct CDN; + +impl EndpointType for CDN {} +#[derive(Default)] +pub struct Internal; + +impl EndpointType for Internal {} diff --git a/libs/serve_utils/src/lib.rs b/libs/serve_utils/src/lib.rs new file mode 100644 index 000000000..9bd104ff3 --- /dev/null +++ b/libs/serve_utils/src/lib.rs @@ -0,0 +1,21 @@ +mod controller_trait; +mod endpoint_type; +mod router_extra; +mod view_traits; + +pub use axum; +pub use axum_resp_result; +pub use controller_trait::{ + ControllerError, ControllerRoute, HandlerMapReject, HandlerResult, + LayeredController, +}; +pub use endpoint_type::EndpointType; +pub use router_extra::{ControllerRouter, ControllerRouterExt}; +pub use status_err; +pub use thiserror::Error as ThisError; +pub use tracing; +pub use view_traits::{OptionField, OptionViewField, SkipField, ValueField}; + +pub mod endpoint { + pub use crate::endpoint_type::{AdminEnd, Internal, UserEnd, CDN}; +} diff --git a/libs/serve_utils/src/router_extra.rs b/libs/serve_utils/src/router_extra.rs new file mode 100644 index 000000000..ebf4c969e --- /dev/null +++ b/libs/serve_utils/src/router_extra.rs @@ -0,0 +1,139 @@ +use std::{convert::Infallible, marker::PhantomData}; + +use axum::{ + extract::Request, response::IntoResponse, routing::Route, Router, +}; +use tower::{Layer, Service}; + +use crate::{ControllerRoute, EndpointType}; + +pub trait ControllerRouterExt { + fn nest_controller(self, controller: C, _endpoint: E) -> Self; + + fn merge_controller(self, controller: C, _endpoint: E) -> Self; +} + +impl ControllerRouterExt for Router +where + C: ControllerRoute, + E: EndpointType, + S: Send + Sync + 'static + Clone, +{ + fn nest_controller(self, controller: C, _endpoint: E) -> Self { + self.nest( + C::BASE_URI, + >::route(controller), + ) + } + + fn merge_controller(self, controller: C, _endpoint: E) -> Self { + self.merge(>::route(controller)) + } +} + +pub struct ControllerRouter { + router: Router, + __phantom: PhantomData, +} + +impl From> for Router { + fn from(val: ControllerRouter) -> Self { val.router } +} + +impl ControllerRouter +where + E: EndpointType, + S: Send + Sync + 'static + Clone, +{ + pub fn nest_controller>( + self, controller: C, + ) -> Self { + self.nest( + C::BASE_URI, + >::route(controller), + ) + } + + pub fn merge_controller>( + self, controller: C, + ) -> Self { + let router = self + .router + .merge(>::route(controller)); + Self { router, ..self } + } + + pub fn nest(self, path: &str, handler: Router) -> Self { + let router = self.router.nest(path, handler); + Self { router, ..self } + } + + pub fn merge>>(self, handler: R) -> Self { + let router = self.router.merge(handler); + Self { router, ..self } + } + + pub fn route_layer(self, layer: L) -> Self + where + L: Layer + Clone + Send + 'static, + L::Service: Service + Clone + Send + 'static, + >::Response: IntoResponse + 'static, + >::Error: Into + 'static, + >::Future: Send + 'static, + { + let router = self.router.route_layer(layer); + Self { router, ..self } + } +} + +impl ControllerRouter { + pub fn new(_endpoint: E) -> Self + where + S: Clone + Send + Sync + 'static, + E: EndpointType, + { + Self { + router: Router::new(), + __phantom: PhantomData, + } + } + + pub fn set_router) -> Router>( + self, handle: F, + ) -> Self { + let router = handle(self.router); + Self { router, ..self } + } +} + +#[cfg(test)] +mod test { + use axum::Router; + + use crate::{ + endpoint::AdminEnd, endpoint_type::UserEnd, ControllerRoute, + ControllerRouterExt, + }; + + pub struct TestController; + + impl ControllerRoute + for TestController + { + const BASE_URI: &'static str = "/admin/test"; + } + + impl ControllerRoute + for TestController + { + const BASE_URI: &'static str = "/test"; + } + #[test] + fn test_ctrl() { + let _:Router = Router::new() + .nest_controller(TestController,UserEnd) + .nest_controller(TestController,AdminEnd) + // .nest_controller(TestController,CDN) + ; + } +} diff --git a/libs/serve_utils/src/view_traits.rs b/libs/serve_utils/src/view_traits.rs new file mode 100644 index 000000000..1a32c1d9e --- /dev/null +++ b/libs/serve_utils/src/view_traits.rs @@ -0,0 +1,139 @@ +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use crate::view_traits::_private::SealTrait; + +/// 用于view中的可选field +/// +/// 由于view可能存面向不同端有细微差别, +/// 但是如果由于少量的字段区分重复整个view定义会带来大量代码冗余。 +/// 因此,提出了该trait +/// +/// ## Example +/// 如果有某个view结构体, +/// - 其在后台接口的view需要提供其ID +/// - 在前台接口的view中不需要提供ID +/// - 在请求接口中会基于是否提供ID进行不同操作 +/// +/// 那么使用[OptionViewField]就可以如下实现 +/// +/// ```rust +/// use serde::{Serialize, Deserialize}; +/// +/// #[derive(Serialize, Deserialize)] +/// struct FooView>{ +/// id:ID, +/// foo:String +/// } +/// ``` +/// +/// - 当在后台接口中使用时,其为 `FooView>`, +/// 即需要提供id的view。可能的序列化结果为 +/// ```json +/// { +/// "id": 114514, +/// "foo": "hello" +/// } +/// ``` +/// - 当在前台接口中使用时,其为 `FooView`, +/// 即不携带id的view。可能的序列化结果为 +/// ```json +/// { +/// "foo": "hello" +/// } +/// ``` +/// - 当需要根据是否提供ID执行不同操作实现,其为 +/// `FooView>`, 即携带Option的ID的view +pub trait OptionViewField: _private::SealTrait { + fn skip_serde(&self) -> bool; +} + +mod _private { + pub trait SealTrait {} +} + +/// View 中可选field的可以跳过情况 +#[derive(Default, Debug, Clone, Copy)] +pub struct SkipField; + +impl Serialize for SkipField { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_none() + } +} + +impl<'de> Deserialize<'de> for SkipField { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let _ = as Deserialize<'de>>::deserialize(deserializer)?; + Ok(Self) + } +} + +impl OptionViewField for SkipField { + fn skip_serde(&self) -> bool { true } +} + +impl SealTrait for SkipField {} + +#[derive(Debug, Clone)] +#[repr(transparent)] +pub struct ValueField(pub T); + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for ValueField { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = ::deserialize(deserializer)?; + Ok(Self(value)) + } +} + +impl Serialize for ValueField { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + ::serialize(&self.0, serializer) + } +} + +impl SealTrait for ValueField {} + +impl OptionViewField for ValueField { + fn skip_serde(&self) -> bool { false } +} + +#[derive(Debug, Clone)] +pub struct OptionField(pub Option); + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for OptionField { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = + as Deserialize<'de>>::deserialize(deserializer)?; + Ok(Self(value)) + } +} + +impl Serialize for OptionField { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Serialize::serialize(&self.0, serializer) + } +} + +impl OptionViewField for OptionField { + fn skip_serde(&self) -> bool { self.0.is_none() } +} + +impl SealTrait for OptionField {} diff --git a/libs/status-err/Cargo.toml b/libs/status-err/Cargo.toml index 53ff34d8e..c0e32f6c8 100644 --- a/libs/status-err/Cargo.toml +++ b/libs/status-err/Cargo.toml @@ -35,7 +35,7 @@ workspace = true [dependencies.range-limit] path = "../range-limit" -[dependencies.resp-result] +[dependencies.axum-resp-result] workspace = true features = ["extra-error"] diff --git a/libs/status-err/src/codegen.rs b/libs/status-err/src/codegen.rs index 1d37b3b7e..5b866e0fe 100644 --- a/libs/status-err/src/codegen.rs +++ b/libs/status-err/src/codegen.rs @@ -177,7 +177,7 @@ macro_rules! error_wrapper { macro_rules! resp_error_impl { ($t:ty) => { /// 实现 Resp -error 可以作为RespResult的异常 - impl ::resp_result::RespError for $t { + impl ::axum_resp_result::RespError for $t { fn log_message(&self) -> std::borrow::Cow<'_, str> { $crate::StatusErr::information(self) } diff --git a/logic/ceobe_operation_logic/Cargo.toml b/logic/ceobe_operation_logic/Cargo.toml index a5db4d585..41ff9d32a 100644 --- a/logic/ceobe_operation_logic/Cargo.toml +++ b/logic/ceobe_operation_logic/Cargo.toml @@ -19,6 +19,8 @@ request-clients.workspace = true reqwest.workspace = true tencent-cloud-server.workspace = true serde_qs.workspace = true +semver = "1.0.23" +db-ops-prelude.workspace = true [dependencies.checker] -path = "../../libs/checker" \ No newline at end of file +path = "../../libs/checker" diff --git a/logic/ceobe_operation_logic/src/impletements/announcement.rs b/logic/ceobe_operation_logic/src/impletements/announcement.rs index 2d78d2f4b..8451419a6 100644 --- a/logic/ceobe_operation_logic/src/impletements/announcement.rs +++ b/logic/ceobe_operation_logic/src/impletements/announcement.rs @@ -1,6 +1,5 @@ use persistence::{ - ceobe_operate::{announcement, ToCeobeOperation}, - ceobe_user::ToCeobe, + ceobe_operate::{announcement, ToCeobe, ToCeobeOperation}, mysql::SqlDatabaseOperate, }; use tencent_cloud_server::{ diff --git a/logic/ceobe_operation_logic/src/impletements/resource.rs b/logic/ceobe_operation_logic/src/impletements/resource.rs index 93713270a..7f76f87bf 100644 --- a/logic/ceobe_operation_logic/src/impletements/resource.rs +++ b/logic/ceobe_operation_logic/src/impletements/resource.rs @@ -1,6 +1,5 @@ use persistence::{ - ceobe_operate::{resource, ToCeobeOperation}, - ceobe_user::ToCeobe, + ceobe_operate::{resource, ToCeobe, ToCeobeOperation}, mysql::SqlDatabaseOperate, }; use tencent_cloud_server::{ diff --git a/logic/ceobe_operation_logic/src/impletements/tool_link.rs b/logic/ceobe_operation_logic/src/impletements/tool_link.rs index 199339115..d86bea143 100644 --- a/logic/ceobe_operation_logic/src/impletements/tool_link.rs +++ b/logic/ceobe_operation_logic/src/impletements/tool_link.rs @@ -6,9 +6,8 @@ use page_size::{ use persistence::{ ceobe_operate::{ models::tool_link::checkers::tool_link_data::CeobeOperationToolLink, - tool_link_mongodb::models::ToolLink, ToCeobeOperation, + tool_link_mongodb::models::ToolLink, ToCeobe, ToCeobeOperation, }, - ceobe_user::ToCeobe, mongodb::{mongodb::bson, MongoDatabaseOperate}, mysql::SqlDatabaseOperate, }; diff --git a/logic/ceobe_operation_logic/src/impletements/video.rs b/logic/ceobe_operation_logic/src/impletements/video.rs index a833aa3ab..52becf287 100644 --- a/logic/ceobe_operation_logic/src/impletements/video.rs +++ b/logic/ceobe_operation_logic/src/impletements/video.rs @@ -1,9 +1,8 @@ use persistence::{ ceobe_operate::{ video::{self, bv::Bv}, - ToCeobeOperation, + ToCeobe, ToCeobeOperation, }, - ceobe_user::ToCeobe, help_crates::tracing::{event, Level}, mysql::SqlDatabaseOperate, }; diff --git a/logic/ceobe_operation_logic/src/lib.rs b/logic/ceobe_operation_logic/src/lib.rs index 10a3001af..d2abe1def 100644 --- a/logic/ceobe_operation_logic/src/lib.rs +++ b/logic/ceobe_operation_logic/src/lib.rs @@ -1,3 +1,39 @@ +use std::ops::{Deref, DerefMut}; + +use db_ops_prelude::sea_orm::prelude::async_trait::async_trait; +use persistence::operate::{FromRequestParts, Parts}; + pub mod error; pub mod impletements; +pub mod release_version; pub mod view; + +pub struct CeobeOperationLogic(T); + +#[async_trait] +impl FromRequestParts for CeobeOperationLogic +where + T: FromRequestParts, + S: Send + Sync + 'static + Clone, +{ + type Rejection = >::Rejection; + + async fn from_request_parts( + parts: &mut Parts, state: &S, + ) -> Result { + Ok(Self( + >::from_request_parts(parts, state) + .await?, + )) + } +} + +impl DerefMut for CeobeOperationLogic { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } +} + +impl Deref for CeobeOperationLogic { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.0 } +} diff --git a/logic/ceobe_operation_logic/src/release_version/error.rs b/logic/ceobe_operation_logic/src/release_version/error.rs new file mode 100644 index 000000000..2e2dba639 --- /dev/null +++ b/logic/ceobe_operation_logic/src/release_version/error.rs @@ -0,0 +1,16 @@ +use std::convert::Infallible; + +use persistence::ceobe_operate::release_version; +use tencent_cloud_server::error::TcCloudError; + +pub(super) type Rejection = Infallible; + +#[derive(Debug, thiserror::Error, status_err::StatusErr)] +pub enum Error { + #[error(transparent)] + Dao(#[from] release_version::Error), + #[error(transparent)] + Tencent(#[from] TcCloudError), +} + +pub(super) type LogicResult = core::result::Result; diff --git a/logic/ceobe_operation_logic/src/release_version/implement.rs b/logic/ceobe_operation_logic/src/release_version/implement.rs new file mode 100644 index 000000000..97c51cb08 --- /dev/null +++ b/logic/ceobe_operation_logic/src/release_version/implement.rs @@ -0,0 +1,132 @@ +use db_ops_prelude::database_operates::operate_trait::OperateTrait; +use page_size::{ + request::Paginator, + response::{GenerateListWithPageInfo, ListWithPageInfo}, +}; +use persistence::ceobe_operate::{ + models::version::models::{ + DownloadSourceItem, ReleasePlatform, ReleaseVersion, + }, + ToCeobe, ToCeobeOperation, +}; +use semver::Version; + +use super::{LogicResult, ReleaseVersionLogic, TencentCDNPath}; + +impl ReleaseVersionLogic { + pub async fn mark_deleted( + &self, version: &Version, platform: &ReleasePlatform, + ) -> LogicResult<()> { + self.mongodb + .ceobe() + .operation() + .release_version() + .update() + .mark_deleted(platform, version) + .await?; + + self.tencent_cloud + .purge_urls_cache(&Some(TencentCDNPath::LATEST_VERSION)) + .await?; + + Ok(()) + } + + pub async fn all( + &self, paginator: Option, + platform: Option, deleted: bool, + ) -> LogicResult> { + let msg = self + .mongodb + .ceobe() + .operation() + .release_version() + .retrieve() + .all(platform, paginator, deleted) + .await?; + + match paginator { + Some(paginator) => { + let total = self.count(platform, deleted).await?; + Ok(msg.with_page_info(paginator, total as _)) + } + None => Ok(msg.with_plain()), + } + } + + async fn count( + &self, platform: Option, deleted: bool, + ) -> LogicResult { + let count = self + .mongodb + .ceobe() + .operation() + .release_version() + .retrieve() + .total_num(platform, deleted) + .await?; + Ok(count) + } + + pub async fn create_new( + &self, release: ReleaseVersion, + ) -> LogicResult<()> { + self.mongodb + .ceobe() + .operation() + .release_version() + .create() + .one(release) + .await?; + self.tencent_cloud + .purge_urls_cache(&Some(TencentCDNPath::LATEST_VERSION)) + .await?; + Ok(()) + } + + pub async fn fetch( + &self, version: Option, platform: ReleasePlatform, + ) -> LogicResult { + let release_info = match version { + None => { + self.mongodb + .ceobe() + .operation() + .release_version() + .retrieve() + .latest_by_platform(platform) + .await? + } + Some(ver) => { + self.mongodb + .ceobe() + .operation() + .release_version() + .retrieve() + .by_version_platform(&ver, platform) + .await? + } + }; + Ok(release_info) + } + + pub async fn update( + &self, version: Version, platform: ReleasePlatform, + description: Option, resources: Vec, + ) -> LogicResult<()> { + self.mongodb + .ceobe() + .operation() + .release_version() + .update() + .description_and_resource( + version.clone(), + platform, + description, + resources, + ) + .await?; + + Ok(()) + } +} diff --git a/logic/ceobe_operation_logic/src/release_version/mod.rs b/logic/ceobe_operation_logic/src/release_version/mod.rs new file mode 100644 index 000000000..e69d9e013 --- /dev/null +++ b/logic/ceobe_operation_logic/src/release_version/mod.rs @@ -0,0 +1,49 @@ +use persistence::{ + mongodb::MongoDatabaseOperate, + mysql::sea_orm::prelude::async_trait::async_trait, + operate::{FromRef, FromRequestParts, Parts}, +}; +use tencent_cloud_server::{ + axum_starter::{PartTencentCloudManagerState, RequestClient}, + cloud_manager::TencentCloudManager, +}; + +pub struct ReleaseVersionLogic { + pub mongodb: MongoDatabaseOperate, + pub tencent_cloud: TencentCloudManager, +} + +#[async_trait] +impl FromRequestParts for ReleaseVersionLogic +where + S: Send + Sync + 'static, + RequestClient: FromRef, + PartTencentCloudManagerState: FromRef, +{ + type Rejection = Rejection; + + async fn from_request_parts( + parts: &mut Parts, state: &S, + ) -> Result { + let mongodb = >::from_request_parts(parts, state).await?; + let tencent_cloud = + >::from_request_parts( + parts, state, + ) + .await?; + Ok(Self { + mongodb, + tencent_cloud, + }) + } +} + +mod error; +mod implement; +pub mod view; + +pub use self::error::Error; +use self::{ + error::{LogicResult, Rejection}, + view::*, +}; diff --git a/logic/ceobe_operation_logic/src/release_version/view.rs b/logic/ceobe_operation_logic/src/release_version/view.rs new file mode 100644 index 000000000..7bf1cdabd --- /dev/null +++ b/logic/ceobe_operation_logic/src/release_version/view.rs @@ -0,0 +1,8 @@ +use tencent_cloud_server::cdn::purge_urls_cache::PurgeCachePath; + +pub struct TencentCDNPath; + +impl TencentCDNPath { + pub const LATEST_VERSION: PurgeCachePath = + PurgeCachePath::new("/cdn/operate/version/fetch"); +} diff --git a/macros/check-obj-macro/Cargo.toml b/macros/check-obj-macro/Cargo.toml index 9f0517de4..fcf553262 100644 --- a/macros/check-obj-macro/Cargo.toml +++ b/macros/check-obj-macro/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" proc-macro = true [dependencies] -syn = "1" +syn = {version="1",features=["full"]} quote = "1" typed-builder = { workspace = true } diff --git a/macros/check-obj-macro/src/lib.rs b/macros/check-obj-macro/src/lib.rs index 1f1490ea9..1bc1bf3bd 100644 --- a/macros/check-obj-macro/src/lib.rs +++ b/macros/check-obj-macro/src/lib.rs @@ -64,7 +64,7 @@ mod inner_checker_info; /// 1. `uncheck` 传递一个标识符,用于作为生成的 `UnCheck` 的名称 /// 2. `checked` 传递一个类型,为`Checked` 结构体的类型 /// 3. `error` 传递一个类型, 为生成的 `Checker` 的异常统一映射目标类型, -/// 要求所有的内部`Checker` 的 `Err` 都实现了 [Into](Into) +/// 要求所有的内部`Checker` 的 `Err` 都实现了 [Into](Into) /// /// 传递顺序不可打乱,使用`,` 分割,最后的`,` 可选 /// @@ -100,7 +100,8 @@ mod inner_checker_info; /// /// - 如果需要挂载额外的过程宏或者 `derive` 宏到 `Uncheck` 结构体上,可以在 /// [check_obj](macro@check_obj) -/// 之下挂载宏,[check_obj](macro@check_obj)将会将其搬运到 `Uncheck` 结构体上 +/// 之下挂载宏,[check_obj](macro@check_obj)将会将其搬运到 `Uncheck` +/// 结构体上 /// - 生成的 `Uncheck` 与 `Checker` 的可见性 与 被挂载结构体的可见性 (`pub`) /// 一致 /// - 生成的 `Uncheck` 中每一个域(field)的可见性 与 @@ -112,11 +113,9 @@ mod inner_checker_info; /// ## 生成什么? /// /// 1. `Uncheck` 结构体,名称通过过程宏参数提供 -/// 2. `Checker` 空白结构体,并为其实现 -/// `Checker` -/// 3. `CheckerFut` -/// [!Unpin](std::marker::Unpin) 的结构体,并为其实现 -/// [Future](std::future::Future) ,在其内部实现具体`check`过程 +/// 2. `Checker` 空白结构体,并为其实现 `Checker` +/// 3. `CheckerFut` [!Unpin](std::marker::Unpin) 的结构体,并为其实现 +/// [Future](std::future::Future) ,在其内部实现具体`check`过程 #[proc_macro_attribute] pub fn check_obj(params: TokenStream, item: TokenStream) -> TokenStream { let params = parse_macro_input!(params as checker_info::CheckerInfo); diff --git a/macros/status-err-derive/Cargo.toml b/macros/status-err-derive/Cargo.toml index 1cc92e828..fa22ec8c1 100644 --- a/macros/status-err-derive/Cargo.toml +++ b/macros/status-err-derive/Cargo.toml @@ -14,4 +14,4 @@ darling = "0.14" [dev-dependencies] status-err = { path = "../../libs/status-err" } -resp-result = { workspace = true } +axum-resp-result = { workspace = true } diff --git a/macros/status-err-derive/src/lib.rs b/macros/status-err-derive/src/lib.rs index 3a8d95e13..5c7a50e17 100644 --- a/macros/status-err-derive/src/lib.rs +++ b/macros/status-err-derive/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::manual_unwrap_or_default)] + use darling::FromDeriveInput; use input_loading::derive_info::StatusErrorDeriveInfo; use proc_macro::TokenStream; diff --git a/middle-server/mob-push-server/src/lib.rs b/middle-server/mob-push-server/src/lib.rs index 6187a1c2e..4db8e2eb0 100644 --- a/middle-server/mob-push-server/src/lib.rs +++ b/middle-server/mob-push-server/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_borrows_for_generic_args)] + pub use config::app_info::MobPushConfigTrait; use device_info::DeviceInfo; pub use error::MobPushError; diff --git a/middle-server/mob-push-server/src/push_notify/android/image.rs b/middle-server/mob-push-server/src/push_notify/android/image.rs index dbc99676c..e055c2a78 100644 --- a/middle-server/mob-push-server/src/push_notify/android/image.rs +++ b/middle-server/mob-push-server/src/push_notify/android/image.rs @@ -25,7 +25,7 @@ impl Image { /// /// - 透传消息不支持 /// - 小米厂商对图片尺寸有严格要求,不符合要求则不会按照大图样式进行推送, - /// 具体要求为:宽高固定为876*324px,格式需为PNG/JPG/JPEG,大小小于1M + /// 具体要求为:宽高固定为876*324px,格式需为PNG/JPG/JPEG,大小小于1M /// - OPPO厂商大图需要申请权限,否则会报错导致客户端收不到推送消息 pub fn new_image(image_url: impl Into) -> Self { Self::Image(image_url.into()) diff --git a/middle-server/qiniu-cdn-upload/src/lib.rs b/middle-server/qiniu-cdn-upload/src/lib.rs index 5f177c784..2e961b872 100644 --- a/middle-server/qiniu-cdn-upload/src/lib.rs +++ b/middle-server/qiniu-cdn-upload/src/lib.rs @@ -15,8 +15,7 @@ pub mod update_source; /// 通用七牛云上传接口 /// /// - `uploader`: [`&Uploader`](Uploader) 七牛云上传器,可以通过 -/// [`QiniuManager`](ceobe_qiniu_upload::QiniuManager) -/// 解引用获得 +/// [`QiniuManager`](ceobe_qiniu_upload::QiniuManager) 解引用获得 /// - `source`: 原始待上传信息,可以从中获得待上传的内容和待上传的 /// `Content-Type` /// - `payload`: 指定荷载的信息,包括 上传七牛云的路径,如何从source diff --git a/middle-server/qq-channel-warning/Cargo.toml b/middle-server/qq-channel-warning/Cargo.toml index f59c50b77..b668e9223 100644 --- a/middle-server/qq-channel-warning/Cargo.toml +++ b/middle-server/qq-channel-warning/Cargo.toml @@ -11,7 +11,7 @@ axum-starter.workspace = true http.workspace = true http_02 = {package = "http",version = "0.2"} prost = "0.11.9" -resp-result.workspace = true +axum-resp-result.workspace = true status-err = { version = "0.1.0", path = "../../libs/status-err" } thiserror.workspace = true tonic = "0.9.1" diff --git a/middle-server/qq-channel-warning/src/grpc_client.rs b/middle-server/qq-channel-warning/src/grpc_client.rs index e54bd29f3..ae82de746 100644 --- a/middle-server/qq-channel-warning/src/grpc_client.rs +++ b/middle-server/qq-channel-warning/src/grpc_client.rs @@ -1,5 +1,5 @@ use axum::extract::{FromRef, FromRequestParts}; -use resp_result::RespResult; +use axum_resp_result::RespResult; use tonic::transport::Channel; use crate::{ @@ -13,12 +13,23 @@ pub struct QqChannelGrpcService { client: LogClient, } +impl QqChannelGrpcService { + pub async fn new_with_uri( + state: QqChannelGrpcState, + ) -> Result { + LogClient::connect(state.uri) + .await + .map_err(error::Error::Transport) + .map(|client| Self { client }) + } +} + impl FromRequestParts for QqChannelGrpcService where S: Send, QqChannelGrpcState: FromRef, { - type Rejection = RespResult; + type Rejection = RespResult; fn from_request_parts<'life0, 'life1, 'async_trait>( _parts: &'life0 mut axum::http::request::Parts, state: &'life1 S, diff --git a/middle-server/tencent-cloud-server/src/axum_starter.rs b/middle-server/tencent-cloud-server/src/axum_starter.rs index 9075763ce..4e87756ed 100644 --- a/middle-server/tencent-cloud-server/src/axum_starter.rs +++ b/middle-server/tencent-cloud-server/src/axum_starter.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use axum_starter::{prepare, state::AddState}; +pub use general_request_client::client::RequestClient; use secrecy::SecretString; pub use crate::cloud_manager::PartTencentCloudManagerState; diff --git a/persistence/dao/ceobe-operate/Cargo.toml b/persistence/dao/ceobe-operate/Cargo.toml index 585e1bc48..110480d04 100644 --- a/persistence/dao/ceobe-operate/Cargo.toml +++ b/persistence/dao/ceobe-operate/Cargo.toml @@ -12,4 +12,9 @@ thiserror.workspace = true tracing.workspace = true abstract_database.workspace = true page_size.workspace = true +serde = { version = "1.0.201", features = ["derive"] } + +[dev-dependencies] +mongo-migration = { path = "../../migrate/mongo-migration" } +tokio = { workspace = true, features = ["test-util"] } diff --git a/persistence/dao/ceobe-operate/src/lib.rs b/persistence/dao/ceobe-operate/src/lib.rs index 1b067c575..6a874ece4 100644 --- a/persistence/dao/ceobe-operate/src/lib.rs +++ b/persistence/dao/ceobe-operate/src/lib.rs @@ -13,6 +13,8 @@ mod common; pub mod desktop_version; #[path = "mongo/plugin_version/mod.rs"] pub mod plugin_version; +#[path = "mongo/release_version/mod.rs"] +pub mod release_version; #[path = "sql/resource/mod.rs"] pub mod resource; #[path = "sql/tool_link/mod.rs"] pub mod tool_link; #[path = "mongo/tool_link/mod.rs"] diff --git a/persistence/dao/ceobe-operate/src/mongo/plugin_version/mod.rs b/persistence/dao/ceobe-operate/src/mongo/plugin_version/mod.rs index ed33e833d..9d7063307 100644 --- a/persistence/dao/ceobe-operate/src/mongo/plugin_version/mod.rs +++ b/persistence/dao/ceobe-operate/src/mongo/plugin_version/mod.rs @@ -51,6 +51,6 @@ type OperateResult = Result; impl<'db, Conn> OperationDatabaseOperate<'db, Conn> { pub fn plugin_version(&self) -> PluginVersionOperate<'_, Conn> { - self.child() + SuperOperate::child(self) } } diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/common.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/common.rs new file mode 100644 index 000000000..f0f9a91f6 --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/common.rs @@ -0,0 +1,16 @@ +use db_ops_prelude::{ + mongo_models::ceobe::operation::version::models::{ + ReleasePlatform, Version, + }, + mongodb::bson::{doc, to_bson, Document}, +}; + +pub(super) fn generate_release_version_filter( + version: &Version, release_platform: &ReleasePlatform, +) -> super::Result { + let doc = doc! { + "version" : to_bson(version)?, + "platform": to_bson(release_platform)? + }; + Ok(doc) +} diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/create.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/create.rs new file mode 100644 index 000000000..323f04b79 --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/create.rs @@ -0,0 +1,129 @@ +use db_ops_prelude::mongo_connection::MongoDbCollectionTrait; + +use super::{models::ReleaseVersion, ReleaseVersionCreate, Result}; +use crate::release_version::verify::suitable_version; + +impl<'db, Conn> ReleaseVersionCreate<'db, Conn> +where + Conn: MongoDbCollectionTrait<'db, ReleaseVersion>, +{ + pub async fn one( + &'db self, release_version: impl Into, + ) -> Result<()> { + let release_version = release_version.into(); + + let collection = self.get_collection()?; + + // 找到当前平台的最新的发布版本,与当前添加版本比较。新版本必须更新 + suitable_version(&collection, &release_version).await?; + + collection + .doing(|collection| collection.insert_one(release_version, None)) + .await?; + Ok(()) + } +} +#[cfg(test)] +mod test { + use abstract_database::ceobe::ToCeobe; + use db_ops_prelude::{ + database_operates::{operate_trait::OperateTrait, DatabaseOperate}, + mongo_connection::{ + database_traits::initial::connect_db_with_migrate, + get_mongo_collection, DatabaseManage, MongoConnect, + MongoDbConfig, + }, + mongo_models::ceobe::operation::version::models::{ + ForceCtrl, ReleasePlatform::Pocket, ReleaseVersion, Version, + }, + mongodb::bson::doc, + }; + use mongo_migration::Migrator; + use serde::{Deserialize, Serialize}; + + use crate::ToCeobeOperation; + + #[tokio::test] + async fn test_create_order() { + #[derive(Debug, Deserialize, Serialize)] + struct VersionOnly { + version: Version, + } + + connect_db_with_migrate::( + &MongoDbConfig::default(), + Migrator, + ) + .await + .expect("connect to db Error"); + + let conn = DatabaseOperate::new(MongoConnect); + let collection = get_mongo_collection::() + .expect("Collection Not Exist"); + + // 开始测试前,清空现有的collection内容 + collection + .delete_many(doc! {}, None) + .await + .expect("clear Collection Error"); + + // 插入一些版本号,按照从小到大,为了方便,这里只插入版本号 + for major in 1..=5 { + let version = Version::new(major, 0, 0); + collection + .with_mapping::() + .insert_one(&VersionOnly { version }, None) + .await + .expect("insert Error"); + } + + // 现在要插入一些新版本 + + // 添加6.0版本,这个是合法的,因为最新的版本是5.0 + let ret = conn + .ceobe() + .operation() + .release_version() + .create() + .one( + ReleaseVersion::builder() + .version(Version::new(6, 0, 0)) + .force( + ForceCtrl::builder() + .previous_force_version(Version::new(1, 0, 0)) + .build(), + ) + .platform(Pocket) + .build(), + ) + .await; + + assert!(ret.is_ok()); + + // 添加5.8.1 版本,这个是非法的,因为最新版本是6.0,必须大于6.0 + let ret = conn + .ceobe() + .operation() + .release_version() + .create() + .one( + ReleaseVersion::builder() + .version(Version::new(5, 8, 1)) + .force( + ForceCtrl::builder() + .previous_force_version(Version::new(1, 0, 0)) + .build(), + ) + .platform(Pocket) + .build(), + ) + .await; + + // 返回Err, 同时Err类型为VersionTooOld + assert!(ret.is_err()); + assert_eq!( + ret.map_err(|e| e.to_string()), + Err("新版本的版本号过旧, 新版本号应大于 6.0.0".to_string()) + ); + } +} diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/delete.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/delete.rs new file mode 100644 index 000000000..7767b0665 --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/delete.rs @@ -0,0 +1,9 @@ +use db_ops_prelude::{ + mongo_connection::MongoDbCollectionTrait, + mongo_models::ceobe::operation::version::models::ReleaseVersion, +}; + +impl<'db, Conn> super::ReleaseVersionDelete<'db, Conn> where + Conn: MongoDbCollectionTrait<'db, ReleaseVersion> +{ +} diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/mod.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/mod.rs new file mode 100644 index 000000000..fca67752a --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/mod.rs @@ -0,0 +1,47 @@ +mod common; +mod create; +mod delete; +mod retrieve; +mod update; +mod verify; + +use db_ops_prelude::{ + mongo_connection::{database_traits::dao_operator, MongoDbError}, + ErrPrefix, HttpCode, StatusErr, ThisError, +}; + +use crate::OperationDatabaseOperate; +dao_operator!(OperationDatabaseOperate=>ReleaseVersion(release_version,err=Error)); + +#[derive(Debug, ThisError, StatusErr)] +pub enum Error { + #[error("数据库查询异常{0}")] + Db(#[from] MongoDbError), + + #[error("版本号已经存在 {1:?}:{0}")] + #[status_err(err( + prefix = "ErrPrefix::CHECKER", + err_code = 0x000B, + http_code = "HttpCode::CONFLICT" + ))] + ConflictVersion(models::Version, models::ReleasePlatform), + #[error("版本信息不存在 {1:?}:{0}")] + #[status_err(err(err_code = 0x0004, prefix = "ErrPrefix::NOT_FOUND",))] + VersionNotFind(models::Version, models::ReleasePlatform), + #[error("暂没有版本信息")] + #[status_err(err(err_code = 0x0005, prefix = "ErrPrefix::NOT_FOUND",))] + VersionInfoNoExist, + #[error("新版本的版本号过旧, 新版本号应大于 {1:?}:{0}")] + #[status_err(err( + err_code = 0x00017, + prefix = "ErrPrefix::CHECKER", + http_code = "HttpCode::CONFLICT" + ))] + VersionTooOld(models::Version, models::ReleasePlatform), + + #[error("Bson序列化失败")] + #[status_err(err(err_code = 0x0004, prefix = "ErrPrefix::MONGO_DB",))] + Bson(#[from] db_ops_prelude::mongodb::bson::ser::Error), +} + +use db_ops_prelude::mongo_models::ceobe::operation::version::*; diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/retrieve.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/retrieve.rs new file mode 100644 index 000000000..085235d37 --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/retrieve.rs @@ -0,0 +1,260 @@ +use db_ops_prelude::{ + futures::TryStreamExt, + mongo_connection::{MongoDbCollectionTrait, MongoDbError}, + mongo_models::ceobe::operation::version::models::ReleasePlatform, + mongodb::{ + bson::{doc, to_bson, Document}, + options::{FindOneOptions, FindOptions}, + }, +}; +use page_size::request::Paginator; +use tracing::info; + +use super::{ + models::{ReleaseVersion, Version}, + Error, ReleaseVersionRetrieve, Result, +}; +use crate::release_version::common::generate_release_version_filter; + +impl<'db, Conn> ReleaseVersionRetrieve<'db, Conn> +where + Conn: MongoDbCollectionTrait<'db, ReleaseVersion>, +{ + /// 根据指定版本号和平台返回对应的版本信息 + pub async fn by_version_platform( + &'db self, version: &Version, platform: ReleasePlatform, + ) -> Result { + info!(release.version = %version, release.platform = ?platform); + let collection = self.get_collection()?; + + let filter = generate_release_version_filter(version, &platform)?; + + let ret = collection + .doing(|collection| collection.find_one(filter, None)) + .await? + .ok_or_else(|| { + Error::VersionNotFind(version.to_owned(), platform) + })?; + Ok(ret) + } + + /// 根据平台返回最新的版本信息 + /// FIXME: 这里直接取最新的一个,理论上没问题/测试上也没问题 + pub async fn latest_by_platform( + &'db self, platform: ReleasePlatform, + ) -> Result { + info!( release.platform = ?platform); + let collection = self.get_collection()?; + let filter = doc! { + "platform":to_bson(&platform)?, + "deleted": false + }; + let sort = doc! { + "$natural": -1i32 + }; + + let ret = collection + .doing(|collection| { + collection.find_one( + filter, + FindOneOptions::builder().sort(sort).build(), + ) + }) + .await? + .ok_or(Error::VersionInfoNoExist)?; + + Ok(ret) + } + + pub async fn all( + &'db self, platform: Option, + paginate: impl Into>, deleted: bool, + ) -> Result> { + let collection = self.get_collection()?; + let filter = generate_platform_filter_document(platform, deleted)?; + let sort = doc! { + "$natural": -1i32 + }; + + let options = FindOptions::builder().sort(sort); + + let options = if let Some(paginator) = paginate.into() { + options + .limit(Some(paginator.limit() as i64)) + .skip(paginator.offset()) + .build() + } + else { + options.build() + }; + + let ret = collection + .doing(|collection| collection.find(filter, options)) + .await? + .try_collect() + .await + .map_err(MongoDbError::Mongo)?; + + Ok(ret) + } + + pub async fn total_num( + &'db self, platform: Option, deleted: bool, + ) -> Result { + let collection = self.get_collection()?; + let filter = generate_platform_filter_document(platform, deleted)?; + + let ret = collection + .doing(|collection| collection.count_documents(filter, None)) + .await?; + + Ok(ret as _) + } +} + +fn generate_platform_filter_document( + platform: Option, deleted: bool, +) -> Result { + Ok(match platform { + None => { + doc! {"deleted": deleted} + } + Some(plat) => { + doc! { + "platform":to_bson(&plat)?, + "deleted": deleted + } + } + }) +} + +#[cfg(test)] +mod test { + use abstract_database::ceobe::ToCeobe; + use db_ops_prelude::{ + database_operates::{operate_trait::OperateTrait, DatabaseOperate}, + mongo_connection::{ + database_traits::initial::connect_db_with_migrate, + get_mongo_collection, DatabaseManage, MongoConnect, + MongoDbConfig, + }, + mongo_models::ceobe::operation::version::models::{ + ForceCtrl, + ReleasePlatform::{Desktop, Pocket}, + ReleaseVersion, Version, + }, + mongodb::bson::doc, + }; + use mongo_migration::Migrator; + + use crate::ToCeobeOperation; + + #[tokio::test] + async fn test_retrieve_version() { + connect_db_with_migrate::( + &MongoDbConfig::default(), + Migrator, + ) + .await + .expect("connect to db Error"); + + let conn = DatabaseOperate::new(MongoConnect); + let collection = get_mongo_collection::() + .expect("Collection Not Exist"); + + // 开始测试前,清空现有的collection内容 + collection + .delete_many(doc! {}, None) + .await + .expect("clear Collection Error"); + + // 当前无任何版本,最新版本返回空 + let latest = conn + .ceobe() + .operation() + .release_version() + .retrieve() + .latest_by_platform(Pocket) + .await; + + assert_eq!( + latest.map_err(|e| e.to_string()), + Err("暂没有版本信息".into()) + ); + + // 现在要插入一些新版本 + let v1 = ReleaseVersion::builder() + .version(Version::new(1, 0, 0)) + .force( + ForceCtrl::builder() + .previous_force_version(Version::new(1, 0, 0)) + .force_update() + .build(), + ) + .platform(Pocket) + .build(); + let v2_1 = ReleaseVersion::builder() + .version(Version::new(2, 1, 0)) + .force( + ForceCtrl::builder() + .previous_force_version(Version::new(1, 0, 0)) + .build(), + ) + .platform(Pocket) + .build(); + + // 添加1.0版本 + conn.ceobe() + .operation() + .release_version() + .create() + .one(v1.clone()) + .await + .unwrap(); + + // 添加2.1 版本 + conn.ceobe() + .operation() + .release_version() + .create() + .one(v2_1.clone()) + .await + .unwrap(); + + // 现在获得最新版本,得到2.1 + let latest = conn + .ceobe() + .operation() + .release_version() + .retrieve() + .latest_by_platform(Pocket) + .await; + assert!(latest.is_ok()); + assert_eq!(latest.unwrap(), v2_1); + + // 指定版本1.0,获得1.0 + let get_v1 = conn + .ceobe() + .operation() + .release_version() + .retrieve() + .by_version_platform(&Version::new(1, 0, 0), Pocket) + .await; + assert!(get_v1.is_ok()); + assert_eq!(get_v1.unwrap(), v1); + + // 指定一个不存在的版本,返回Err + let version_not_exist = conn + .ceobe() + .operation() + .release_version() + .retrieve() + .by_version_platform(&Version::new(1, 0, 0), Desktop) + .await; + + assert_eq!( + version_not_exist.map_err(|e| e.to_string()), + Err("版本信息不存在 Desktop:1.0.0".into()) + ) + } +} diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/update.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/update.rs new file mode 100644 index 000000000..571467487 --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/update.rs @@ -0,0 +1,64 @@ +use db_ops_prelude::{ + mongo_connection::MongoDbCollectionTrait, + mongo_models::ceobe::operation::version::models::{ + DownloadSourceItem, ReleasePlatform, ReleaseVersion, Version, + }, + mongodb::bson::{doc, to_bson}, +}; + +use super::Result; +use crate::release_version::common::generate_release_version_filter; + +impl<'db, C> super::ReleaseVersionUpdate<'db, C> +where + C: MongoDbCollectionTrait<'db, ReleaseVersion>, +{ + pub async fn description_and_resource( + &'db self, version: Version, platform: ReleasePlatform, + new_description: impl Into>, + resource: Vec, + ) -> Result<()> { + let collection = self.get_collection()?; + + let filter = generate_release_version_filter(&version, &platform)?; + let update = doc! { + "$set":{ + "description": to_bson(&new_description.into())?, + "download_source":to_bson(&resource)? + } + }; + + collection + .doing(|collection| collection.update_one(filter, update, None)) + .await?; + + Ok(()) + } + + /// 撤回一个已经发布的版本 + pub async fn mark_deleted( + &'db self, platform: &ReleasePlatform, version: &Version, + ) -> Result<()> { + let collection = self.get_collection()?; + let filter = doc! { + "platform": to_bson(platform)?, + "version": to_bson(version)?, + "deleted":false + }; + collection + .doing(|collection| { + collection.find_one_and_update( + filter, + doc! { + "$set":{ + "deleted": true + } + }, + None, + ) + }) + .await?; + + Ok(()) + } +} diff --git a/persistence/dao/ceobe-operate/src/mongo/release_version/verify.rs b/persistence/dao/ceobe-operate/src/mongo/release_version/verify.rs new file mode 100644 index 000000000..82cc40a8e --- /dev/null +++ b/persistence/dao/ceobe-operate/src/mongo/release_version/verify.rs @@ -0,0 +1,48 @@ +use db_ops_prelude::{ + mongo_connection::CollectionGuard, + mongo_models::ceobe::operation::version::models::{ + ReleaseVersion, Version, + }, + mongodb::{ + bson::{doc, to_bson}, + options::FindOneOptions, + }, +}; +use serde::{Deserialize, Serialize}; + +use super::{Error, Result}; +pub(super) async fn suitable_version( + collection: &CollectionGuard, + release_version: &ReleaseVersion, +) -> Result<()> { + #[derive(Debug, Deserialize, Serialize)] + struct VersionOnly { + version: Version, + } + + // 找到当前平台的最新的发布版本,与当前添加版本比较。新版本必须更新 + let filter = doc! { + "platform":to_bson(&release_version.platform)? + }; + let exist_latest_version = collection + .with_mapping::() + .doing(|collection| { + collection.find_one( + filter, + FindOneOptions::builder() + .sort(doc! {"$natural": -1i32}) + .projection(doc! {"version": 1i32}) + .build(), + ) + }) + .await?; + + match exist_latest_version { + Some(VersionOnly { version }) + if release_version.version <= version => + { + Err(Error::VersionTooOld(version, release_version.platform)) + } + _ => Ok(()), + } +} diff --git a/persistence/dao/fetcher/src/sql/datasource_combination/retrieve.rs b/persistence/dao/fetcher/src/sql/datasource_combination/retrieve.rs index 2857a2454..36a21b391 100644 --- a/persistence/dao/fetcher/src/sql/datasource_combination/retrieve.rs +++ b/persistence/dao/fetcher/src/sql/datasource_combination/retrieve.rs @@ -31,7 +31,7 @@ impl DatasourceCombinationOperate<'_, NoConnect> { Ok(Entity::find() .from_raw_sql(Statement::from_sql_and_values( db.get_database_backend(), - &query.to_string(MysqlQueryBuilder).to_lowercase(), + query.to_string(MysqlQueryBuilder).to_lowercase(), [], )) .into_model::() diff --git a/persistence/database/database_traits/Cargo.toml b/persistence/database/database_traits/Cargo.toml index 1552da3d0..54d1cc7e3 100644 --- a/persistence/database/database_traits/Cargo.toml +++ b/persistence/database/database_traits/Cargo.toml @@ -14,3 +14,4 @@ get-connect = [] axum-core = { workspace = true } futures.workspace = true http = { workspace = true } +paste = "1.0.15" diff --git a/persistence/database/database_traits/src/database_operates/dao_macros.rs b/persistence/database/database_traits/src/database_operates/dao_macros.rs new file mode 100644 index 000000000..2688357b6 --- /dev/null +++ b/persistence/database/database_traits/src/database_operates/dao_macros.rs @@ -0,0 +1,92 @@ +#[macro_export] +macro_rules! dao_operator { + ($parent:ty=>$curr:ident($cove:ident, err=$err:ty)) => { + $crate::paste!{ + pub struct [<$curr Operate>]<'db,Conn>(&'db Conn); + + impl <'db, Conn> $crate::SubOperate<'db> for [<$curr Operate>]<'db,Conn>{ + type Parent = $parent<'db,Conn>; + + fn from_parent(parent: &'db Self::Parent)->Self{ + Self(parent) + } + } + + impl <'db, Conn> std::ops::Deref for [<$curr Operate>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + + impl<'db, Conn> $parent<'db, Conn> { + pub fn $cove(&self) -> [<$curr Operate>]<'_, Conn> { + $crate::SuperOperate::child(self) + } + } + + pub struct [<$curr Create>]<'db,Conn>(&'db Conn); + pub struct [<$curr Delete>]<'db,Conn>(&'db Conn); + pub struct [<$curr Retrieve>]<'db,Conn>(&'db Conn); + pub struct [<$curr Update>]<'db,Conn>(&'db Conn); + pub struct [<$curr Verify>]<'db,Conn>(&'db Conn); + + impl <'db, Conn> $crate::OperateTrait<'db> for [<$curr Operate>]<'db,Conn>{ + type Create = [<$curr Create>]<'db,Conn>; + type Delete = [<$curr Delete>]<'db,Conn>; + type Retrieve = [<$curr Retrieve>]<'db,Conn>; + type Update = [<$curr Update>]<'db,Conn>; + type Verify = [<$curr Verify>]<'db,Conn>; + + type Error = $err; + + fn create(&self)->Self::Create{ + [<$curr Create>](self.0) + } + + fn delete(&self)->Self::Delete{ + [<$curr Delete>](self.0) + } + + fn retrieve(&self)->Self::Retrieve{ + [<$curr Retrieve>](self.0) + } + + fn update(&self)->Self::Update{ + [<$curr Update>](self.0) + } + + fn verify(&self)->Self::Verify{ + [<$curr Verify>](self.0) + } + } + + impl <'db, Conn> std::ops::Deref for [<$curr Create>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + impl <'db, Conn> std::ops::Deref for [<$curr Delete>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + impl <'db, Conn> std::ops::Deref for [<$curr Retrieve>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + impl <'db, Conn> std::ops::Deref for [<$curr Update>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + impl <'db, Conn> std::ops::Deref for [<$curr Verify>]<'db,Conn>{ + type Target = Conn; + + fn deref(&self) -> &Self::Target { self.0 } + } + + type Result = core::result::Result; + } + }; +} diff --git a/persistence/database/database_traits/src/database_operates/mod.rs b/persistence/database/database_traits/src/database_operates/mod.rs index a93508560..1e1b26ae1 100644 --- a/persistence/database/database_traits/src/database_operates/mod.rs +++ b/persistence/database/database_traits/src/database_operates/mod.rs @@ -1,6 +1,7 @@ use std::ops::{Deref, DerefMut}; - +mod dao_macros; mod db_op_impls; +pub mod operate_trait; pub mod sub_operate; #[derive(Clone)] @@ -8,6 +9,10 @@ pub struct DatabaseOperate { connect: C, } +impl DatabaseOperate { + pub fn new(connect: C) -> Self { Self { connect } } +} + impl DerefMut for DatabaseOperate { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.connect } } diff --git a/persistence/database/database_traits/src/database_operates/operate_trait.rs b/persistence/database/database_traits/src/database_operates/operate_trait.rs new file mode 100644 index 000000000..158bd0984 --- /dev/null +++ b/persistence/database/database_traits/src/database_operates/operate_trait.rs @@ -0,0 +1,21 @@ +pub trait OperateTrait<'db> { + type Create; + type Delete; + + type Retrieve; + type Update; + + type Verify; + + type Error; + + fn create(&self) -> Self::Create; + + fn delete(&self) -> Self::Delete; + + fn retrieve(&self) -> Self::Retrieve; + + fn update(&self) -> Self::Update; + + fn verify(&self) -> Self::Verify; +} diff --git a/persistence/database/database_traits/src/get_connect.rs b/persistence/database/database_traits/src/get_connect.rs index d03f47ca0..8b2fb4110 100644 --- a/persistence/database/database_traits/src/get_connect.rs +++ b/persistence/database/database_traits/src/get_connect.rs @@ -1,6 +1,6 @@ use std::{error::Error as StdError, future::Future}; -pub use axum_core::extract::FromRequestParts; +pub use axum_core::extract::{FromRef, FromRequestParts}; pub use http::request::Parts; /// 获取数据库连接, 以及后续操作基本trait diff --git a/persistence/database/database_traits/src/lib.rs b/persistence/database/database_traits/src/lib.rs index 8c9ae27e7..e6ccf3a72 100644 --- a/persistence/database/database_traits/src/lib.rs +++ b/persistence/database/database_traits/src/lib.rs @@ -8,3 +8,9 @@ pub type BoxedResultFuture<'r, T, E> = Pin> + 'r>>; pub type BoxedResultSendFuture<'r, T, E> = Pin> + 'r + Send>>; + +pub use database_operates::{ + operate_trait::OperateTrait, + sub_operate::{SubOperate, SuperOperate}, +}; +pub use paste::paste; diff --git a/persistence/database/mongo_connection/src/config.rs b/persistence/database/mongo_connection/src/config.rs index 35e008a77..4fba4f9c0 100644 --- a/persistence/database/mongo_connection/src/config.rs +++ b/persistence/database/mongo_connection/src/config.rs @@ -23,6 +23,19 @@ pub struct MongoDbConfig { query: HashMap, } +impl Default for MongoDbConfig { + fn default() -> Self { + Self { + username: "ceobe".into(), + password: "114514".into(), + host: host_default(), + port: port_default(), + db_name: "ceobe_canteen".into(), + query: Default::default(), + } + } +} + impl DbConnectConfig for MongoDbConfig { fn scheme(&self) -> &str { "mongodb" } diff --git a/persistence/database/mongo_connection/src/database/manager.rs b/persistence/database/mongo_connection/src/database/manager.rs index 36ca1eef1..aee885d14 100644 --- a/persistence/database/mongo_connection/src/database/manager.rs +++ b/persistence/database/mongo_connection/src/database/manager.rs @@ -47,13 +47,13 @@ impl DatabaseManage { } /// 对完成获取的数据库进行数据操作 - /// - handle 为一个异步操作闭包 - /// 形如 `async fn function(&Collection)->Result` + /// - handle 为一个异步操作闭包 形如 `async fn + /// function(&Collection)->Result` /// /// - 这里要求 E 允许 `MongodbError` 可以转换为E /// - /// - 函数通过泛型参数自动识别并寻找对应的Collection - /// 如果Collection 未被创建,就会允许失败 + /// - 函数通过泛型参数自动识别并寻找对应的Collection 如果Collection + /// 未被创建,就会允许失败 pub async fn doing( &self, handle: F, ) -> Result diff --git a/persistence/database/mongo_connection/src/lib.rs b/persistence/database/mongo_connection/src/lib.rs index 4960f7aab..245ae1390 100644 --- a/persistence/database/mongo_connection/src/lib.rs +++ b/persistence/database/mongo_connection/src/lib.rs @@ -24,3 +24,4 @@ pub type MongoDatabaseOperate = database_traits::database_operates::DatabaseOperate; pub use mongodb; +pub use static_vars::{get_mongo_collection, get_mongo_database}; diff --git a/persistence/migrate/mongo-migration/Cargo.toml b/persistence/migrate/mongo-migration/Cargo.toml index 40e9b3e12..0ce71557c 100644 --- a/persistence/migrate/mongo-migration/Cargo.toml +++ b/persistence/migrate/mongo-migration/Cargo.toml @@ -17,3 +17,9 @@ path = "../../models/mongo-models" [dependencies.mongo-migrate-util] path = "../../../libs/mongo-migrate-util" + +[dev-dependencies] +database_traits = { path = "../../database/database_traits", features = ["all", "get-connect", "initial"] } +mongo_connection = { path = "../../database/mongo_connection" } + +tokio = { workspace = true, features = ["test-util"] } diff --git a/persistence/migrate/mongo-migration/src/lib.rs b/persistence/migrate/mongo-migration/src/lib.rs index a062fa6ee..18fcb3271 100644 --- a/persistence/migrate/mongo-migration/src/lib.rs +++ b/persistence/migrate/mongo-migration/src/lib.rs @@ -24,9 +24,46 @@ impl MigratorTrait for Migrator { .await? .append(migrations::ceobe::cookie::terra_comic::Migration) .await? + .append(migrations::ceobe::operation::release_version::Migration) + .await? .append(migrations::ceobe::operation::tool_link::Migration) .await?; Ok(()) } } + +#[cfg(test)] +mod test { + use database_traits::initial::connect_db_with_migrate; + use mongo_connection::{DatabaseManage, DbConnectConfig}; + use serde::Deserialize; + + use crate::Migrator; + + #[tokio::test] + async fn test_migrate() { + #[derive(Deserialize)] + pub struct MongoDbConfig; + impl DbConnectConfig for MongoDbConfig { + fn scheme(&self) -> &str { "mongodb" } + + fn username(&self) -> &str { "ceobe" } + + fn password(&self) -> &str { "114514" } + + fn host(&self) -> &str { "localhost" } + + fn port(&self) -> u16 { 27017 } + + fn name(&self) -> &str { "ceobe_canteen" } + } + + let _ = connect_db_with_migrate::( + &MongoDbConfig, + Migrator, + ) + .await + .expect("Migrate error"); + } +} diff --git a/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/mod.rs b/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/mod.rs index 29a581318..291184df1 100644 --- a/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/mod.rs +++ b/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/mod.rs @@ -1,2 +1,3 @@ pub mod plugin_version; +pub mod release_version; pub mod tool_link; diff --git a/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/release_version.rs b/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/release_version.rs new file mode 100644 index 000000000..f82d493a4 --- /dev/null +++ b/persistence/migrate/mongo-migration/src/migrations/ceobe/operation/release_version.rs @@ -0,0 +1,37 @@ +use async_trait::async_trait; +use mongo_migrate_util::{CollectManage, MigrationTrait}; +use mongo_models::ceobe::operation::version::models::ReleaseVersion; +use mongodb::{bson::doc, error::Error, options::IndexOptions, IndexModel}; + +const UNIQUE_KEY: &str = "unique_version_platform"; + +pub struct Migration; +#[async_trait] +impl MigrationTrait for Migration { + type Model = ReleaseVersion; + + fn name(&self) -> &'static str { "ceobe_operation_release_version" } + + async fn migrate( + &self, mut collection: CollectManage, + ) -> Result<(), Error> { + collection + .create_idx_if_not_exist( + IndexModel::builder() + .keys(doc! { + "version": 1i32, + "platform": 1i32 + }) + .options( + IndexOptions::builder() + .unique(true) + .name(UNIQUE_KEY.to_owned()) + .build(), + ) + .build(), + None, + ) + .await?; + Ok(()) + } +} diff --git a/persistence/models/mongo-models/Cargo.toml b/persistence/models/mongo-models/Cargo.toml index f2daa0ea7..e0fe26547 100644 --- a/persistence/models/mongo-models/Cargo.toml +++ b/persistence/models/mongo-models/Cargo.toml @@ -17,6 +17,9 @@ modify-cache = { path = "../../../libs/modify-cache" } bool_or.workspace = true serde_json.workspace = true uuid.workspace = true +semver = { version = "1.0.23", features = ["serde"] } +sql-models = { version = "0.1.0", path = "../sql-models" } +tracing-unwrap.workspace = true [dependencies.sub-model] workspace = true diff --git a/persistence/models/mongo-models/src/ceobe/operation/mod.rs b/persistence/models/mongo-models/src/ceobe/operation/mod.rs index 29a581318..cbe05be4c 100644 --- a/persistence/models/mongo-models/src/ceobe/operation/mod.rs +++ b/persistence/models/mongo-models/src/ceobe/operation/mod.rs @@ -1,2 +1,3 @@ pub mod plugin_version; pub mod tool_link; +pub mod version; diff --git a/persistence/models/mongo-models/src/ceobe/operation/plugin_version/models/mod.rs b/persistence/models/mongo-models/src/ceobe/operation/plugin_version/models/mod.rs index 120c216c3..352dbbdb8 100644 --- a/persistence/models/mongo-models/src/ceobe/operation/plugin_version/models/mod.rs +++ b/persistence/models/mongo-models/src/ceobe/operation/plugin_version/models/mod.rs @@ -28,7 +28,7 @@ pub struct DownloadResource { #[sub_model(all( vis = "pub", name = "PluginVersionChecked", - extra(derive(Debug, TypedBuilder)) + extra(derive(Debug, TypedBuilder, Clone)) ))] pub struct PluginVersion { pub version: Version, diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/checker.rs b/persistence/models/mongo-models/src/ceobe/operation/version/checker.rs new file mode 100644 index 000000000..dedceee72 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/checker.rs @@ -0,0 +1,5 @@ +use checker::prefabs::no_check::NoCheck; + +use crate::ceobe::operation::version::models::ReleaseVersion; + +pub type ReleaseVersionChecker = NoCheck; diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/mod.rs b/persistence/models/mongo-models/src/ceobe/operation/version/mod.rs new file mode 100644 index 000000000..ed3aa4d71 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/mod.rs @@ -0,0 +1,2 @@ +pub mod checker; +pub mod models; diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/conv.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/conv.rs new file mode 100644 index 000000000..08b245f04 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/conv.rs @@ -0,0 +1,258 @@ +use semver::Version; +use sql_models::ceobe_operation::{app_version, desktop_version}; +use tracing_unwrap::ResultExt; + +use crate::ceobe::operation::{ + plugin_version::{self, DownloadResource, SpareLink}, + version::models::{ + DownloadSourceItem, ForceCtrl, Primary, + ReleasePlatform::{Desktop, Plugin, Pocket}, + ReleaseVersion, ResourceUrl, + SupportPlatform::{Android, MacOS, Windows}, + }, +}; + +impl From for ReleaseVersion { + fn from( + plugin_version::Checked { + version: + checker::prefabs::version_checker::Version { + major, + minor, + security, + }, + description, + down: + DownloadResource { + crx, + spare_crx, + zip, + spare_zip, + chrome, + edge, + firefox, + spare: SpareLink { url, msg }, + }, + .. + }: plugin_version::Checked, + ) -> Self { + ReleaseVersion::builder() + .version(Version::new(major as _, minor as _, security as _)) + .description(description) + .platform(Plugin) + .force( + ForceCtrl::builder() + .force_update() + .previous_force_version(Version::new( + major as _, + minor as _, + security as _, + )) + .build(), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("CRX") + .primary_url( + ResourceUrl::builder().name(Primary).url(crx).build(), + ) + .extend_spare_url(spare_crx.map(|url| { + ResourceUrl::builder() + .name("CRX备用") + .url(url) + .manual() + .build() + })) + .build(), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("ZIP 包下载") + .primary_url( + ResourceUrl::builder().name(Primary).url(zip).build(), + ) + .extend_spare_url(spare_zip.map(|url| { + ResourceUrl::builder() + .name("ZIP备用") + .url(url) + .manual() + .build() + })) + .build(), + ) + .extend_download_source( + ["Chrome", "Edge", "FireFox"] + .into_iter() + .zip([chrome, edge, firefox]) + .map(|(name, url)| { + DownloadSourceItem::builder() + .name(name) + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(url) + .build(), + ) + .build() + }), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("云盘备用") + .description(msg) + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(url) + .manual() + .build(), + ) + .build(), + ) + .build() + } +} + +impl From for ReleaseVersion { + fn from( + app_version::Checked { + version, + force, + last_force_version, + description, + apk, + spare_apk, + baidu, + baidu_text, + }: app_version::Checked, + ) -> Self { + ReleaseVersion::builder() + // 经过校验的version,没有问题 + .version(version.parse().unwrap_or_log()) + .force( + ForceCtrl::builder() + .set_force_update(force) + .previous_force_version( + last_force_version.parse().unwrap_or_log(), + ) + .build(), + ) + .platform(Pocket) + .description(description) + .add_download_source( + DownloadSourceItem::builder() + .name("安卓下载") + .primary_url( + ResourceUrl::builder().name(Primary).url(apk).build(), + ) + .add_spare_url( + ResourceUrl::builder() + .name("安卓备用下载") + .url(spare_apk) + .manual() + .add_support_platform(Android) + .build(), + ) + .build(), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("百度云盘下载") + .description(baidu_text) + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(baidu) + .manual() + .build(), + ) + .build(), + ) + .build() + } +} + +impl From for ReleaseVersion { + fn from( + desktop_version::Checked { + version, + force, + last_force_version, + description, + exe, + spare_exe, + dmg, + spare_dmg, + baidu, + baidu_text, + }: desktop_version::Checked, + ) -> Self { + ReleaseVersion::builder() + // 经过校验的version,没有问题 + .version(version.parse().unwrap_or_log()) + .force( + ForceCtrl::builder() + .set_force_update(force) + .previous_force_version( + last_force_version.parse().unwrap_or_log(), + ) + .build(), + ) + .platform(Desktop) + .description(description) + .add_download_source( + DownloadSourceItem::builder() + .name("Windows安装包下载(.exe)") + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(exe) + .add_support_platform(Windows) + .build(), + ) + .add_spare_url( + ResourceUrl::builder() + .name("Windows安装包备用下载") + .url(spare_exe) + .manual() + .add_support_platform(Windows) + .build(), + ) + .build(), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("MacOS安装包下载(.dmg)") + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(dmg) + .add_support_platform(MacOS) + .build(), + ) + .add_spare_url( + ResourceUrl::builder() + .name("MacOS安装包备用下载") + .url(spare_dmg) + .manual() + .add_support_platform(MacOS) + .build(), + ) + .build(), + ) + .add_download_source( + DownloadSourceItem::builder() + .name("百度云盘下载") + .description(baidu_text) + .primary_url( + ResourceUrl::builder() + .name(Primary) + .url(baidu) + .manual() + .build(), + ) + .build(), + ) + .build() + } +} diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/download_source.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/download_source.rs new file mode 100644 index 000000000..0ede74726 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/download_source.rs @@ -0,0 +1,99 @@ +use serde::{Deserialize, Serialize}; +use typed_builder::TypedBuilder; +use url::Url; + +use super::primary::SkipPrimarySerialize; +use crate::ceobe::operation::version::models::{ + platform::SupportPlatform, primary::Primary, +}; +/// 可供使用的下载源 +#[derive(Debug, Serialize, Clone, Deserialize, TypedBuilder, PartialEq)] +#[builder(mutators( + /// 一次添加一个备用下载源 + pub fn add_spare_url(&mut self, spare: ResourceUrl){ + self.spare_urls.push(spare) + } + /// 一次添加多个备用下载源 + pub fn extend_spare_url( + &mut self, + spares: impl IntoIterator + ){ + self.spare_urls.extend(spares) + } +),doc)] +pub struct DownloadSourceItem { + /// 下载源的名称,例如 “百度云盘”、“Github”等 + #[builder(setter( + doc = "下载源的名称,例如 “百度云盘”、“Github”等", + into + ))] + name: String, + /// 下载源的描述,可选内容 + #[builder(default)] + #[builder(setter(doc = "下载源的描述,可选内容", into, strip_option))] + #[serde(skip_serializing_if = "Option::is_none", default)] + description: Option, + /// 下载源的主要URL + #[builder(setter(doc = "下载源的主要URL"))] + primary_url: ResourceUrl, + /// 下载源的备用URL,可空 + #[builder(via_mutators)] + #[serde(skip_serializing_if = "Vec::is_empty", default)] + spare_urls: Vec, +} + +/// 下载源的备用URL +#[derive(Debug, Clone, Deserialize, Serialize, TypedBuilder, PartialEq)] +#[builder(doc, mutators( + pub fn add_support_platform(&mut self, platform: SupportPlatform){ + self.support_platforms.push(platform) + } +))] +pub struct ResourceUrl { + /// 下载源备用URL的名称 + #[builder(setter(doc = "下载源URL的名称", into))] + #[serde( + skip_serializing_if = "SkipPrimarySerialize::should_skip", + bound = "for<'d>Name: SkipPrimarySerialize + \ + Serialize+Deserialize<'d>", + default + )] + name: Name, + /// 下载源备用URL的URL + #[builder(setter(doc = "下载源URL的URL"))] + url: Url, + #[builder(setter(strip_bool))] + manual: bool, + #[builder(via_mutators)] + #[serde(skip_serializing_if = "Vec::is_empty", default)] + support_platforms: Vec, +} + +#[cfg(test)] +mod test { + use crate::ceobe::operation::version::models::download_source::{ + DownloadSourceItem, Primary, ResourceUrl, + }; + #[test] + fn test_construct_spare() { + let item = DownloadSourceItem::builder() + .extend_spare_url([ResourceUrl::builder() + .url("http://example.com".parse().unwrap()) + .name("example backup".to_string()) + .build()]) + .name("ABC".to_string()) + .primary_url( + ResourceUrl::builder() + .url("http://primary.com".parse().unwrap()) + .name(Primary) + .build(), + ) + .build(); + println!("{item:?}") + } + #[test] + fn test_primary_serde() { + let a = serde_json::to_string(&Primary).unwrap(); + assert_eq!(a, "\"primary\"") + } +} diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/force.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/force.rs new file mode 100644 index 000000000..56a7193bc --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/force.rs @@ -0,0 +1,29 @@ +use semver::Version; +use serde::{Deserialize, Serialize}; +use typed_builder::TypedBuilder; + +#[derive(Debug, Serialize, Deserialize, Clone, TypedBuilder, PartialEq)] +#[builder(mutators( + pub fn force_update(&mut self){ + self.force_update = true + } + pub fn set_force_update(&mut self,force:bool){ + self.force_update = force + } +))] +pub struct ForceCtrl { + #[builder(via_mutators)] + force_update: bool, + previous_force_version: Version, +} + +#[cfg(test)] +mod test { + use semver::Version; + #[test] + fn test_version_serde() { + let ver = Version::new(1, 1, 1); + let s = serde_json::to_string(&ver).unwrap(); + assert_eq!(s, "\"1.1.1\"") + } +} diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/mod.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/mod.rs new file mode 100644 index 000000000..9fc19a513 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/mod.rs @@ -0,0 +1,13 @@ +mod conv; +mod download_source; +mod force; +mod platform; +mod primary; +mod version; + +pub use download_source::{DownloadSourceItem, ResourceUrl}; +pub use force::ForceCtrl; +pub use platform::{ReleasePlatform, SupportPlatform}; +pub use primary::Primary; +pub use semver::Version; +pub use version::ReleaseVersion; diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/platform.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/platform.rs new file mode 100644 index 000000000..1815eed42 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/platform.rs @@ -0,0 +1,60 @@ +use std::fmt::{Display, Formatter}; + +use serde::{Deserialize, Serialize}; + +/// 下载源对应的平台 +#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum ReleasePlatform { + /// 插件端 + Plugin, + /// 桌面端 + Desktop, + /// 口袋端(Android,IOS,WP等) + Pocket, +} + +impl Display for ReleasePlatform { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ReleasePlatform::Plugin => { + write!(f, "plugin") + } + ReleasePlatform::Desktop => { + write!(f, "desktop") + } + ReleasePlatform::Pocket => { + write!(f, "pocket") + } + } + } +} + +/// 当前下载源支持的平台 +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum SupportPlatform { + // desktop + /// linux发行版桌面端,能兼容X11和Wayland + Linux, + MacOS, + Windows, + // plugin + Chrome, + Firefox, + Edge, + /// Webkit, Linux平台上基于webkit4gtk-dev等开发的轻量化浏览器 + Webkit, + /// MacOS\IPadOS\IOS的内置浏览器 + Safari, + /// 微软的Internet Explorer 浏览器 + IE, + /// 其他使用ZIP安装的浏览器 + BrowserZIP, + // pocket + Android, + Ios, + WindowsPhone, + /// 鸿蒙系统 + Harmony, +} diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/primary.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/primary.rs new file mode 100644 index 000000000..7ba709d4e --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/primary.rs @@ -0,0 +1,46 @@ +use serde::{ + de::Unexpected, Deserialize, Deserializer, Serialize, Serializer, +}; + +#[derive(Debug, Copy, Clone, Default, PartialEq)] +pub struct Primary; + +impl<'de> Deserialize<'de> for Primary { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = + as Deserialize<'de>>::deserialize(deserializer)?; + match s { + Some("primary") | None => Ok(Primary), + Some(s) => { + Err(serde::de::Error::invalid_value( + Unexpected::Str(s), + &"primary", + )) + } + } + } +} + +impl Serialize for Primary { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str("primary") + } +} + +pub trait SkipPrimarySerialize { + fn should_skip(&self) -> bool; +} + +impl SkipPrimarySerialize for Primary { + fn should_skip(&self) -> bool { true } +} + +impl SkipPrimarySerialize for String { + fn should_skip(&self) -> bool { false } +} diff --git a/persistence/models/mongo-models/src/ceobe/operation/version/models/version.rs b/persistence/models/mongo-models/src/ceobe/operation/version/models/version.rs new file mode 100644 index 000000000..81ea0ee55 --- /dev/null +++ b/persistence/models/mongo-models/src/ceobe/operation/version/models/version.rs @@ -0,0 +1,129 @@ +use semver::Version; +use serde::{Deserialize, Serialize}; +use typed_builder::TypedBuilder; + +use crate::ceobe::operation::version::models::{ + download_source::DownloadSourceItem, force::ForceCtrl, + platform::ReleasePlatform, +}; + +#[derive(Debug, Serialize, Deserialize, Clone, TypedBuilder, PartialEq)] +#[builder(mutators( + /// 一次添加一个下载源 + pub fn add_download_source(&mut self, source: DownloadSourceItem){ + self.download_source.push(source) + } + /// 一次添加多个下载源 + pub fn extend_download_source(&mut self, sources: impl IntoIterator){ + self.download_source.extend(sources) + } + ) +)] +pub struct ReleaseVersion { + /// 当前要发布的版本号 + pub version: Version, + /// 发布的版本更新控制 + force: ForceCtrl, + /// 发布的版本的说明 + #[builder(default, setter(into, strip_option))] + #[serde(skip_serializing_if = "Option::is_none")] + description: Option, + /// 该版本发布的平台 + pub platform: ReleasePlatform, + /// 该版本的可用下载源 + #[builder(via_mutators)] + download_source: Vec, + #[builder(default = false)] + deleted: bool, +} + +#[cfg(test)] +mod test { + use semver::Version; + use serde_json::json; + + use crate::ceobe::operation::version::models::{ + platform::SupportPlatform, primary::Primary, DownloadSourceItem, + ForceCtrl, ReleasePlatform, ReleaseVersion, ResourceUrl, + }; + + #[test] + fn test_version_serde() { + let ver = ReleaseVersion::builder() + .version(Version::new(1, 13, 2)) + .force( + ForceCtrl::builder() + .previous_force_version(Version::new(1, 0, 0)) + .build(), + ) + .description("Abc") + .platform(ReleasePlatform::Desktop) + .add_download_source( + DownloadSourceItem::builder() + .name("百度云盘") + .description("PanBaidu") + .primary_url( + ResourceUrl::builder() + .url( + "https://pan.baidu.com/s/114514" + .parse() + .unwrap(), + ) + .name(Primary) + .manual() + .add_support_platform(SupportPlatform::Firefox) + .add_support_platform(SupportPlatform::Safari) + .build(), + ) + .add_spare_url( + ResourceUrl::builder() + .url( + "https://pan.baidu.com/s/1919810" + .parse() + .unwrap(), + ) + .name("百度云备用") + .build(), + ) + .build(), + ) + .build(); + + let serde = + serde_json::to_value(ver.clone()).expect("serde json error"); + assert_eq!( + serde, + json!({ + "version": "1.13.2", + "force": { + "force_update": false, + "previous_force_version": "1.0.0" + }, + "description": "Abc", + "platform": "desktop", + "download_source": [ + { + "name": "百度云盘", + "description": "PanBaidu", + "primary_url": { + "url":"https://pan.baidu.com/s/114514", + "manual":true, + "support_platforms":["Firefox","Safari"] + }, + "spare_urls": [ + { + "name": "百度云备用", + "url": "https://pan.baidu.com/s/1919810", + "manual":false + } + ] + } + ] + + }) + ); + + let ver_de = serde_json::from_value(serde).expect("Deserailze_err"); + assert_eq!(ver, ver_de) + } +} diff --git a/persistence/models/mongo-models/src/ceobe/user_property/models/mod.rs b/persistence/models/mongo-models/src/ceobe/user_property/models/mod.rs index 1c556ca94..8cd8f21ea 100644 --- a/persistence/models/mongo-models/src/ceobe/user_property/models/mod.rs +++ b/persistence/models/mongo-models/src/ceobe/user_property/models/mod.rs @@ -8,7 +8,7 @@ use sub_model::SubModel; use typed_builder::TypedBuilder; use crate::{RecordUnit, RecordUnitUpdater, SetRecordUnit}; - +#[allow(clippy::duplicated_attributes)] #[derive(Debug, Clone, Serialize, Deserialize, TypedBuilder, SubModel)] #[sub_model( all( diff --git a/persistence/models/sql-models/src/ceobe_operation/app_version/checkers/app_version_data.rs b/persistence/models/sql-models/src/ceobe_operation/app_version/checkers/app_version_data.rs index e086d1260..a89d6b8f2 100644 --- a/persistence/models/sql-models/src/ceobe_operation/app_version/checkers/app_version_data.rs +++ b/persistence/models/sql-models/src/ceobe_operation/app_version/checkers/app_version_data.rs @@ -3,16 +3,17 @@ use checker::prefabs::{ url_checker::UrlChecker, version_checker::VersionChecker, }; use sea_orm::{IntoActiveModel, Set}; +use tracing_unwrap::ResultExt; use typed_builder::TypedBuilder; use url::Url; -use super::CheckError; +use super::{super::models::model_app_version, CheckError}; use crate::{ ceobe_operation::app_version::models::model_app_version::ActiveModel, get_now_naive_date_time, }; -#[derive(Debug, TypedBuilder)] +#[derive(Debug, TypedBuilder, Clone)] pub struct CeobeOperationAppVersion { pub version: String, pub force: bool, @@ -24,6 +25,33 @@ pub struct CeobeOperationAppVersion { pub baidu_text: String, } +impl From for CeobeOperationAppVersion { + fn from( + model_app_version::Model { + version, + force, + last_force_version, + description, + apk, + spare_apk, + baidu, + baidu_text, + .. + }: model_app_version::Model, + ) -> Self { + Self { + version, + force, + last_force_version, + description, + apk: apk.parse().unwrap_or_log(), + spare_apk: spare_apk.parse().unwrap_or_log(), + baidu: baidu.parse().unwrap_or_log(), + baidu_text, + } + } +} + #[checker::check_gen( uncheck = CeobeOperationAppVersionUncheck, checked = CeobeOperationAppVersion, diff --git a/persistence/models/sql-models/src/ceobe_operation/desktop_version/checkers/desktop_version_data.rs b/persistence/models/sql-models/src/ceobe_operation/desktop_version/checkers/desktop_version_data.rs index 85da1d2d0..4ab92a716 100644 --- a/persistence/models/sql-models/src/ceobe_operation/desktop_version/checkers/desktop_version_data.rs +++ b/persistence/models/sql-models/src/ceobe_operation/desktop_version/checkers/desktop_version_data.rs @@ -3,16 +3,17 @@ use checker::prefabs::{ url_checker::UrlChecker, version_checker::VersionChecker, }; use sea_orm::{IntoActiveModel, Set}; +use tracing_unwrap::ResultExt; use typed_builder::TypedBuilder; use url::Url; -use super::CheckError; +use super::{super::models::model_desktop_version, CheckError}; use crate::{ ceobe_operation::desktop_version::models::model_desktop_version::ActiveModel, get_now_naive_date_time, }; -#[derive(Debug, TypedBuilder)] +#[derive(Debug, TypedBuilder, Clone)] pub struct CeobeOperationDesktopVersion { pub version: String, pub force: bool, @@ -26,6 +27,37 @@ pub struct CeobeOperationDesktopVersion { pub baidu_text: String, } +impl From for CeobeOperationDesktopVersion { + fn from( + model_desktop_version::Model { + version, + force, + last_force_version, + description, + exe, + spare_exe, + dmg, + spare_dmg, + baidu, + baidu_text, + .. + }: model_desktop_version::Model, + ) -> Self { + Self { + version, + force, + last_force_version, + description, + exe: exe.parse().unwrap_or_log(), + spare_exe: spare_exe.parse().unwrap_or_log(), + dmg: dmg.parse().unwrap_or_log(), + spare_dmg: spare_dmg.parse().unwrap_or_log(), + baidu: baidu.parse().unwrap_or_log(), + baidu_text, + } + } +} + #[checker::check_gen( uncheck = CeobeOperationDesktopVersionUncheck, checked = CeobeOperationDesktopVersion, diff --git a/persistence/models/sql-models/src/fetcher/datasource_config/models/model_datasource_config.rs b/persistence/models/sql-models/src/fetcher/datasource_config/models/model_datasource_config.rs index 3c207eacb..d243d7b56 100644 --- a/persistence/models/sql-models/src/fetcher/datasource_config/models/model_datasource_config.rs +++ b/persistence/models/sql-models/src/fetcher/datasource_config/models/model_datasource_config.rs @@ -9,6 +9,7 @@ use crate::{ NaiveDateTime, SoftDelete, }; +#[allow(clippy::duplicated_attributes)] #[derive(Debug, Clone, PartialEq, Eq, DeriveEntityModel, SubModel)] #[sea_orm(table_name = "fetcher_datasource_config")] #[sub_model( diff --git a/persistence/persistence/src/lib.rs b/persistence/persistence/src/lib.rs index bbb7ef428..ff9e8b1f9 100644 --- a/persistence/persistence/src/lib.rs +++ b/persistence/persistence/src/lib.rs @@ -25,7 +25,7 @@ pub mod ceobe_operate { pub use dao_ceobe_operate::*; pub mod models { - pub use mongo_models::ceobe::operation::plugin_version; + pub use mongo_models::ceobe::operation::{plugin_version, version}; pub use sql_models::ceobe_operation::*; } diff --git a/service/qiniu_service/src/impletements/datasource_comb.rs b/service/qiniu_service/src/impletements/datasource_comb.rs index dbd1badb8..71752774d 100644 --- a/service/qiniu_service/src/impletements/datasource_comb.rs +++ b/service/qiniu_service/src/impletements/datasource_comb.rs @@ -43,7 +43,7 @@ impl QiniuService { .remove(&comb_id) .await?; } - } + }; Ok(()) } diff --git a/src/bootstrap/init/component_init.rs b/src/bootstrap/init/component_init.rs index 6c9b6bbbb..19325acf0 100644 --- a/src/bootstrap/init/component_init.rs +++ b/src/bootstrap/init/component_init.rs @@ -1,5 +1,5 @@ +use axum_resp_result::ConfigTrait; use axum_starter::prepare; -use resp_result::ConfigTrait; use crate::utils::{ mob_verify, @@ -10,11 +10,11 @@ use crate::utils::{ #[prepare(RResultConfig?)] fn resp_conf( resp_result: &C, -) -> Result<(), resp_result::SetRespResultConfigureError> +) -> Result<(), axum_resp_result::SetRespResultConfigureError> where C: ConfigTrait, { - resp_result::try_set_config(resp_result) + axum_resp_result::try_set_config(resp_result) } /// 鉴权配置 diff --git a/src/bootstrap/middleware/panic_report.rs b/src/bootstrap/middleware/panic_report.rs index 8e6a047fd..5d3352ee6 100644 --- a/src/bootstrap/middleware/panic_report.rs +++ b/src/bootstrap/middleware/panic_report.rs @@ -1,11 +1,11 @@ use axum::response::IntoResponse; +use axum_resp_result::RespResult; use axum_starter::{prepare, PrepareMiddlewareEffect}; use persistence::operate::FromRequestParts; use qq_channel_warning::{ qq_channel_logger, GrpcConfigTrait, LogRequest, LogType, QqChannelGrpcService, }; -use resp_result::RespResult; use tower_http::catch_panic::{CatchPanicLayer, ResponseForPanic}; use tracing::{error, instrument}; @@ -49,17 +49,14 @@ impl ResponseForPanic for PanicReportHandle { &mut self, err: Box, ) -> http::Response { // TODO: 推送panic到频道好像有问题 - let err = if let Some(msg) = err + + let err = err .downcast_ref::() .map(String::as_str) .or_else(|| err.downcast_ref::<&str>().copied()) - { - msg - } - else { - "Unknown Panic Message" - } - .to_owned(); + .unwrap_or("Unknown Panic Message") + .to_owned(); + error!(unexpectedPanic.detail = err); let service = self.0.clone(); tokio::spawn(async move { diff --git a/src/bootstrap/mod.rs b/src/bootstrap/mod.rs index 87548e581..f18098be3 100644 --- a/src/bootstrap/mod.rs +++ b/src/bootstrap/mod.rs @@ -14,6 +14,7 @@ pub mod decorator; pub mod default_user; pub mod init; pub mod middleware; +pub mod postprepare; #[derive(Debug, Clone, FromRef, FromStateCollector)] pub struct State { diff --git a/src/bootstrap/postprepare/migrate_version.rs b/src/bootstrap/postprepare/migrate_version.rs new file mode 100644 index 000000000..fe5f358e3 --- /dev/null +++ b/src/bootstrap/postprepare/migrate_version.rs @@ -0,0 +1,184 @@ +use std::borrow::Cow; + +use axum_resp_result::{resp_result, RespError, RespResult}; +use bson::doc; +use futures::TryStreamExt; +use persistence::{ + ceobe_cookie::ToCeobe, + ceobe_operate::{ + app_version, desktop_version, + plugin_version::{PluginVersion, PluginVersionChecked}, + ToCeobeOperation, + }, + help_crates::sea_orm::{EntityTrait, QueryOrder}, + mongodb::{ + database_traits::OperateTrait, mongodb, + mongodb::options::FindOptions, MongoConnect, MongoDatabaseOperate, + MongoDbError, + }, + mysql::{sea_orm::DbErr, SqlConnect, SqlDatabaseOperate}, + operate::{DatabaseOperate, GetDatabaseConnect}, +}; +use qq_channel_warning::{ + LogRequest, LogType, QqChannelGrpcService, QqChannelGrpcState, +}; +use tracing::{error, info, instrument, warn}; +pub async fn migrate_version(qq_channel: QqChannelGrpcState) { + let qq_channel = QqChannelGrpcService::new_with_uri(qq_channel).await; + let mut qq_channel = match qq_channel { + Ok(qq_channel_warning) => qq_channel_warning, + Err(err) => { + error!(Action="Migrate Version", Error = %err); + return; + } + }; + + let a = raw_migrate_version( + DatabaseOperate::new(SqlConnect), + DatabaseOperate::new(MongoConnect), + ) + .await; + match a { + RespResult::Success(_) => {} + RespResult::Err(err) => { + qq_channel + .send_logger( + LogRequest::builder() + .info(format!("版本迁移时异常: {err}")) + .manual() + .level(LogType::Error) + .build(), + ) + .await + .ok(); + } + } +} + +#[resp_result] +#[instrument(skip_all)] +pub async fn raw_migrate_version( + sql: SqlDatabaseOperate, mongo: MongoDatabaseOperate, +) -> Result<(), Error> { + let mongo_conn = mongo.get_connect(); + + let sql = sql.get_connect(); + // 迁移 AppVersion + let all_app_version = app_version::Entity::find() + .order_by_asc(app_version::Column::CreateAt) + .all(sql) + .await?; + + info!( + Action = "Migrate Version", + Platform = "移动端", + Number = all_app_version.len() + ); + for ver in all_app_version { + let crr_ver = ver.version.clone(); + let result = mongo + .ceobe() + .operation() + .release_version() + .create() + .one(app_version::Checked::from(ver)) + .await; + + if let Err(err) = result { + warn!( + Action = "迁移旧版Version", + Version = crr_ver, + Platform = "移动端", + Error = %err + ); + } + } + + let all_desktop_version = desktop_version::Entity::find() + .order_by_asc(desktop_version::Column::CreateAt) + .all(sql) + .await?; + info!( + Action = "Migrate Version", + Platform = "桌面端", + Number = all_desktop_version.len() + ); + for ver in all_desktop_version { + let crr_ver = ver.version.clone(); + let result = mongo + .ceobe() + .operation() + .release_version() + .create() + .one(desktop_version::Checked::from(ver)) + .await; + + if let Err(err) = result { + warn!( + Action = "迁移旧版Version", + Version = crr_ver, + Platform = "桌面端", + Error = %err + ); + } + } + + let plugin_version_collection = + mongo_conn.get_collection::()?; + + let all_plugin_version = plugin_version_collection + .find( + doc! {}, + FindOptions::builder() + .sort(doc! {"time_record.create_at":1i32}) + .build(), + ) + .await? + .try_collect::>() + .await?; + + info!( + Action = "Migrate Version", + Platform = "插件端", + Number = all_plugin_version.len() + ); + for ver in all_plugin_version { + let crr_ver = ver.version; + let result = mongo + .ceobe() + .operation() + .release_version() + .create() + .one(PluginVersionChecked::from(ver)) + .await; + + if let Err(err) = result { + warn!( + Action = "迁移旧版Version", + Version = %crr_ver, + Platform = "插件端", + Error = %err + ); + } + } + info!(Action = "Migrate Version", Status = "完成"); + Ok(()) +} + +#[derive(Debug, thiserror::Error)] +enum Error { + #[error(transparent)] + Db(#[from] DbErr), + #[error(transparent)] + Mongo(#[from] MongoDbError), + #[error(transparent)] + MongoErr(#[from] mongodb::error::Error), +} + +impl RespError for Error { + type ExtraMessage = i32; + + fn log_message(&self) -> Cow<'_, str> { self.to_string().into() } + + fn extra_message(&self) -> Self::ExtraMessage { 0 } +} diff --git a/src/bootstrap/postprepare/mod.rs b/src/bootstrap/postprepare/mod.rs new file mode 100644 index 000000000..4cc9939e4 --- /dev/null +++ b/src/bootstrap/postprepare/mod.rs @@ -0,0 +1,3 @@ +mod migrate_version; + +pub use migrate_version::migrate_version; diff --git a/src/configs/resp_result_config.rs b/src/configs/resp_result_config.rs index b32154e0e..e7f2bc6c4 100644 --- a/src/configs/resp_result_config.rs +++ b/src/configs/resp_result_config.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use resp_result::{ConfigTrait, RespConfig, SignType, StatusSign}; +use axum_resp_result::{ConfigTrait, RespConfig, SignType, StatusSign}; #[derive(Debug, serde::Deserialize)] pub struct RespResultConfig { @@ -22,7 +22,7 @@ pub struct RespResultConfig { impl ConfigTrait for RespResultConfig {} -impl resp_result::SerdeConfig for RespResultConfig { +impl axum_resp_result::SerdeConfig for RespResultConfig { fn body_name(&self) -> Cow<'static, str> { self.body_name.clone().into() } fn err_msg_name(&self) -> Cow<'static, str> { diff --git a/src/error/mod.rs b/src/error/mod.rs index 81dc31583..928b99e61 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -3,25 +3,25 @@ use std::any::Any; use axum::{ body::Body as BoxBody, extract::OriginalUri, response::IntoResponse, }; +use axum_resp_result::RespResult; use http::Method; -use resp_result::RespResult; use status_err::ErrPrefix; use tracing::{error, instrument, warn}; #[macro_export] -/// 1. 辅助构造枚举形式的Error, -/// 并提供 [Form](std::convert::Form)转换实现, -/// 和 [StatusErr](status_err::StatusErr)实现 -/// ```rust +/// 1. 辅助构造枚举形式的Error, 并提供 [Form](std::convert::Form)转换实现, 和 +/// [StatusErr](status_err::StatusErr)实现 +/// +/// ```rust /// error_generate!( -/// // |------- 构造的枚举型异常的类型名称 -/// pub GolbalError -/// // |--------------枚举类型的名称 -/// // | |-------每一枚举类型内部的类型 -/// Io=std::io::Error // 多个内部类型用空格区分 -/// Db=sea_orm::DbErr +/// // |------- 构造的枚举型异常的类型名称 +/// pub GolbalError +/// // |--------------枚举类型的名称 +/// // | |-------每一枚举类型内部的类型 +/// Io=std::io::Error // 多个内部类型用空格区分 +/// Db=sea_orm::DbErr /// ); -/// ``` +/// ``` /// 2. 为现有类型生成包装类型 /// ```rust /// error_generate!( diff --git a/src/main.rs b/src/main.rs index 3f43754cd..df66a0f1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,7 +38,7 @@ use tencent_cloud_server::axum_starter::TencentCloudPrepare; use tower_http::compression::CompressionLayer; use tracing_unwrap::ResultExt; -use crate::bootstrap::decorator::Decroator; +use crate::bootstrap::{decorator::Decroator, postprepare::migrate_version}; mod bootstrap; mod configs; @@ -104,6 +104,7 @@ async fn main_task() { .layer(CompressionLayer::new()) .prepare_middleware::(PrepareRequestTracker) .graceful_shutdown(graceful_shutdown()) + .post_prepare(migrate_version) .preparing() .await .expect("准备启动服务异常") diff --git a/src/middleware/authorize/mod.rs b/src/middleware/authorize/mod.rs index e66e1aca1..f416c47c6 100644 --- a/src/middleware/authorize/mod.rs +++ b/src/middleware/authorize/mod.rs @@ -1,9 +1,9 @@ use async_trait::async_trait; use axum::extract::FromRequestParts; +use axum_resp_result::{Nil, RespResult}; use http::request::Parts; pub use layer::AuthorizeLayer; use persistence::admin; -use resp_result::{Nil, RespResult}; pub use self::error::AuthorizeError; diff --git a/src/middleware/authorize/service.rs b/src/middleware/authorize/service.rs index cb27d323e..51e7b6a29 100644 --- a/src/middleware/authorize/service.rs +++ b/src/middleware/authorize/service.rs @@ -5,6 +5,7 @@ use axum::{ extract::FromRequestParts, response::{IntoResponse, Response}, }; +use axum_resp_result::RespResult; use futures::future::BoxFuture; use http::Request; use persistence::{ @@ -14,7 +15,6 @@ use persistence::{ }, mysql::SqlDatabaseOperate, }; -use resp_result::RespResult; use tap::Tap; use tower_http::auth::AsyncAuthorizeRequest; use tracing::{info, warn, Instrument}; diff --git a/src/middleware/mob/mod.rs b/src/middleware/mob/mod.rs index 53eae2653..2645e2a8d 100644 --- a/src/middleware/mob/mod.rs +++ b/src/middleware/mob/mod.rs @@ -1,9 +1,9 @@ use async_trait::async_trait; use axum::extract::FromRequestParts; +use axum_resp_result::{Nil, RespResult}; use http::request::Parts; pub use layer::MobVerifyLayer; use persistence::ceobe_user::models::models::UserMobId; -use resp_result::{Nil, RespResult}; use self::error::MobVerifyError; diff --git a/src/middleware/mob/service.rs b/src/middleware/mob/service.rs index bcb7be274..ace571c23 100644 --- a/src/middleware/mob/service.rs +++ b/src/middleware/mob/service.rs @@ -3,6 +3,7 @@ use axum::{ extract::FromRequestParts, response::{IntoResponse, Response}, }; +use axum_resp_result::RespResult; use bool_or::TrueOrError; use futures::future::BoxFuture; use http::Request; @@ -11,7 +12,6 @@ use persistence::{ ceobe_user::{models::models::UserMobId, ToCeobeUser}, mongodb::MongoDatabaseOperate, }; -use resp_result::RespResult; use tap::Tap; use tower_http::auth::AsyncAuthorizeRequest; use tracing::{info, Instrument}; diff --git a/src/router/back_end/ceobe_operation/mod.rs b/src/router/back_end/ceobe_operation/mod.rs index f05079589..ff43f82b1 100644 --- a/src/router/back_end/ceobe_operation/mod.rs +++ b/src/router/back_end/ceobe_operation/mod.rs @@ -1,6 +1,7 @@ pub use announcement::CeobeOperationAnnouncement; -use axum::Router; +use release_version_service::ReleaseVersionController; pub use resource::CeobeOpResource; +use serve_utils::{endpoint::AdminEnd, ControllerRouter}; pub use tool_link::CeobeOpToolLink; pub use version::CeobeOpVersion; pub use video::CeobeOperationVideo; @@ -23,13 +24,15 @@ mod version; mod video; pub(super) fn ceobe_operation_router() -> crate::router::ServerRoute { - Router::new() + ControllerRouter::new(AdminEnd) .nest("/announcement", announcement_router()) .nest("/video", video_router()) .nest("/version", version_router()) .nest("/resource", resource_router()) + .nest_controller(ReleaseVersionController) .route_layer(AuthorizeLayer::::new()) .nest("/toolLink", tool_link_router()) + .into() } new_auth_level! { diff --git a/src/router/cdn/operation/mod.rs b/src/router/cdn/operation/mod.rs index 50247f064..24ddefefc 100644 --- a/src/router/cdn/operation/mod.rs +++ b/src/router/cdn/operation/mod.rs @@ -1,6 +1,7 @@ pub use announcement::CdnOperationAnnouncementFrontend; -use axum::Router; +use release_version_service::ReleaseVersionController; pub use resource::CdnOperationResourceFrontend; +use serve_utils::{endpoint::CDN, ControllerRouter}; pub use tool_link::CdnOperateToolLinkFrontend; pub use video::CdnOperationVideoFrontend; @@ -16,9 +17,11 @@ mod tool_link; mod video; pub(super) fn operation_router() -> ServerRoute { - Router::new() + ControllerRouter::new(CDN) .nest("/video", video_router()) .nest("/announcement", announcement_router()) .nest("/resource", resource_router()) + .nest_controller(ReleaseVersionController) .nest("/toolLink", tool_list_router()) + .into() } diff --git a/src/router/mod.rs b/src/router/mod.rs index e74a4be89..00e0bdb39 100644 --- a/src/router/mod.rs +++ b/src/router/mod.rs @@ -43,15 +43,18 @@ pub fn root_route() -> ServerRoute { .nest("/qiniuCdn", qiniu_cdn_router()) .route( "/panic", - get(|| async { - #[cfg(debug_assertions)] - { - panic!("测试 Panic"); + get(|| { + async { + #[cfg(debug_assertions)] + { + let f =||->&str{panic!("测试 Panic")}; + f() + } + #[cfg(not(debug_assertions))] + axum_resp_result::RespResult::<_, crate::error::NotAnError>::ok( + "不可以Panic", + ) } - #[cfg(not(debug_assertions))] - resp_result::RespResult::<_, crate::error::NotAnError>::ok( - "不可以Panic", - ) }), ) } diff --git a/src/serves/backend/bakery_mansion/controllers.rs b/src/serves/backend/bakery_mansion/controllers.rs index 9a4355ad1..9b380a607 100644 --- a/src/serves/backend/bakery_mansion/controllers.rs +++ b/src/serves/backend/bakery_mansion/controllers.rs @@ -1,7 +1,7 @@ +use axum_resp_result::resp_try; use bakery_logic::{impletements::BakeryLogic, view::MansionResp}; use checker::CheckExtract; use persistence::mongodb::MongoDatabaseOperate; -use resp_result::resp_try; use tencent_cloud_server::cloud_manager::TencentCloudManager; use tracing::instrument; diff --git a/src/serves/backend/bakery_mansion/mod.rs b/src/serves/backend/bakery_mansion/mod.rs index 0dca3ea15..8ad2c4292 100644 --- a/src/serves/backend/bakery_mansion/mod.rs +++ b/src/serves/backend/bakery_mansion/mod.rs @@ -1,4 +1,4 @@ -use resp_result::RespResult; +use axum_resp_result::RespResult; pub mod controllers; pub(crate) mod error; diff --git a/src/serves/backend/ceobe_cookie/newest/controllers.rs b/src/serves/backend/ceobe_cookie/newest/controllers.rs index 00153ef60..e483c260a 100644 --- a/src/serves/backend/ceobe_cookie/newest/controllers.rs +++ b/src/serves/backend/ceobe_cookie/newest/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::resp_try; use ceobe_cookie_logic::impletements::CeobeCookieLogic; use ceobe_qiniu_upload::QiniuManager; use persistence::redis::RedisConnect; use qq_channel_warning::QqChannelGrpcService; -use resp_result::resp_try; use tracing::instrument; use super::error::CookieNewestRResult; diff --git a/src/serves/backend/ceobe_cookie/newest/error.rs b/src/serves/backend/ceobe_cookie/newest/error.rs index 3143eec41..638c0c573 100644 --- a/src/serves/backend/ceobe_cookie/newest/error.rs +++ b/src/serves/backend/ceobe_cookie/newest/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/backend/ceobe_operation/announcement/controllers.rs b/src/serves/backend/ceobe_operation/announcement/controllers.rs index d42536ee0..2a7ebe22a 100644 --- a/src/serves/backend/ceobe_operation/announcement/controllers.rs +++ b/src/serves/backend/ceobe_operation/announcement/controllers.rs @@ -1,3 +1,4 @@ +use axum_resp_result::resp_try; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::AnnouncementResp, }; @@ -8,7 +9,6 @@ use checker::{ use persistence::{ ceobe_operate::models::announcement, mysql::SqlDatabaseOperate, }; -use resp_result::resp_try; use tencent_cloud_server::cloud_manager::TencentCloudManager; use tracing::instrument; diff --git a/src/serves/backend/ceobe_operation/announcement/error.rs b/src/serves/backend/ceobe_operation/announcement/error.rs index cc744c503..af004ccc3 100644 --- a/src/serves/backend/ceobe_operation/announcement/error.rs +++ b/src/serves/backend/ceobe_operation/announcement/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use persistence::ceobe_operate::announcement; -use resp_result::RespResult; use crate::{error_generate, utils::user_authorize::error::AuthError}; diff --git a/src/serves/backend/ceobe_operation/app_version/controllers.rs b/src/serves/backend/ceobe_operation/app_version/controllers.rs index b07af82cb..3cd9aedca 100644 --- a/src/serves/backend/ceobe_operation/app_version/controllers.rs +++ b/src/serves/backend/ceobe_operation/app_version/controllers.rs @@ -1,9 +1,11 @@ +use axum_resp_result::resp_try; use checker::{CheckExtract, JsonCheckExtract}; use persistence::{ ceobe_operate::{models::app_version, ToCeobe, ToCeobeOperation}, + mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate, + operate::operate_trait::OperateTrait, }; -use resp_result::resp_try; use tracing::instrument; use super::error::{AppRespResult, CeobeOperationAppVersionError}; @@ -14,17 +16,24 @@ type CreateAppVersionCheck = impl CeobeOpVersion { // 新增一个app版本 - #[instrument(ret, skip(db))] + #[instrument(ret, skip(db, mongo))] pub async fn create_app_version( - db: SqlDatabaseOperate, CheckExtract(version): CreateAppVersionCheck, + db: SqlDatabaseOperate, mongo: MongoDatabaseOperate, + CheckExtract(version): CreateAppVersionCheck, ) -> AppRespResult<()> { resp_try(async { db.ceobe() .operation() .app_version() - .create_one(version) + .create_one(version.clone()) + .await?; + mongo + .ceobe() + .operation() + .release_version() + .create() + .one(version) .await?; - Ok(()) }) .await diff --git a/src/serves/backend/ceobe_operation/app_version/error.rs b/src/serves/backend/ceobe_operation/app_version/error.rs index c09c8241a..31a47f40b 100644 --- a/src/serves/backend/ceobe_operation/app_version/error.rs +++ b/src/serves/backend/ceobe_operation/app_version/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::JsonRejection; -use persistence::ceobe_operate::app_version; -use resp_result::RespResult; +use axum_resp_result::RespResult; +use persistence::ceobe_operate::{app_version, release_version}; use crate::error_generate; @@ -10,6 +10,7 @@ error_generate! { Json = JsonRejection Check = app_version::CheckError DbOperate = app_version::OperateError + ReleaseDbError = release_version::Error } pub(super) type AppRespResult = diff --git a/src/serves/backend/ceobe_operation/desktop_version/controllers.rs b/src/serves/backend/ceobe_operation/desktop_version/controllers.rs index 4e222d146..cddabc573 100644 --- a/src/serves/backend/ceobe_operation/desktop_version/controllers.rs +++ b/src/serves/backend/ceobe_operation/desktop_version/controllers.rs @@ -1,9 +1,11 @@ +use axum_resp_result::resp_try; use checker::{CheckExtract, JsonCheckExtract}; use persistence::{ ceobe_operate::{models::desktop_version, ToCeobe, ToCeobeOperation}, + mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate, + operate::operate_trait::OperateTrait, }; -use resp_result::resp_try; use tracing::instrument; use super::error::{CeobeOperationDesktopVersionError, DesktopRespResult}; @@ -16,18 +18,24 @@ type CreateDesktopVersionCheck = JsonCheckExtract< impl CeobeOpVersion { // 新增一个桌面端版本 - #[instrument(ret, skip(db))] + #[instrument(ret, skip(db, mongo))] pub async fn create_desktop_version( - db: SqlDatabaseOperate, + db: SqlDatabaseOperate, mongo: MongoDatabaseOperate, CheckExtract(version): CreateDesktopVersionCheck, ) -> DesktopRespResult<()> { resp_try(async { db.ceobe() .operation() .desktop_version() - .create_one(version) + .create_one(version.clone()) + .await?; + mongo + .ceobe() + .operation() + .release_version() + .create() + .one(version) .await?; - Ok(()) }) .await diff --git a/src/serves/backend/ceobe_operation/desktop_version/error.rs b/src/serves/backend/ceobe_operation/desktop_version/error.rs index 1a1c0f609..29b6f56c0 100644 --- a/src/serves/backend/ceobe_operation/desktop_version/error.rs +++ b/src/serves/backend/ceobe_operation/desktop_version/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::JsonRejection; -use persistence::ceobe_operate::desktop_version; -use resp_result::RespResult; +use axum_resp_result::RespResult; +use persistence::ceobe_operate::{desktop_version, release_version}; use crate::error_generate; @@ -10,6 +10,7 @@ error_generate! { Json = JsonRejection Check = desktop_version::CheckError DbOperate = desktop_version::OperateError + ReleaseDbOperate = release_version::Error } pub(super) type DesktopRespResult = diff --git a/src/serves/backend/ceobe_operation/plugin_version/controllers.rs b/src/serves/backend/ceobe_operation/plugin_version/controllers.rs index 96f29509e..e151ffc50 100644 --- a/src/serves/backend/ceobe_operation/plugin_version/controllers.rs +++ b/src/serves/backend/ceobe_operation/plugin_version/controllers.rs @@ -1,9 +1,10 @@ +use axum_resp_result::resp_try; use checker::{CheckExtract, JsonCheckExtract}; use persistence::{ ceobe_operate::{plugin_version::Checker, ToCeobe, ToCeobeOperation}, mongodb::MongoDatabaseOperate, + operate::operate_trait::OperateTrait, }; -use resp_result::resp_try; use tracing::instrument; use super::error::{CeobeOperationPluginVersionError, PluginRespResult}; @@ -22,7 +23,13 @@ impl CeobeOpVersion { db.ceobe() .operation() .plugin_version() - .update_new(version) + .update_new(version.clone()) + .await?; + db.ceobe() + .operation() + .release_version() + .create() + .one(version) .await?; Ok(()) diff --git a/src/serves/backend/ceobe_operation/plugin_version/error.rs b/src/serves/backend/ceobe_operation/plugin_version/error.rs index 2384d63cc..9f786b8e4 100644 --- a/src/serves/backend/ceobe_operation/plugin_version/error.rs +++ b/src/serves/backend/ceobe_operation/plugin_version/error.rs @@ -1,6 +1,9 @@ use axum::extract::rejection::JsonRejection; -use persistence::ceobe_operate::plugin_version::{CheckError, OperateError}; -use resp_result::RespResult; +use axum_resp_result::RespResult; +use persistence::ceobe_operate::{ + plugin_version::{CheckError, OperateError}, + release_version, +}; use crate::error_generate; @@ -10,6 +13,7 @@ error_generate! { Json = JsonRejection Check = CheckError DbOperate = OperateError + ReleaseDbOperate = release_version::Error } pub(super) type PluginRespResult = diff --git a/src/serves/backend/ceobe_operation/resource/controller.rs b/src/serves/backend/ceobe_operation/resource/controller.rs index 821a65e57..eac73977f 100644 --- a/src/serves/backend/ceobe_operation/resource/controller.rs +++ b/src/serves/backend/ceobe_operation/resource/controller.rs @@ -1,3 +1,4 @@ +use axum_resp_result::{resp_try, rtry, RespResult}; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::Resource, }; @@ -5,7 +6,6 @@ use checker::{CheckExtract, JsonCheckExtract}; use persistence::{ ceobe_operate::models::resource, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, rtry, RespResult}; use tencent_cloud_server::cloud_manager::TencentCloudManager; use tracing::instrument; diff --git a/src/serves/backend/ceobe_operation/resource/error.rs b/src/serves/backend/ceobe_operation/resource/error.rs index c27951cb5..e3fd5e15c 100644 --- a/src/serves/backend/ceobe_operation/resource/error.rs +++ b/src/serves/backend/ceobe_operation/resource/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::JsonRejection; +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use persistence::ceobe_operate::resource::CheckError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/backend/ceobe_operation/tool_link/controllers.rs b/src/serves/backend/ceobe_operation/tool_link/controllers.rs index 1a7b7b00b..892e82c8c 100644 --- a/src/serves/backend/ceobe_operation/tool_link/controllers.rs +++ b/src/serves/backend/ceobe_operation/tool_link/controllers.rs @@ -2,6 +2,7 @@ use axum::{ extract::{multipart::MultipartRejection, Multipart, Query}, Json, }; +use axum_resp_result::{resp_try, MapReject}; use ceobe_cookie_logic::view::AvatarId; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, @@ -18,7 +19,6 @@ use persistence::{ mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate, }; use qiniu_cdn_upload::UploadWrap; -use resp_result::{resp_try, MapReject}; use tencent_cloud_server::cloud_manager::TencentCloudManager; use tracing::instrument; @@ -96,7 +96,7 @@ impl CeobeOpToolLink { pub async fn upload_avatar( qiniu: QiniuManager, multipart: Result, ) -> OperateToolLinkRResult { - resp_result::resp_try(async move { + resp_try(async move { let mut multipart = multipart?; let field = multipart.next_field().await?.ok_or(FieldNotExist)?; diff --git a/src/serves/backend/ceobe_operation/tool_link/error.rs b/src/serves/backend/ceobe_operation/tool_link/error.rs index b3eb9566d..1c84cf8b5 100644 --- a/src/serves/backend/ceobe_operation/tool_link/error.rs +++ b/src/serves/backend/ceobe_operation/tool_link/error.rs @@ -2,6 +2,7 @@ use axum::extract::{ multipart::{MultipartError, MultipartRejection}, rejection::{JsonRejection, QueryRejection}, }; +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use ceobe_qiniu_upload::Error as QiniuError; use checker::{ @@ -15,7 +16,6 @@ use persistence::ceobe_operate::{ }, tool_link_mongodb::OperateError, }; -use resp_result::RespResult; use status_err::{ErrPrefix, StatusErr}; use crate::error_generate; diff --git a/src/serves/backend/ceobe_operation/video/controllers.rs b/src/serves/backend/ceobe_operation/video/controllers.rs index aec548ac6..13f588ec7 100644 --- a/src/serves/backend/ceobe_operation/video/controllers.rs +++ b/src/serves/backend/ceobe_operation/video/controllers.rs @@ -1,3 +1,4 @@ +use axum_resp_result::{resp_try, rtry, RespResult}; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::VideoItem, }; @@ -10,7 +11,6 @@ use persistence::{ mysql::SqlDatabaseOperate, }; use request_clients::bili_client::QueryBiliVideo; -use resp_result::{resp_try, rtry, RespResult}; use tencent_cloud_server::cloud_manager::TencentCloudManager; use tracing::instrument; diff --git a/src/serves/backend/ceobe_operation/video/error.rs b/src/serves/backend/ceobe_operation/video/error.rs index dbf17dfdf..1260c0137 100644 --- a/src/serves/backend/ceobe_operation/video/error.rs +++ b/src/serves/backend/ceobe_operation/video/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use persistence::ceobe_operate::video; -use resp_result::RespResult; use crate::{error_generate, utils::user_authorize::error::AuthError}; diff --git a/src/serves/backend/fetcher/datasource_configs/controllers.rs b/src/serves/backend/fetcher/datasource_configs/controllers.rs index d39c8dd41..d2afe78cc 100644 --- a/src/serves/backend/fetcher/datasource_configs/controllers.rs +++ b/src/serves/backend/fetcher/datasource_configs/controllers.rs @@ -2,6 +2,7 @@ use axum::{ extract::{multipart::MultipartRejection, Multipart, Query}, Json, }; +use axum_resp_result::{resp_try, rtry, MapReject}; use ceobe_qiniu_upload::QiniuManager; use checker::CheckExtract; use fetcher_logic::{ @@ -23,7 +24,6 @@ use persistence::{ }; use qiniu_cdn_upload::UploadWrap; use qq_channel_warning::QqChannelGrpcService; -use resp_result::{resp_try, rtry, MapReject}; use scheduler_notifier::SchedulerNotifier; use tracing::instrument; @@ -180,7 +180,7 @@ impl FetcherConfigControllers { pub async fn upload_avatar( qiniu: QiniuManager, multipart: Result, ) -> DatasourceConfigRResult { - resp_result::resp_try(async move { + axum_resp_result::resp_try(async move { let mut multipart = multipart?; let field = multipart.next_field().await?.ok_or(FieldNotExist)?; diff --git a/src/serves/backend/fetcher/datasource_configs/error.rs b/src/serves/backend/fetcher/datasource_configs/error.rs index 4100bdc55..96064a090 100644 --- a/src/serves/backend/fetcher/datasource_configs/error.rs +++ b/src/serves/backend/fetcher/datasource_configs/error.rs @@ -2,6 +2,7 @@ use axum::extract::{ multipart::{MultipartError, MultipartRejection}, rejection::{JsonRejection, QueryRejection}, }; +use axum_resp_result::RespResult; use ceobe_qiniu_upload::Error as QiniuError; use checker::prefabs::num_check::NonZeroUnsignedError; use fetcher_logic::error::LogicError; @@ -10,7 +11,6 @@ use persistence::fetcher::{ models::datasource_config::checkers::CheckError, platform_config::OperateError as PlatformOperateError, }; -use resp_result::RespResult; use status_err::{ErrPrefix, StatusErr}; use crate::error_generate; diff --git a/src/serves/backend/fetcher/fetcher_configs/controllers.rs b/src/serves/backend/fetcher/fetcher_configs/controllers.rs index ceb47f667..a4d3a6733 100644 --- a/src/serves/backend/fetcher/fetcher_configs/controllers.rs +++ b/src/serves/backend/fetcher/fetcher_configs/controllers.rs @@ -1,10 +1,10 @@ use axum::{extract::Query, Json}; +use axum_resp_result::{resp_try, rtry, MapReject}; use fetcher_logic::{ implements::FetcherConfigLogic, view::{BackEndFetcherConfig, MaxLiveNumberResp, PlatformFilterReq}, }; use persistence::{mysql::SqlDatabaseOperate, redis::RedisConnect}; -use resp_result::{resp_try, rtry, MapReject}; use scheduler_notifier::SchedulerNotifier; use tracing::instrument; diff --git a/src/serves/backend/fetcher/fetcher_configs/error.rs b/src/serves/backend/fetcher/fetcher_configs/error.rs index 2db82bb64..cf32710d7 100644 --- a/src/serves/backend/fetcher/fetcher_configs/error.rs +++ b/src/serves/backend/fetcher/fetcher_configs/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use fetcher_logic::error::LogicError; use persistence::fetcher::config::OperateError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/backend/fetcher/global_configs/controllers.rs b/src/serves/backend/fetcher/global_configs/controllers.rs index dfb31bacd..8d71aac0e 100644 --- a/src/serves/backend/fetcher/global_configs/controllers.rs +++ b/src/serves/backend/fetcher/global_configs/controllers.rs @@ -1,7 +1,7 @@ use axum::Json; +use axum_resp_result::{rtry, MapReject, RespResult}; use fetcher_logic::implements::FetcherConfigLogic; use persistence::mysql::SqlDatabaseOperate; -use resp_result::{rtry, MapReject, RespResult}; use serde_json::{Map, Value}; use tracing::instrument; diff --git a/src/serves/backend/fetcher/global_configs/error.rs b/src/serves/backend/fetcher/global_configs/error.rs index 486bbf5c2..f50c51b64 100644 --- a/src/serves/backend/fetcher/global_configs/error.rs +++ b/src/serves/backend/fetcher/global_configs/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::JsonRejection; +use axum_resp_result::RespResult; use fetcher_logic::error::LogicError; use persistence::fetcher::models::global_config::checkers::CheckError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/backend/fetcher/platform_configs/controllers.rs b/src/serves/backend/fetcher/platform_configs/controllers.rs index 22ccae85e..27bec3f1c 100644 --- a/src/serves/backend/fetcher/platform_configs/controllers.rs +++ b/src/serves/backend/fetcher/platform_configs/controllers.rs @@ -1,4 +1,5 @@ use axum::Json; +use axum_resp_result::{resp_try, rtry, MapReject}; use checker::CheckExtract; use fetcher_logic::{implements::FetcherConfigLogic, view::OneIdReq}; use futures::future; @@ -13,7 +14,6 @@ use persistence::{ }, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, rtry, MapReject}; use tracing::instrument; use super::{ diff --git a/src/serves/backend/fetcher/platform_configs/error.rs b/src/serves/backend/fetcher/platform_configs/error.rs index e5f6d42ef..a9c1244bf 100644 --- a/src/serves/backend/fetcher/platform_configs/error.rs +++ b/src/serves/backend/fetcher/platform_configs/error.rs @@ -1,10 +1,10 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use checker::prefabs::num_check::NonZeroUnsignedError; use fetcher_logic::error::LogicError; use persistence::fetcher::{ models::platform_config, platform_config::OperateError, }; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/backend/user_auth/controllers.rs b/src/serves/backend/user_auth/controllers.rs index 09d2ea5a5..9f8c069ff 100644 --- a/src/serves/backend/user_auth/controllers.rs +++ b/src/serves/backend/user_auth/controllers.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use axum::{extract::Query, Json}; +use axum_resp_result::{resp_try, rtry, MapReject}; use checker::CheckExtract; use crypto_str::Encoder; use futures::{future, TryFutureExt}; @@ -11,7 +12,6 @@ use persistence::{ mysql::SqlDatabaseOperate, }; use rand::{distributions::Alphanumeric, thread_rng, Rng}; -use resp_result::{resp_try, rtry, MapReject}; use tracing::{debug, instrument}; use super::{ diff --git a/src/serves/backend/user_auth/mod.rs b/src/serves/backend/user_auth/mod.rs index bc9fa6c36..83dbd9999 100644 --- a/src/serves/backend/user_auth/mod.rs +++ b/src/serves/backend/user_auth/mod.rs @@ -1,7 +1,7 @@ +use axum_resp_result::RespResult; use checker::{JsonCheckExtract, QueryCheckExtract}; use page_size::request::PageSizeChecker; use persistence::admin::models::username::Checker; -use resp_result::RespResult; use self::error::AdminUserError; diff --git a/src/serves/cdn/bakery_mansion/controllers.rs b/src/serves/cdn/bakery_mansion/controllers.rs index 49a14ff90..2b6b827b0 100644 --- a/src/serves/cdn/bakery_mansion/controllers.rs +++ b/src/serves/cdn/bakery_mansion/controllers.rs @@ -1,10 +1,10 @@ +use axum_resp_result::resp_try; use bakery_logic::{ impletements::BakeryLogic, view::{MansionRecentPredictResp, MansionWithTimeResp}, }; use checker::CheckExtract; use persistence::mongodb::MongoDatabaseOperate; -use resp_result::resp_try; use tracing::instrument; use super::error::{MansionRResult, MidCheckerPretreatment}; diff --git a/src/serves/cdn/bakery_mansion/error.rs b/src/serves/cdn/bakery_mansion/error.rs index 762aebc31..ba96258f4 100644 --- a/src/serves/cdn/bakery_mansion/error.rs +++ b/src/serves/cdn/bakery_mansion/error.rs @@ -1,4 +1,5 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use bakery_logic::error::LogicError; use checker::QueryCheckExtract; use persistence::bakery::{ @@ -7,7 +8,6 @@ use persistence::bakery::{ checkers::CheckError, preludes::id_checker::MidChecker, }, }; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/cookie/main_list/controllers.rs b/src/serves/cdn/ceobe/cookie/main_list/controllers.rs index 835b30913..aceb9989d 100644 --- a/src/serves/cdn/ceobe/cookie/main_list/controllers.rs +++ b/src/serves/cdn/ceobe/cookie/main_list/controllers.rs @@ -1,4 +1,5 @@ use axum::extract::Query; +use axum_resp_result::{rtry, MapReject}; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::{CookieListReq, CookieListResp}, @@ -7,7 +8,6 @@ use persistence::{ mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate, redis::RedisConnect, }; -use resp_result::{rtry, MapReject}; use tracing::instrument; use super::error::{CeobeCookieMainListError, CeobeCookieRResult}; diff --git a/src/serves/cdn/ceobe/cookie/main_list/error.rs b/src/serves/cdn/ceobe/cookie/main_list/error.rs index bb18894cd..f1c5dffb1 100644 --- a/src/serves/cdn/ceobe/cookie/main_list/error.rs +++ b/src/serves/cdn/ceobe/cookie/main_list/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/cookie/temp_list/controllers.rs b/src/serves/cdn/ceobe/cookie/temp_list/controllers.rs index a0a1966a9..1a497278e 100644 --- a/src/serves/cdn/ceobe/cookie/temp_list/controllers.rs +++ b/src/serves/cdn/ceobe/cookie/temp_list/controllers.rs @@ -1,10 +1,10 @@ use axum::extract::Query; +use axum_resp_result::{rtry, MapReject}; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::{CookieListReq, CookieTempListResp}, }; use persistence::{mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate}; -use resp_result::{rtry, MapReject}; use tracing::instrument; use super::error::{CeobeCookieRResult, CeobeCookieTempListError}; diff --git a/src/serves/cdn/ceobe/cookie/temp_list/error.rs b/src/serves/cdn/ceobe/cookie/temp_list/error.rs index 3ec6812b6..fb1a767f5 100644 --- a/src/serves/cdn/ceobe/cookie/temp_list/error.rs +++ b/src/serves/cdn/ceobe/cookie/temp_list/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; use persistence::ceobe_cookie::temp_list::OperateError as TempListOperateError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/operation/announcement/controllers.rs b/src/serves/cdn/ceobe/operation/announcement/controllers.rs index c15d77beb..44d805d86 100644 --- a/src/serves/cdn/ceobe/operation/announcement/controllers.rs +++ b/src/serves/cdn/ceobe/operation/announcement/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::resp_try; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::AnnouncementResp, }; use persistence::mysql::SqlDatabaseOperate; -use resp_result::resp_try; use tracing::instrument; use super::error::AnnouncementRespResult; diff --git a/src/serves/cdn/ceobe/operation/announcement/error.rs b/src/serves/cdn/ceobe/operation/announcement/error.rs index 6c7f0ee50..8a3a09da6 100644 --- a/src/serves/cdn/ceobe/operation/announcement/error.rs +++ b/src/serves/cdn/ceobe/operation/announcement/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/operation/resource/controllers.rs b/src/serves/cdn/ceobe/operation/resource/controllers.rs index b5e44dd70..9f7d6bf59 100644 --- a/src/serves/cdn/ceobe/operation/resource/controllers.rs +++ b/src/serves/cdn/ceobe/operation/resource/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::{rtry, RespResult}; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::Resource, }; use persistence::mysql::SqlDatabaseOperate; -use resp_result::{rtry, RespResult}; use tracing::instrument; use super::error::ResourceRespResult; diff --git a/src/serves/cdn/ceobe/operation/resource/error.rs b/src/serves/cdn/ceobe/operation/resource/error.rs index 2c32cc6f6..858b875b0 100644 --- a/src/serves/cdn/ceobe/operation/resource/error.rs +++ b/src/serves/cdn/ceobe/operation/resource/error.rs @@ -1,6 +1,6 @@ +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use persistence::ceobe_operate::resource; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/operation/tool_link/controllers.rs b/src/serves/cdn/ceobe/operation/tool_link/controllers.rs index 6b32e5887..0978f951b 100644 --- a/src/serves/cdn/ceobe/operation/tool_link/controllers.rs +++ b/src/serves/cdn/ceobe/operation/tool_link/controllers.rs @@ -1,9 +1,9 @@ +use axum_resp_result::resp_try; use ceobe_operation_logic::impletements::CeobeOperateLogic; use persistence::{ ceobe_operate::tool_link_mongodb::models::ToolLink, mongodb::MongoDatabaseOperate, }; -use resp_result::resp_try; use tracing::instrument; use super::error::CeobeToolLinkRResult; diff --git a/src/serves/cdn/ceobe/operation/tool_link/error.rs b/src/serves/cdn/ceobe/operation/tool_link/error.rs index e727fa9fc..858f868c1 100644 --- a/src/serves/cdn/ceobe/operation/tool_link/error.rs +++ b/src/serves/cdn/ceobe/operation/tool_link/error.rs @@ -1,8 +1,8 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; use checker::prefabs::num_check::NonZeroUnsignedError; use persistence::ceobe_operate::tool_link_mongodb::OperateError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/cdn/ceobe/operation/video/controllers.rs b/src/serves/cdn/ceobe/operation/video/controllers.rs index 1427627a5..07f99433b 100644 --- a/src/serves/cdn/ceobe/operation/video/controllers.rs +++ b/src/serves/cdn/ceobe/operation/video/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::resp_try; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::VideoItem, }; use persistence::mysql::SqlDatabaseOperate; -use resp_result::resp_try; use tracing::instrument; use super::error::VideoRespResult; diff --git a/src/serves/cdn/ceobe/operation/video/error.rs b/src/serves/cdn/ceobe/operation/video/error.rs index 699bc69aa..9a4815e83 100644 --- a/src/serves/cdn/ceobe/operation/video/error.rs +++ b/src/serves/cdn/ceobe/operation/video/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/bakery_mansion/controllers.rs b/src/serves/frontend/bakery_mansion/controllers.rs index ebdc82174..4daa58f56 100644 --- a/src/serves/frontend/bakery_mansion/controllers.rs +++ b/src/serves/frontend/bakery_mansion/controllers.rs @@ -1,3 +1,4 @@ +use axum_resp_result::{resp_try, FlagWrap}; use bakery_logic::{ impletements::BakeryLogic, view::MansionRecentPredictResp, }; @@ -7,7 +8,6 @@ use persistence::{ bakery::{mansion::ToMansion, ToBakery}, mongodb::MongoDatabaseOperate, }; -use resp_result::{resp_try, FlagWrap}; use tracing::instrument; use super::{ diff --git a/src/serves/frontend/bakery_mansion/mod.rs b/src/serves/frontend/bakery_mansion/mod.rs index 8a5ac3908..0b7a2e295 100644 --- a/src/serves/frontend/bakery_mansion/mod.rs +++ b/src/serves/frontend/bakery_mansion/mod.rs @@ -1,4 +1,4 @@ -use resp_result::{FlagRespResult, RespResult}; +use axum_resp_result::{FlagRespResult, RespResult}; pub mod controllers; pub(crate) mod error; diff --git a/src/serves/frontend/ceobe/cookie/basic_info/controllers.rs b/src/serves/frontend/ceobe/cookie/basic_info/controllers.rs index 58cd8a992..23a599d2c 100644 --- a/src/serves/frontend/ceobe/cookie/basic_info/controllers.rs +++ b/src/serves/frontend/ceobe/cookie/basic_info/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::rtry; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::CookieNumberResp, }; use persistence::mongodb::MongoDatabaseOperate; -use resp_result::rtry; use tracing::instrument; use super::error::CeobeCookieRResult; diff --git a/src/serves/frontend/ceobe/cookie/basic_info/error.rs b/src/serves/frontend/ceobe/cookie/basic_info/error.rs index a165a3421..7f15c6052 100644 --- a/src/serves/frontend/ceobe/cookie/basic_info/error.rs +++ b/src/serves/frontend/ceobe/cookie/basic_info/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/cookie/search/controllers.rs b/src/serves/frontend/ceobe/cookie/search/controllers.rs index 938156c88..dd844b9a7 100644 --- a/src/serves/frontend/ceobe/cookie/search/controllers.rs +++ b/src/serves/frontend/ceobe/cookie/search/controllers.rs @@ -1,10 +1,10 @@ use axum::extract::Query; +use axum_resp_result::{rtry, MapReject}; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::{CookieListResp, SearchListReq}, }; use persistence::{mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate}; -use resp_result::{rtry, MapReject}; use tracing::instrument; use super::error::{CeobeCookieRResult, CeobeCookieSearchError}; diff --git a/src/serves/frontend/ceobe/cookie/search/error.rs b/src/serves/frontend/ceobe/cookie/search/error.rs index 3f4d52b7f..7ec414251 100644 --- a/src/serves/frontend/ceobe/cookie/search/error.rs +++ b/src/serves/frontend/ceobe/cookie/search/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/cookie/terra_comic/controllers.rs b/src/serves/frontend/ceobe/cookie/terra_comic/controllers.rs index e571d5f5a..fe9517eb3 100644 --- a/src/serves/frontend/ceobe/cookie/terra_comic/controllers.rs +++ b/src/serves/frontend/ceobe/cookie/terra_comic/controllers.rs @@ -1,4 +1,5 @@ use axum::extract::Query; +use axum_resp_result::{rtry, MapReject}; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::{TerraCidReq, TerraComicListResp, TerraEntryResp}, @@ -7,7 +8,6 @@ use persistence::{ ceobe_cookie::models::analyze::models::TerraComicEpisodeInfo, mongodb::MongoDatabaseOperate, }; -use resp_result::{rtry, MapReject}; use tracing::instrument; use super::error::{CeobeCookieRResult, CeobeCookieTerraComicError}; diff --git a/src/serves/frontend/ceobe/cookie/terra_comic/error.rs b/src/serves/frontend/ceobe/cookie/terra_comic/error.rs index dd471ed72..9aa2057ff 100644 --- a/src/serves/frontend/ceobe/cookie/terra_comic/error.rs +++ b/src/serves/frontend/ceobe/cookie/terra_comic/error.rs @@ -1,7 +1,7 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; use persistence::ceobe_cookie::terra_comic::OperateError as TerraComicOperateError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/operation/announcement/controllers.rs b/src/serves/frontend/ceobe/operation/announcement/controllers.rs index f029ed2eb..4ab051ee6 100644 --- a/src/serves/frontend/ceobe/operation/announcement/controllers.rs +++ b/src/serves/frontend/ceobe/operation/announcement/controllers.rs @@ -1,9 +1,9 @@ +use axum_resp_result::{resp_try, FlagWrap}; use modify_cache::CacheMode; use persistence::{ ceobe_operate::{ToCeobe, ToCeobeOperation}, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, FlagWrap}; use tracing::instrument; use super::{ diff --git a/src/serves/frontend/ceobe/operation/announcement/error.rs b/src/serves/frontend/ceobe/operation/announcement/error.rs index ed9a3daad..89e84aafa 100644 --- a/src/serves/frontend/ceobe/operation/announcement/error.rs +++ b/src/serves/frontend/ceobe/operation/announcement/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::FlagRespResult; use persistence::ceobe_operate::announcement; -use resp_result::FlagRespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/operation/resource/controllers.rs b/src/serves/frontend/ceobe/operation/resource/controllers.rs index 18e7f3d9b..4ea3c544f 100644 --- a/src/serves/frontend/ceobe/operation/resource/controllers.rs +++ b/src/serves/frontend/ceobe/operation/resource/controllers.rs @@ -1,10 +1,10 @@ use std::time::Duration; +use axum_resp_result::{resp_try, FlagWrap}; use persistence::{ ceobe_operate::{ToCeobe, ToCeobeOperation}, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, FlagWrap}; use tracing::instrument; use super::{error::FlagResourceRespResult, view::Resource}; diff --git a/src/serves/frontend/ceobe/operation/resource/error.rs b/src/serves/frontend/ceobe/operation/resource/error.rs index 0dab55a21..c214c4096 100644 --- a/src/serves/frontend/ceobe/operation/resource/error.rs +++ b/src/serves/frontend/ceobe/operation/resource/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::FlagRespResult; use persistence::ceobe_operate::resource; -use resp_result::FlagRespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/operation/tool_link/controllers.rs b/src/serves/frontend/ceobe/operation/tool_link/controllers.rs index 419798c94..9be6a77c2 100644 --- a/src/serves/frontend/ceobe/operation/tool_link/controllers.rs +++ b/src/serves/frontend/ceobe/operation/tool_link/controllers.rs @@ -1,8 +1,8 @@ +use axum_resp_result::resp_try; use ceobe_operation_logic::{ impletements::CeobeOperateLogic, view::ToolLinkResp, }; use persistence::mysql::SqlDatabaseOperate; -use resp_result::resp_try; use tracing::instrument; use super::error::OperateToolLinkRResult; diff --git a/src/serves/frontend/ceobe/operation/tool_link/error.rs b/src/serves/frontend/ceobe/operation/tool_link/error.rs index 90416aded..84ade77de 100644 --- a/src/serves/frontend/ceobe/operation/tool_link/error.rs +++ b/src/serves/frontend/ceobe/operation/tool_link/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::RespResult; use ceobe_operation_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/operation/version/controllers.rs b/src/serves/frontend/ceobe/operation/version/controllers.rs index 058f83856..6ca1c83a2 100644 --- a/src/serves/frontend/ceobe/operation/version/controllers.rs +++ b/src/serves/frontend/ceobe/operation/version/controllers.rs @@ -1,12 +1,12 @@ use std::time::Duration; +use axum_resp_result::{resp_try, FlagWrap}; use checker::CheckExtract; use persistence::{ ceobe_operate::{ToCeobe, ToCeobeOperation}, mongodb::MongoDatabaseOperate, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, FlagWrap}; use tracing::instrument; use super::{ diff --git a/src/serves/frontend/ceobe/operation/version/error.rs b/src/serves/frontend/ceobe/operation/version/error.rs index 2d7a8d73d..32e751dd7 100644 --- a/src/serves/frontend/ceobe/operation/version/error.rs +++ b/src/serves/frontend/ceobe/operation/version/error.rs @@ -1,4 +1,5 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::FlagRespResult; use persistence::{ ceobe_operate, ceobe_operate::{ @@ -6,7 +7,6 @@ use persistence::{ models::{app_version, plugin_version}, }, }; -use resp_result::FlagRespResult; use crate::error_generate; @@ -19,7 +19,7 @@ error_generate! { Query = QueryRejection AppOperate = ceobe_operate::app_version::OperateError DesktopOperate = ceobe_operate::desktop_version::OperateError - MongoDbError = ceobe_operate::plugin_version::OperateError + PluginDbError = ceobe_operate::plugin_version::OperateError ModifyVerify = modify_cache::Error } diff --git a/src/serves/frontend/ceobe/operation/video/controllers.rs b/src/serves/frontend/ceobe/operation/video/controllers.rs index 12282ee19..f518f8795 100644 --- a/src/serves/frontend/ceobe/operation/video/controllers.rs +++ b/src/serves/frontend/ceobe/operation/video/controllers.rs @@ -1,10 +1,10 @@ use std::time::Duration; +use axum_resp_result::{resp_try, FlagWrap}; use persistence::{ ceobe_operate::{ToCeobe, ToCeobeOperation}, mysql::SqlDatabaseOperate, }; -use resp_result::{resp_try, FlagWrap}; use tracing::instrument; use super::{ diff --git a/src/serves/frontend/ceobe/operation/video/error.rs b/src/serves/frontend/ceobe/operation/video/error.rs index ce186f439..ac0dd81b8 100644 --- a/src/serves/frontend/ceobe/operation/video/error.rs +++ b/src/serves/frontend/ceobe/operation/video/error.rs @@ -1,5 +1,5 @@ +use axum_resp_result::FlagRespResult; use persistence::ceobe_operate::video; -use resp_result::FlagRespResult; use crate::error_generate; diff --git a/src/serves/frontend/ceobe/user/controllers.rs b/src/serves/frontend/ceobe/user/controllers.rs index c4bd6fa94..2d7c10c84 100644 --- a/src/serves/frontend/ceobe/user/controllers.rs +++ b/src/serves/frontend/ceobe/user/controllers.rs @@ -1,4 +1,5 @@ use axum::Json; +use axum_resp_result::{rtry, MapReject}; use ceobe_user_logic::{ implements::CeobeUserLogic, view::{DatasourceCombResp, DatasourceConfig, MobIdReq}, @@ -10,7 +11,6 @@ use persistence::{ mysql::SqlDatabaseOperate, redis::RedisConnect, }; -use resp_result::{rtry, MapReject}; use tracing::instrument; use super::error::{CeobeUserError, CeobeUserRResult}; diff --git a/src/serves/frontend/ceobe/user/error.rs b/src/serves/frontend/ceobe/user/error.rs index f94bf4576..4f8a26fc3 100644 --- a/src/serves/frontend/ceobe/user/error.rs +++ b/src/serves/frontend/ceobe/user/error.rs @@ -1,10 +1,10 @@ use axum::extract::rejection::{JsonRejection, QueryRejection}; +use axum_resp_result::RespResult; use ceobe_user_logic::error::LogicError; use persistence::ceobe_user::{ models::check::CheckError as CeobeUserPropertyCheckError, property::OperateError, }; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/config/datasource/controllers.rs b/src/serves/frontend/config/datasource/controllers.rs index da84312a8..8227f5bf2 100644 --- a/src/serves/frontend/config/datasource/controllers.rs +++ b/src/serves/frontend/config/datasource/controllers.rs @@ -1,3 +1,4 @@ +use axum_resp_result::rtry; use persistence::{ fetcher::{ datasource_config::ToDatasource, @@ -6,7 +7,6 @@ use persistence::{ }, mysql::SqlDatabaseOperate, }; -use resp_result::rtry; use tracing::instrument; use crate::{ diff --git a/src/serves/frontend/config/datasource/error.rs b/src/serves/frontend/config/datasource/error.rs index 38d1bdd8c..1caa0bf72 100644 --- a/src/serves/frontend/config/datasource/error.rs +++ b/src/serves/frontend/config/datasource/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::QueryRejection; +use axum_resp_result::RespResult; use persistence::fetcher::datasource_config::OperateError as DatasourceOperateError; -use resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/frontend/config/fetcher/controllers.rs b/src/serves/frontend/config/fetcher/controllers.rs index 5963b1968..00715496a 100644 --- a/src/serves/frontend/config/fetcher/controllers.rs +++ b/src/serves/frontend/config/fetcher/controllers.rs @@ -1,11 +1,11 @@ use axum::extract::{Path, State}; +use axum_resp_result::resp_try; use bitmap_convert::{ base70::BitmapBase70Conv, vec_usize::BitmapVecUsizeConv, }; use bitmaps::Bitmap; use general_request_client::{client::RequestClient, traits::Requester}; use http::{Method, Version}; -use resp_result::resp_try; use scheduler_notifier::SchedulerUrl; use serde_json::{json, Value}; use tap::Tap; diff --git a/src/serves/frontend/config/fetcher/error.rs b/src/serves/frontend/config/fetcher/error.rs index 13f0670b1..4bf58ae77 100644 --- a/src/serves/frontend/config/fetcher/error.rs +++ b/src/serves/frontend/config/fetcher/error.rs @@ -1,4 +1,4 @@ -use resp_result::RespResult; +use axum_resp_result::RespResult; use crate::error_generate; diff --git a/src/serves/inside/analyze/cookie/controllers.rs b/src/serves/inside/analyze/cookie/controllers.rs index dfe0d6460..02435a137 100644 --- a/src/serves/inside/analyze/cookie/controllers.rs +++ b/src/serves/inside/analyze/cookie/controllers.rs @@ -1,4 +1,5 @@ use axum::Json; +use axum_resp_result::{resp_try, MapReject}; use ceobe_cookie_logic::{ impletements::CeobeCookieLogic, view::NewCookieReq, }; @@ -9,7 +10,6 @@ use persistence::{ redis::RedisConnect, }; use qq_channel_warning::QqChannelGrpcService; -use resp_result::{resp_try, MapReject}; use tracing::instrument; use super::error::{AnalyzeCookieError, AnalyzeCookieRResult}; diff --git a/src/serves/inside/analyze/cookie/error.rs b/src/serves/inside/analyze/cookie/error.rs index 916cf5f12..627af80a9 100644 --- a/src/serves/inside/analyze/cookie/error.rs +++ b/src/serves/inside/analyze/cookie/error.rs @@ -1,6 +1,6 @@ use axum::extract::rejection::JsonRejection; +use axum_resp_result::RespResult; use ceobe_cookie_logic::error::LogicError; -use resp_result::RespResult; use crate::error_generate;