From 59bca1f8bfb4a6d4db4ad9cd244d7828995dba22 Mon Sep 17 00:00:00 2001 From: 4t145 Date: Fri, 30 Aug 2024 15:57:10 +0800 Subject: [PATCH] event: use new event center (#832) * new event center * ignore package lock file * remove package-lock --- .gitignore | 3 + Cargo.toml | 5 +- backend/basic/src/process/task_processor.rs | 72 +- backend/middlewares/event/Cargo.toml | 3 + .../event/src/api/event_listener_api.rs | 11 +- .../event/src/api/event_proc_api.rs | 7 +- .../event/src/domain/event_topic.rs | 83 +- .../middlewares/event/src/dto/event_dto.rs | 77 +- backend/middlewares/event/src/event_config.rs | 2 + .../event/src/event_initializer.rs | 148 +- backend/middlewares/event/src/serv.rs | 1 - .../event/src/serv/event_listener_serv.rs | 97 - .../event/src/serv/event_persistent_serv.rs | 106 - .../event/src/serv/event_proc_serv.rs | 221 -- .../event/src/serv/event_topic_serv.rs | 76 +- .../event/test-vue/package-lock.json | 3313 ----------------- backend/middlewares/event/tests/test_event.rs | 9 +- .../event/tests/test_event_inmails.rs | 236 -- .../tests/test_event_multi_node_server.rs | 156 - .../event/tests/test_event_with_event_code.rs | 250 -- .../event/tests/test_event_with_im.rs | 268 -- .../event/tests/test_event_without_mgr.rs | 123 - backend/middlewares/flow/src/event.rs | 24 +- backend/middlewares/flow/src/flow_config.rs | 7 +- .../middlewares/flow/src/flow_initializer.rs | 4 +- .../flow/src/serv/clients/search_client.rs | 20 +- .../flow/src/serv/flow_event_serv.rs | 22 +- .../flow/src/serv/flow_inst_serv.rs | 34 +- .../schedule/src/schedule_config.rs | 4 +- .../src/serv/schedule_job_serv_v2/event.rs | 3 +- .../event/schedule_event.rs | 1 - backend/services/bios-all/Cargo.toml | 2 +- backend/services/bios-all/Dockerfile | 1 + backend/services/bios-all/build.sh | 36 +- backend/services/bios-all/src/initializer.rs | 4 +- backend/spi/spi-conf/Cargo.toml | 6 +- .../spi/spi-conf/src/api/nacos/grpc/proto.rs | 135 +- backend/spi/spi-conf/src/serv/placeholder.rs | 1 + backend/spi/spi-kv/src/event.rs | 24 +- backend/spi/spi-kv/src/kv_initializer.rs | 2 +- backend/spi/spi-log/src/event.rs | 23 +- backend/spi/spi-log/src/log_config.rs | 4 +- backend/spi/spi-log/src/log_initializer.rs | 2 +- backend/spi/spi-search/src/event.rs | 27 +- backend/spi/spi-search/src/search_config.rs | 2 - .../spi/spi-search/src/search_initializer.rs | 2 +- .../src/basic/serv/clients/iam_log_client.rs | 11 +- .../basic/serv/clients/iam_search_client.rs | 17 +- backend/supports/iam/src/iam_config.rs | 9 - frontend/sdks/invoke/Cargo.toml | 2 + .../sdks/invoke/src/clients/event_client.rs | 561 +-- .../sdks/invoke/src/clients/flow_client.rs | 17 +- .../sdks/invoke/src/clients/spi_kv_client.rs | 16 +- .../sdks/invoke/src/clients/spi_log_client.rs | 8 +- .../invoke/src/clients/spi_search_client.rs | 146 +- 55 files changed, 628 insertions(+), 5816 deletions(-) delete mode 100644 backend/middlewares/event/src/serv/event_persistent_serv.rs delete mode 100644 backend/middlewares/event/test-vue/package-lock.json delete mode 100644 backend/middlewares/event/tests/test_event_inmails.rs delete mode 100644 backend/middlewares/event/tests/test_event_multi_node_server.rs delete mode 100644 backend/middlewares/event/tests/test_event_with_event_code.rs delete mode 100644 backend/middlewares/event/tests/test_event_with_im.rs delete mode 100644 backend/middlewares/event/tests/test_event_without_mgr.rs diff --git a/.gitignore b/.gitignore index a935818dd..aa64d9814 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ backend/services/spacegate/devsh/ .uuid backend/services/bios-all/dev.sh + +# front end +package-lock.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index dd801e7f6..2482ebccc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,8 +64,9 @@ strum = { version = "0.26", features = ["derive"] } # tardis # tardis = { version = "0.1.0-rc.16" } # tardis = { path = "../tardis/tardis" } -tardis = { git = "https://github.com/ideal-world/tardis.git", rev = "17fed580" } - +tardis = { git = "https://github.com/ideal-world/tardis.git", rev = "763b987" } +asteroid-mq = { git = "https://github.com/4t145/asteroid-mq.git", rev = "d59c64d" } +# asteroid-mq = { path = "../asteroid/asteroid-mq" } #spacegate # spacegate-shell = { path = "../spacegate/crates/shell", features = [ diff --git a/backend/basic/src/process/task_processor.rs b/backend/basic/src/process/task_processor.rs index 9717c3376..443955545 100644 --- a/backend/basic/src/process/task_processor.rs +++ b/backend/basic/src/process/task_processor.rs @@ -3,7 +3,10 @@ //! 异步任务处理器 use std::{collections::HashMap, future::Future, sync::Arc}; -use bios_sdk_invoke::clients::event_client::{BiosEventCenter, Event, EventCenter, EventExt}; +use bios_sdk_invoke::clients::event_client::{ + asteroid_mq::prelude::{EventAttribute, Subject, TopicCode}, + get_topic, EventAttributeExt, +}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use tardis::{ @@ -21,7 +24,7 @@ lazy_static! { } const TASK_PROCESSOR_DATA_EX_SEC: u64 = 60 * 60 * 24; const TASK_IN_CTX_FLAG: &str = "task_id"; - +const TASK_TOPIC: TopicCode = TopicCode::const_new("task"); /// Set task status event flag /// 设置任务状态事件标识 pub const EVENT_SET_TASK_STATUS_FLAG: &str = "task/set_status"; @@ -102,17 +105,19 @@ impl TaskProcessor { to_avatars: Option>, ) -> TardisResult<()> { Self::set_status(cache_key, task_id, status, cache_client).await?; - if let Some(ec) = BiosEventCenter::public() { - ec.publish( - TaskSetStatusEventReq { - task_id, - data: status, - msg: format!("task status: {}", status), - } - .with_source(from_avatar) - .with_targets(to_avatars), - ) - .await?; + if let Some(topic) = get_topic(&TASK_TOPIC) { + // todo: broadcast event to users + // topic + // .send_event( + // TaskSetStatusEventReq { + // task_id, + // data: status, + // msg: format!("task status: {}", status), + // } + // .json(), + // ) + // .await + // .map_err(mq_error)?; } Ok(()) } @@ -137,9 +142,8 @@ impl TaskProcessor { to_avatars: Option>, ) -> TardisResult<()> { Self::set_process_data(cache_key, task_id, data.clone(), cache_client).await?; - if let Some(ec) = BiosEventCenter::public() { - let msg = format!("set task process: {}", &TardisFuns::json.json_to_string(data.clone())?); - ec.publish(TaskSetProcessDataEventReq { task_id, data, msg }.with_source(from_avatar).with_targets(to_avatars)).await?; + if let Some(topic) = get_topic(&TASK_TOPIC) { + // todo: broadcast event to users } Ok(()) } @@ -214,16 +218,8 @@ impl TaskProcessor { } }); TASK_HANDLE.write().await.insert(task_id, handle); - if let Some(ec) = BiosEventCenter::public() { - ec.publish( - TaskExecuteEventReq { - task_id, - msg: "execute task start".to_owned(), - } - .with_source(from_avatar_clone) - .with_targets(to_avatars_clone), - ) - .await?; + if let Some(topic) = get_topic(&TASK_TOPIC) { + // todo: broadcast event to users } if let Some(ctx) = ctx { if let Some(exist_task_ids) = ctx.get_ext(TASK_IN_CTX_FLAG).await? { @@ -246,16 +242,8 @@ impl TaskProcessor { to_avatars: Option>, ) -> TardisResult { let task_id = TaskProcessor::init_status(cache_key, Some(task_id), cache_client).await?; - if let Some(ec) = BiosEventCenter::public() { - ec.publish( - TaskExecuteEventReq { - task_id, - msg: "execute task start".to_owned(), - } - .with_source(from_avatar) - .with_targets(to_avatars), - ) - .await?; + if let Some(topic) = get_topic(&TASK_TOPIC) { + // todo: broadcast event to users } Ok(task_id) } @@ -322,14 +310,14 @@ struct TaskExecuteEventReq { pub msg: String, } -impl Event for TaskSetStatusEventReq { - const CODE: &'static str = EVENT_SET_TASK_STATUS_FLAG; +impl EventAttribute for TaskSetStatusEventReq { + const SUBJECT: Subject = Subject::const_new(EVENT_SET_TASK_STATUS_FLAG.as_bytes()); } -impl Event for TaskSetProcessDataEventReq { - const CODE: &'static str = EVENT_SET_TASK_PROCESS_DATA_FLAG; +impl EventAttribute for TaskSetProcessDataEventReq { + const SUBJECT: Subject = Subject::const_new(EVENT_SET_TASK_PROCESS_DATA_FLAG.as_bytes()); } -impl Event for TaskExecuteEventReq { - const CODE: &'static str = EVENT_EXECUTE_TASK_FLAG; +impl EventAttribute for TaskExecuteEventReq { + const SUBJECT: Subject = Subject::const_new(EVENT_EXECUTE_TASK_FLAG.as_bytes()); } diff --git a/backend/middlewares/event/Cargo.toml b/backend/middlewares/event/Cargo.toml index 0cedc2ca8..8270a00e2 100644 --- a/backend/middlewares/event/Cargo.toml +++ b/backend/middlewares/event/Cargo.toml @@ -29,6 +29,9 @@ bios-sdk-invoke = { path = "../../../frontend/sdks/invoke", features = [ "spi_log", "event", ], default-features = false } +asteroid-mq = { workspace = true, features = ["cluster-k8s", "json"] } + + [dev-dependencies] tardis = { workspace = true, features = [ "test", diff --git a/backend/middlewares/event/src/api/event_listener_api.rs b/backend/middlewares/event/src/api/event_listener_api.rs index bf8dcaa10..5faccc3fc 100644 --- a/backend/middlewares/event/src/api/event_listener_api.rs +++ b/backend/middlewares/event/src/api/event_listener_api.rs @@ -1,3 +1,4 @@ +use tardis::basic::error::TardisError; use tardis::web::poem_openapi; use tardis::web::poem_openapi::param::{Path, Query}; use tardis::web::poem_openapi::payload::Json; @@ -19,9 +20,8 @@ impl EventListenerApi { /// 注册事件监听器 #[oai(path = "/", method = "post")] async fn register(&self, listener: Json) -> TardisApiResult { - let funs = get_tardis_inst(); - let resp = event_listener_serv::register(listener.0, &funs).await?; - TardisResp::ok(resp) + + TardisResp::err(TardisError::not_implemented("unimplemented", "unimplemented")) } /// Remove event listener @@ -29,8 +29,7 @@ impl EventListenerApi { /// 移除事件监听器 #[oai(path = "/:listener_code", method = "delete")] async fn remove(&self, listener_code: Path, token: Query) -> TardisApiResult { - let funs = get_tardis_inst(); - event_listener_serv::remove(&listener_code.0, &token.0, &funs).await?; - TardisResp::ok(Void {}) + TardisResp::err(TardisError::not_implemented("unimplemented", "unimplemented")) + } } diff --git a/backend/middlewares/event/src/api/event_proc_api.rs b/backend/middlewares/event/src/api/event_proc_api.rs index c2d5bebd4..be7a11781 100644 --- a/backend/middlewares/event/src/api/event_proc_api.rs +++ b/backend/middlewares/event/src/api/event_proc_api.rs @@ -2,8 +2,7 @@ use tardis::web::poem::web::websocket::{BoxWebSocketUpgraded, WebSocket}; use tardis::web::poem_openapi; use tardis::web::poem_openapi::param::{Path, Query}; -use crate::event_constants::get_tardis_inst; -use crate::serv::event_proc_serv; + #[derive(Clone)] pub struct EventProcApi; @@ -17,8 +16,6 @@ impl EventProcApi { /// 处理事件 #[oai(path = "/:listener_code", method = "get")] async fn ws_process(&self, listener_code: Path, token: Query, websocket: WebSocket) -> Result { - let funs = get_tardis_inst(); - let upgraded = event_proc_serv::ws_process(listener_code.0, token.0, websocket, funs).await?; - Ok(upgraded) + Err(tardis::web::poem::Error::from_status(tardis::web::poem::http::StatusCode::NOT_IMPLEMENTED)) } } diff --git a/backend/middlewares/event/src/domain/event_topic.rs b/backend/middlewares/event/src/domain/event_topic.rs index 5bb37aac6..c9bba7c76 100644 --- a/backend/middlewares/event/src/domain/event_topic.rs +++ b/backend/middlewares/event/src/domain/event_topic.rs @@ -1,69 +1,36 @@ -use tardis::basic::dto::TardisContext; -use tardis::db::reldb_client::TardisActiveModel; +use std::num::NonZeroU32; use tardis::db::sea_orm; -use tardis::db::sea_orm::sea_query::{ColumnDef, IndexCreateStatement, Table, TableCreateStatement}; +use tardis::db::sea_orm::prelude::*; use tardis::db::sea_orm::*; -/// Event Topic model -/// -/// 事件主题模型 -#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] -#[sea_orm(table_name = "event_topic")] +use asteroid_mq::prelude::{TopicCode, TopicConfig, TopicOverflowConfig, TopicOverflowPolicy}; +use tardis::{TardisCreateEntity, TardisEmptyBehavior, TardisEmptyRelation}; +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, TardisCreateEntity, TardisEmptyBehavior, TardisEmptyRelation)] +#[sea_orm(table_name = "mq_topic")] pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] + #[sea_orm(primary_key, auto_increment = true)] pub id: String, - /// Whether to save messages - /// - /// 是否保存消息 - pub save_message: bool, - /// Whether a management node is required - /// - /// 是否需要管理节点 - pub need_mgr: bool, - pub queue_size: i32, - /// If need_mgr is false, this field is used when registering - /// - /// 如果 need_mgr 为 false,则在注册时使用该sk - pub use_sk: String, - /// If need_mgr is true, this field is used when registering - /// - /// 如果 need_mgr 为 true,则在注册时使用该sk - pub mgr_sk: String, - + pub blocking: bool, + pub topic_code: String, + pub overflow_policy: String, + pub overflow_size: i32, + #[fill_ctx] pub own_paths: String, } -impl TardisActiveModel for ActiveModel { - fn fill_ctx(&mut self, ctx: &TardisContext, is_insert: bool) { - if is_insert { - self.own_paths = Set(ctx.own_paths.to_string()); - } - } - - fn create_table_statement(db: DbBackend) -> TableCreateStatement { - let mut builder = Table::create(); - builder - .table(Entity.table_ref()) - .if_not_exists() - .col(ColumnDef::new(Column::Id).not_null().string().primary_key()) - .col(ColumnDef::new(Column::SaveMessage).not_null().boolean()) - .col(ColumnDef::new(Column::NeedMgr).not_null().boolean()) - .col(ColumnDef::new(Column::QueueSize).not_null().integer()) - .col(ColumnDef::new(Column::UseSk).not_null().string()) - .col(ColumnDef::new(Column::MgrSk).not_null().string()) - .col(ColumnDef::new(Column::OwnPaths).not_null().string()); - if db == DatabaseBackend::MySql { - builder.engine("InnoDB").character_set("utf8mb4").collate("utf8mb4_0900_as_cs"); +impl Model { + pub fn into_topic_config(self) -> TopicConfig { + TopicConfig { + code: TopicCode::new(self.topic_code), + blocking: self.blocking, + overflow_config: Some(TopicOverflowConfig { + policy: match self.overflow_policy.as_str() { + "RejectNew" => TopicOverflowPolicy::RejectNew, + "DropOld" => TopicOverflowPolicy::DropOld, + _ => TopicOverflowPolicy::default(), + }, + size: NonZeroU32::new(self.overflow_size.clamp(1, i32::MAX) as u32).expect("clamped"), + }), } - builder.to_owned() - } - - fn create_index_statement() -> Vec { - vec![] } } - -impl ActiveModelBehavior for ActiveModel {} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} diff --git a/backend/middlewares/event/src/dto/event_dto.rs b/backend/middlewares/event/src/dto/event_dto.rs index efbe7d0d9..dcfaeeabe 100644 --- a/backend/middlewares/event/src/dto/event_dto.rs +++ b/backend/middlewares/event/src/dto/event_dto.rs @@ -1,36 +1,77 @@ +use std::num::NonZeroU32; + +use asteroid_mq::prelude::{TopicCode, TopicConfig, TopicOverflowConfig, TopicOverflowPolicy}; use bios_basic::rbum::dto::rbum_filer_dto::{RbumBasicFilterReq, RbumItemFilterFetcher}; use serde::{Deserialize, Serialize}; use tardis::{ basic::field::TrimString, - db::sea_orm::{self}, + db::sea_orm::{self, FromQueryResult}, serde_json::Value, web::poem_openapi, }; -#[derive(poem_openapi::Object, Serialize, Deserialize, Debug)] +#[derive(poem_openapi::Object, Serialize, Deserialize, Debug, Clone)] +pub struct EventTopicConfig { + pub code: String, + pub blocking: bool, + pub topic_code: String, + pub overflow_policy: String, + pub overflow_size: i32, +} + +#[derive(poem_openapi::Object, Serialize, Deserialize, Debug, Clone, FromQueryResult)] + pub struct EventTopicAddOrModifyReq { - // #[oai(validator(pattern = r"^[a-z0-9]+$"))] - pub code: TrimString, - pub name: TrimString, - pub save_message: bool, - pub need_mgr: bool, - #[oai(validator(minimum(value = "1", exclusive = "false")))] - pub queue_size: i32, - pub use_sk: Option, - pub mgr_sk: Option, + pub code: String, + pub name: String, + pub blocking: bool, + pub topic_code: String, + pub overflow_policy: String, + pub overflow_size: i32, +} +impl EventTopicAddOrModifyReq { + pub fn into_topic_config(self) -> TopicConfig { + TopicConfig { + code: TopicCode::new(self.topic_code), + blocking: self.blocking, + overflow_config: Some(TopicOverflowConfig { + policy: match self.overflow_policy.as_str() { + "RejectNew" => TopicOverflowPolicy::RejectNew, + "DropOld" => TopicOverflowPolicy::DropOld, + _ => TopicOverflowPolicy::default(), + }, + size: NonZeroU32::new(self.overflow_size.clamp(1, i32::MAX) as u32).expect("clamped"), + }), + } + } } -#[derive(poem_openapi::Object, sea_orm::FromQueryResult, Serialize, Deserialize, Debug, Clone)] +#[derive(poem_openapi::Object, Serialize, Deserialize, Debug, Clone, FromQueryResult)] pub struct EventTopicInfoResp { // #[oai(validator(pattern = r"^[a-z0-9]+$"))] pub code: String, pub name: String, - pub save_message: bool, - pub need_mgr: bool, - #[oai(validator(minimum(value = "1", exclusive = "false")))] - pub queue_size: i32, - pub use_sk: String, - pub mgr_sk: String, + pub blocking: bool, + pub topic_code: String, + pub overflow_policy: String, + pub overflow_size: i32, +} + +impl EventTopicInfoResp { + pub fn into_topic_config(self) -> TopicConfig { + TopicConfig { + code: TopicCode::new(self.topic_code), + blocking: self.blocking, + overflow_config: Some(TopicOverflowConfig { + policy: match self.overflow_policy.as_str() { + "RejectNew" => TopicOverflowPolicy::RejectNew, + "DropOld" => TopicOverflowPolicy::DropOld, + _ => TopicOverflowPolicy::default(), + }, + size: NonZeroU32::new(self.overflow_size.clamp(1, i32::MAX) as u32).expect("clamped"), + }), + } + } } #[derive(poem_openapi::Object, Serialize, Deserialize, Debug, Clone, Default)] diff --git a/backend/middlewares/event/src/event_config.rs b/backend/middlewares/event/src/event_config.rs index 511b95e2b..167d589ab 100644 --- a/backend/middlewares/event/src/event_config.rs +++ b/backend/middlewares/event/src/event_config.rs @@ -8,6 +8,7 @@ use tardis::basic::{error::TardisError, result::TardisResult}; pub struct EventConfig { pub rbum: RbumConfig, pub enable: bool, + pub svc: String, pub event_url: String, pub base_url: String, pub event_bus_sk: String, @@ -22,6 +23,7 @@ impl Default for EventConfig { rbum: Default::default(), enable: false, base_url: "http://localhost:8080/event".to_string(), + svc: "bios".to_string(), avatars: Vec::new(), event_url: "".to_string(), event_bus_sk: "".to_string(), diff --git a/backend/middlewares/event/src/event_initializer.rs b/backend/middlewares/event/src/event_initializer.rs index db977fd37..e5183f74c 100644 --- a/backend/middlewares/event/src/event_initializer.rs +++ b/backend/middlewares/event/src/event_initializer.rs @@ -1,9 +1,12 @@ +use std::vec; + +use asteroid_mq::{prelude::TopicConfig, protocol::topic::durable_message::LoadTopic}; use bios_basic::rbum::{ dto::{rbum_domain_dto::RbumDomainAddReq, rbum_kind_dto::RbumKindAddReq}, rbum_enumeration::RbumScopeLevelKind, - serv::{rbum_crud_serv::RbumCrudOperation, rbum_domain_serv::RbumDomainServ, rbum_item_serv::RbumItemCrudOperation, rbum_kind_serv::RbumKindServ}, + serv::{rbum_crud_serv::RbumCrudOperation, rbum_domain_serv::RbumDomainServ, rbum_kind_serv::RbumKindServ}, }; -use bios_sdk_invoke::clients::event_client::{BiosEventCenter, EventCenter, EventCenterConfig, TOPIC_BIOS_PUB_SUB, TOPIC_BIOS_WORKER_QUEUE}; +use bios_sdk_invoke::clients::event_client::SPI_RPC_TOPIC; use tardis::{ basic::{dto::TardisContext, field::TrimString, result::TardisResult}, db::reldb_client::TardisActiveModel, @@ -13,21 +16,16 @@ use tardis::{ use crate::{ api::{event_listener_api, event_proc_api, event_topic_api}, - domain::{event_persistent, event_topic}, - dto::event_dto::EventTopicAddOrModifyReq, + domain::event_topic, event_config::{EventConfig, EventInfo, EventInfoManager}, event_constants::{DOMAIN_CODE, KIND_CODE}, - serv::{self, event_proc_serv::CreateRemoteSenderHandler, event_topic_serv::EventDefServ}, }; pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { let mut funs = TardisFuns::inst_with_db_conn(DOMAIN_CODE.to_string(), None); let config = funs.conf::(); - if config.enable { - create_event_center()?; - } + init_api(web_server).await?; - init_cluster_resource().await; let ctx = TardisContext { own_paths: "".to_string(), ak: "".to_string(), @@ -38,45 +36,11 @@ pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { }; funs.begin().await?; init_db(DOMAIN_CODE.to_string(), KIND_CODE.to_string(), &funs, &ctx).await?; - EventDefServ::init(&funs, &ctx).await?; - init_topic(&funs, &ctx).await?; - funs.commit().await?; - init_scan_and_resend_task(); - Ok(()) -} -async fn init_topic(funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let config = funs.conf::(); - // create bios worker queue topic - let _result = serv::event_topic_serv::EventDefServ::add_item( - &mut EventTopicAddOrModifyReq { - code: TOPIC_BIOS_WORKER_QUEUE.into(), - name: TOPIC_BIOS_WORKER_QUEUE.into(), - save_message: false, - need_mgr: false, - queue_size: 1024, - use_sk: Some(config.event_bus_sk.clone()), - mgr_sk: None, - }, - funs, - ctx, - ) - .await; - // create bios pub sub topic - let _result = serv::event_topic_serv::EventDefServ::add_item( - &mut EventTopicAddOrModifyReq { - code: TOPIC_BIOS_PUB_SUB.into(), - name: TOPIC_BIOS_PUB_SUB.into(), - save_message: false, - need_mgr: false, - queue_size: 1024, - use_sk: Some(config.event_bus_sk.clone()), - mgr_sk: None, - }, - funs, - ctx, - ) - .await; + funs.commit().await?; + if config.enable { + init_mq_cluster(&config.svc).await?; + } Ok(()) } @@ -87,15 +51,15 @@ async fn init_db(domain_code: String, kind_code: String, funs: &TardisFunsInst, return Ok(()); } - funs.db() - .init(event_persistent::ActiveModel::init( - TardisFuns::reldb().backend(), - None, - TardisFuns::reldb().compatible_type(), - )) - .await?; // Initialize event component RBUM item table and indexs funs.db().init(event_topic::ActiveModel::init(TardisFuns::reldb().backend(), None, TardisFuns::reldb().compatible_type())).await?; + // funs.db() + // .init(event_persistent::ActiveModel::init( + // TardisFuns::reldb().backend(), + // None, + // TardisFuns::reldb().compatible_type(), + // )) + // .await?; // Initialize event component RBUM domain data let domain_id = RbumDomainServ::add_rbum( &mut RbumDomainAddReq { @@ -119,7 +83,7 @@ async fn init_db(domain_code: String, kind_code: String, funs: &TardisFunsInst, icon: None, sort: None, module: None, - ext_table_name: Some("event_topic".to_lowercase()), + ext_table_name: Some("mq_topic".to_lowercase()), scope_level: Some(RbumScopeLevelKind::Root), }, funs, @@ -140,55 +104,31 @@ async fn init_api(web_server: &TardisWebServer) -> TardisResult<()> { Ok(()) } -async fn init_cluster_resource() { - use crate::serv::event_listener_serv::{listeners, mgr_listeners}; - use crate::serv::event_topic_serv::topics; - use tardis::cluster::cluster_processor::subscribe; - subscribe(listeners().clone()).await; - subscribe(mgr_listeners().clone()).await; - subscribe(topics().clone()).await; - subscribe(CreateRemoteSenderHandler).await; -} - -fn init_scan_and_resend_task() { - let funs = TardisFuns::inst_with_db_conn(DOMAIN_CODE.to_string(), None); - - let config = funs.conf::(); - let Some(interval_sec) = config.resend_interval_sec else { - return; - }; - let mut interval = tardis::tokio::time::interval(tardis::tokio::time::Duration::from_secs(interval_sec as u64)); - tardis::tokio::spawn(async move { - loop { - interval.tick().await; - let funs = TardisFuns::inst_with_db_conn(DOMAIN_CODE.to_string(), None); - let _ = crate::serv::event_proc_serv::scan_and_resend(funs.into()).await; - } - }); +async fn init_mq_cluster(svc_name: &str) -> TardisResult<()> { + use bios_sdk_invoke::clients::event_client::mq_error; + let mq_node = init_mq_node(svc_name).await; + mq_node + .load_topic(LoadTopic { + config: TopicConfig { + code: SPI_RPC_TOPIC, + overflow_config: None, + blocking: false, + }, + queue: vec![], + }) + .await + .map_err(mq_error)?; + Ok(()) } -fn create_event_center() -> TardisResult<()> { - let config = TardisFuns::cs_config::(DOMAIN_CODE); - let pubsub_config = EventCenterConfig { - base_url: config.base_url.clone(), - topic_sk: config.event_bus_sk.clone(), - topic_code: TOPIC_BIOS_PUB_SUB.to_owned(), - subscribe: true, - avatars: config.avatars.clone(), - }; - let pubsub = BiosEventCenter::from_config(pubsub_config); - pubsub.init()?; - pubsub.set_as_worker_queue(); - - let wq_config = EventCenterConfig { - base_url: config.base_url.clone(), - topic_sk: config.event_bus_sk.clone(), - topic_code: TOPIC_BIOS_WORKER_QUEUE.to_owned(), - subscribe: false, - avatars: config.avatars.clone(), - }; - let wq = BiosEventCenter::from_config(wq_config); - wq.init()?; - wq.set_as_worker_queue(); - Ok(()) +pub async fn init_mq_node(svc_name: &str) -> asteroid_mq::prelude::Node { + if let Some(node) = TardisFuns::store().get_singleton::() { + node + } else { + let cluster_provider = asteroid_mq::protocol::cluster::k8s::K8sClusterProvider::new(svc_name.to_string(), asteroid_mq::DEFAULT_TCP_PORT).await; + let uid = std::env::var("POD_UID").expect("POD_UID is required"); + let node = cluster_provider.run(uid).await.expect("failed to run k8s cluster"); + TardisFuns::store().insert_singleton(node.clone()); + node + } } diff --git a/backend/middlewares/event/src/serv.rs b/backend/middlewares/event/src/serv.rs index 4e880d804..eddea19ba 100644 --- a/backend/middlewares/event/src/serv.rs +++ b/backend/middlewares/event/src/serv.rs @@ -1,4 +1,3 @@ pub mod event_listener_serv; -pub mod event_persistent_serv; pub mod event_proc_serv; pub mod event_topic_serv; diff --git a/backend/middlewares/event/src/serv/event_listener_serv.rs b/backend/middlewares/event/src/serv/event_listener_serv.rs index cd7d57c0a..e69de29bb 100644 --- a/backend/middlewares/event/src/serv/event_listener_serv.rs +++ b/backend/middlewares/event/src/serv/event_listener_serv.rs @@ -1,97 +0,0 @@ -use crate::dto::event_dto::{EventListenerInfo, EventListenerRegisterReq, EventListenerRegisterResp}; -use crate::event_config::EventConfig; -use tardis::cluster::cluster_hashmap::ClusterStaticHashMap; -use tardis::tardis_static; -use tardis::tracing; -use tardis::TardisFunsInst; -use tardis::{basic::result::TardisResult, TardisFuns}; - -use super::event_topic_serv::topics; - -tardis_static! { - pub(crate) listeners: ClusterStaticHashMap = ClusterStaticHashMap::new("bios/event/listeners"); - // (topic, event) => avatar - pub(crate) mgr_listeners: ClusterStaticHashMap<(String, String), String> = ClusterStaticHashMap::new("bios/event/msg_listeners"); -} - -const MGR_LISTENER_AVATAR_PREFIX: &str = "_"; - -#[tracing::instrument(skip_all, fields(domain = "event"))] -pub(crate) async fn register(listener: EventListenerRegisterReq, funs: &TardisFunsInst) -> TardisResult { - let Some(topic) = topics().get(listener.topic_code.to_string()).await? else { - return Err(funs.err().not_found("listener", "register", "topic not found", "404-event-topic-not-exist")); - }; - let sk = listener.topic_sk.clone().unwrap_or("".to_string()); - let mgr = if sk == topic.use_sk { - false - } else if sk == topic.mgr_sk { - true - } else { - return Err(funs.err().unauthorized("listener", "register", "sk do not match", "401-event-listener-sk-not-match")); - }; - let avatars = if mgr { - // let mut mgr_listeners = MGR_LISTENERS.write().await; - // let mgr_listeners_with_topic = mgr_listeners.entry(listener.topic_code.to_string()).or_insert_with(HashMap::new); - let topic = listener.topic_code.to_string(); - match &listener.events { - Some(events) => { - let pairs = events.iter().map(|event| ((topic.to_string(), event.to_string()), format!("{MGR_LISTENER_AVATAR_PREFIX}{event}"))).collect(); - let avatars = events.iter().map(|event| format!("{MGR_LISTENER_AVATAR_PREFIX}{event}")).collect::>(); - mgr_listeners().batch_insert(pairs).await?; - avatars - } - None => { - mgr_listeners().insert((topic.to_string(), String::default()), MGR_LISTENER_AVATAR_PREFIX.to_string()).await?; - vec![MGR_LISTENER_AVATAR_PREFIX.to_string()] - } - } - } else { - if listener.avatars.is_empty() { - return Err(funs.err().bad_request("listener", "register", "avatars can not be empty", "400-event-listener-avatars-empty")); - } - if listener.avatars.iter().any(|v| v.starts_with(MGR_LISTENER_AVATAR_PREFIX)) { - return Err(funs.err().bad_request( - "listener", - "register", - &format!("non-management avatars can not start with '{MGR_LISTENER_AVATAR_PREFIX}'"), - "400-event-listener-avatars-invalid", - )); - } - listener.avatars.iter().map(|v| v.to_string()).collect() - }; - - let listener_code = TardisFuns::crypto.base64.encode(TardisFuns::field.nanoid()); - let token = TardisFuns::field.nanoid_len(32); - let listener_info = EventListenerInfo { - topic_code: listener.topic_code.to_string(), - events: listener.events.map(|v| v.iter().map(|v| v.to_string()).collect()), - mgr, - subscribe_mode: listener.subscribe_mode, - token: token.clone(), - avatars: avatars.clone(), - }; - listeners().insert(listener_code.clone(), listener_info).await?; - let event_url = funs.conf::().event_url(); - Ok(EventListenerRegisterResp { - listener_code: listener_code.clone(), - ws_addr: format!("{event_url}proc/{listener_code}?token={token}"), - }) -} - -pub(crate) async fn remove(listener_code: &str, token: &str, funs: &TardisFunsInst) -> TardisResult<()> { - let Some(listener) = listeners().get(listener_code.to_string()).await? else { - return Err(funs.err().not_found("listener", "remove", "listener not found", "404-event-listener-not-exist")); - }; - if listener.token != token { - return Err(funs.err().unauthorized("listener", "remove", "token do not match", "401-event-listener-token-not-match")); - } - listeners().remove(listener_code.to_string()).await?; - if listener.mgr { - let to_removes = match listener.events { - Some(events) => events.into_iter().map(|event_code| (listener.topic_code.clone(), event_code)).collect(), - None => vec![(listener.topic_code.clone(), String::default())], - }; - mgr_listeners().batch_remove(to_removes).await?; - } - Ok(()) -} diff --git a/backend/middlewares/event/src/serv/event_persistent_serv.rs b/backend/middlewares/event/src/serv/event_persistent_serv.rs deleted file mode 100644 index 989dad646..000000000 --- a/backend/middlewares/event/src/serv/event_persistent_serv.rs +++ /dev/null @@ -1,106 +0,0 @@ -use tardis::basic::result::TardisResult; -use tardis::db::sea_orm::sea_query::{Expr, Query}; -use tardis::db::sea_orm::{ColumnTrait, ConnectionTrait, EntityTrait, QueryFilter, QueryOrder, Set}; -use tardis::futures::{Stream, StreamExt}; -use tardis::web::ws_processor::{TardisWebsocketReq, WsBroadcastContext}; -use tardis::{serde_json, TardisFunsInst}; - -use crate::domain::event_persistent; - -pub struct EventPersistentServ; -impl EventPersistentServ { - pub async fn save_message(message: PersistentMessage, funs: &TardisFunsInst) -> TardisResult<()> { - if let Some(id) = message.req.msg_id.to_owned() { - let db = funs.db(); - let _ = event_persistent::Entity::insert(event_persistent::ActiveModel { - id: Set(id), - message: Set(serde_json::to_value(message.req).expect("TardisWebsocketReq cannot be converted to json")), - status: Set(event_persistent::Status::Sending.to_string()), - topic: Set(message.topic), - inst_id: Set(message.context.inst_id.clone()), - mgr_node: Set(message.context.mgr_node), - subscribe_mode: Set(message.context.subscribe_mode), - ..Default::default() - }) - .exec(db.raw_conn()) - .await?; - } - Ok(()) - } - pub async fn sending(id: String, funs: &TardisFunsInst) -> TardisResult { - use tardis::db::sea_orm::StatementBuilder; - let db = funs.db().raw_conn(); - let query = Query::update() - .table(event_persistent::Entity) - .value(event_persistent::Column::RetryTimes, Expr::col(event_persistent::Column::RetryTimes).add(1)) - .value(event_persistent::Column::Status, event_persistent::Status::Sending.to_string()) - .cond_where(event_persistent::Column::Id.eq(id).and(event_persistent::Column::Status.eq(event_persistent::Status::Failed.to_string()))) - .to_owned(); - let statement = StatementBuilder::build(&query, &db.get_database_backend()); - let success = db.execute(statement).await?.rows_affected() >= 1; - Ok(success) - } - pub async fn send_success(id: String, funs: &TardisFunsInst) -> TardisResult<()> { - let db = funs.db().raw_conn(); - let result = event_persistent::Entity::update(event_persistent::ActiveModel { - id: Set(id), - status: Set(event_persistent::Status::Success.to_string()), - ..Default::default() - }) - .filter(event_persistent::Column::Status.eq(event_persistent::Status::Sending.as_str())) - .exec(db) - .await; - // Missing this record implies that we have never processed it, witch it's ok. - if matches!(result, Err(tardis::db::sea_orm::DbErr::RecordNotUpdated)) { - return Ok(()); - } else { - result?; - } - Ok(()) - } - pub async fn send_fail(id: String, error: impl Into, funs: &TardisFunsInst) -> TardisResult<()> { - let db = funs.db().raw_conn(); - let result = event_persistent::Entity::update(event_persistent::ActiveModel { - id: Set(id), - status: Set(event_persistent::Status::Failed.to_string()), - error: Set(Some(error.into())), - ..Default::default() - }) - .filter(event_persistent::Column::Status.eq(event_persistent::Status::Sending.as_str())) - .exec(db) - .await; - // Missing this record implies that we have never processed it, witch it's ok. - if matches!(result, Err(tardis::db::sea_orm::DbErr::RecordNotUpdated)) { - return Ok(()); - } else { - result?; - } - Ok(()) - } - - pub async fn scan_failed(funs: &TardisFunsInst, threshold: i32) -> TardisResult + '_> { - let db = funs.db().raw_conn(); - Ok(event_persistent::Entity::find() - .filter(event_persistent::Column::Status.eq(event_persistent::Status::Failed.as_str()).and(event_persistent::Column::RetryTimes.lt(threshold))) - .order_by_desc(event_persistent::Column::UpdateTime) - .stream(db) - .await? - .filter_map(|item| async move { - let item = item.ok()?; - let req = serde_json::from_value::(item.message).ok()?; - let topic = item.topic; - let context = WsBroadcastContext { - inst_id: item.inst_id, - mgr_node: item.mgr_node, - subscribe_mode: item.subscribe_mode, - }; - Some(PersistentMessage { req, context, topic }) - })) - } -} - -pub struct PersistentMessage { - pub req: TardisWebsocketReq, - pub context: WsBroadcastContext, - pub topic: String, -} diff --git a/backend/middlewares/event/src/serv/event_proc_serv.rs b/backend/middlewares/event/src/serv/event_proc_serv.rs index a3c82df53..e69de29bb 100644 --- a/backend/middlewares/event/src/serv/event_proc_serv.rs +++ b/backend/middlewares/event/src/serv/event_proc_serv.rs @@ -1,221 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use serde::{Deserialize, Serialize}; -use tardis::basic::error::TardisError; -use tardis::basic::result::TardisResult; -use tardis::cluster::cluster_processor::{ClusterEventTarget, TardisClusterMessageReq}; -use tardis::cluster::cluster_publish::publish_event_no_response; -use tardis::futures::StreamExt; -use tardis::log::{self as tracing, debug, instrument, warn}; -use tardis::serde_json::Value; -use tardis::tokio::sync::RwLock; -use tardis::web::poem::web::websocket::{BoxWebSocketUpgraded, WebSocket}; -use tardis::web::ws_processor::{TardisWebsocketMgrMessage, TardisWebsocketReq, TardisWebsocketResp, WsBroadcast, WsBroadcastContext, WsHooks}; -use tardis::{ - cluster::{cluster_broadcast::ClusterBroadcastChannel, cluster_processor::ClusterHandler}, - tardis_static, -}; -use tardis::{TardisFuns, TardisFunsInst}; - -use crate::dto::event_dto::EventMessageMgrWrap; -use crate::event_config::EventConfig; - -use super::event_listener_serv::{listeners, mgr_listeners}; -use super::event_persistent_serv::PersistentMessage; -use super::event_topic_serv::topics; - -tardis_static! { - // temporary no cleaner for senders - pub senders: Arc>>>>; -} - -#[derive(Clone, Serialize, Deserialize)] -pub struct CreateRemoteSenderEvent { - pub topic_code: String, - pub capacity: usize, -} - -pub struct CreateRemoteSenderHandler; - -impl ClusterHandler for CreateRemoteSenderHandler { - fn event_name(&self) -> String { - "bios/event/create_remote_sender".into() - } - async fn handle(self: Arc, message_req: TardisClusterMessageReq) -> TardisResult> { - let CreateRemoteSenderEvent { topic_code, capacity } = TardisFuns::json.json_to_obj(message_req.msg)?; - - let clst_bc_tx = ClusterBroadcastChannel::new(topic_code.clone(), capacity); - let mut wg = senders().write().await; - wg.insert(topic_code, clst_bc_tx); - - Ok(None) - } -} - -pub async fn get_or_init_sender(topic_code: String, capacity: usize) -> Arc> { - let mut wg = senders().write().await; - if let Some(chan) = wg.get(&topic_code) { - tardis::log::trace!("clone existed sender: {topic_code}"); - chan.clone() - } else { - tardis::log::trace!("create new sender: {topic_code}:{capacity}"); - let clst_bc_tx = ClusterBroadcastChannel::new(topic_code.clone(), capacity); - wg.insert(topic_code.clone(), clst_bc_tx.clone()); - drop(wg); - if TardisFuns::fw_config().cluster.is_some() { - let _ = publish_event_no_response( - CreateRemoteSenderHandler.event_name(), - TardisFuns::json.obj_to_json(&CreateRemoteSenderEvent { topic_code, capacity }).expect("invalid json"), - ClusterEventTarget::Broadcast, - ) - .await; - } - clst_bc_tx - } -} - -pub struct Hooks { - persistent: bool, - need_mgr: bool, - topic_code: String, - funs: Arc, -} - -impl WsHooks for Hooks { - async fn on_fail(&self, id: String, error: TardisError, _context: &WsBroadcastContext) { - debug!("[Event] message {id} send out fail"); - if self.persistent { - let result = super::event_persistent_serv::EventPersistentServ::send_fail(id, error.to_string(), &self.funs).await; - if let Err(error) = result { - warn!("[Event] store status failed: {error}"); - } - } - } - async fn on_success(&self, id: String, _context: &WsBroadcastContext) { - debug!("[Event] message {id} send out success"); - if self.persistent { - let result = super::event_persistent_serv::EventPersistentServ::send_success(id, &self.funs).await; - if let Err(error) = result { - warn!("[Event] store status failed: {error}"); - } - } - } - #[instrument(skip(self))] - async fn on_process(&self, req_msg: TardisWebsocketReq, context: &WsBroadcastContext) -> Option { - if self.persistent { - let result = super::event_persistent_serv::EventPersistentServ::save_message( - PersistentMessage { - req: req_msg.clone(), - context: context.clone(), - topic: self.topic_code.clone(), - }, - &self.funs, - ) - .await; - if let Err(error) = result { - warn!("[Event] save message failed: {error}"); - } - } - if !self.need_mgr || context.mgr_node { - return Some(TardisWebsocketResp { - msg: req_msg.msg, - to_avatars: req_msg.to_avatars.unwrap_or_default(), - ignore_avatars: vec![], - }); - } - // TODO set cache - let topic_code = self.topic_code.clone(); - let msg_avatar = if let Some(req_event_code) = req_msg.event.clone() { - mgr_listeners().get((topic_code.clone(), req_event_code)).await - } else { - mgr_listeners().get((topic_code.clone(), Default::default())).await - }; - let Ok(Some(msg_avatar)) = msg_avatar else { - warn!( - "[Event] topic [{}] event code [{}] management node not found", - topic_code, - &req_msg.event.unwrap_or_default() - ); - return None; - }; - Some(TardisWebsocketResp { - msg: TardisFuns::json - .obj_to_json(&EventMessageMgrWrap { - msg: req_msg.msg, - ori_from_avatar: req_msg.from_avatar, - ori_to_avatars: req_msg.to_avatars, - }) - .expect("EventMessageMgrWrap not a valid json value"), - to_avatars: vec![msg_avatar.clone()], - ignore_avatars: vec![], - }) - } -} - -pub(crate) async fn ws_process(listener_code: String, token: String, websocket: WebSocket, funs: TardisFunsInst) -> TardisResult { - let Ok(Some(listener)) = listeners().get(listener_code.clone()).await else { - return Err(TardisError::bad_request(&format!("listener {} not found", listener_code), "ws-upgrade-error")); - }; - if listener.token != token { - return Err(TardisError::bad_request(&format!("invalid token {} ", token), "ws-upgrade-error")); - } - let Ok(Some(topic)) = topics().get(listener.topic_code.clone()).await else { - return Err(TardisError::bad_request(&format!("topic not found {} ", token), "ws-upgrade-error")); - }; - let sender = get_or_init_sender(listener.topic_code.clone(), topic.queue_size as usize).await; - tardis::log::trace!("[Bios.Event] create {topic:?} process for {token}"); - Ok(WsBroadcast::new( - sender, - Hooks { - persistent: topic.save_message, - need_mgr: topic.need_mgr, - topic_code: listener.topic_code.clone(), - funs: Arc::new(funs), - }, - WsBroadcastContext::new(listener.mgr, listener.subscribe_mode), - ) - .run(listener.avatars.clone(), websocket) - .await) -} - -pub async fn scan_and_resend(funs: Arc) -> TardisResult<()> { - let config = funs.conf::(); - let threshold = config.resend_threshold; - let scanner = super::event_persistent_serv::EventPersistentServ::scan_failed(&funs, threshold as i32).await?; - let mut scanner = std::pin::pin!(scanner); - while let Some(PersistentMessage { req, context, topic }) = scanner.next().await { - let funs = funs.clone(); - tardis::tokio::spawn(async move { - let Some(id) = req.msg_id.clone() else { - warn!("[Bios.Event] msg_id not found: {req:?}"); - return Ok(()); - }; - let Ok(Some(topic_resp)) = topics().get(topic.clone()).await else { - warn!("[Bios.Event] topic not found: {topic}"); - return Ok(()); - }; - let sender = get_or_init_sender(topic_resp.code.clone(), topic_resp.queue_size as usize).await; - if !super::event_persistent_serv::EventPersistentServ::sending(id.clone(), &funs).await? { - // state conflict - return TardisResult::Ok(()); - } - let broadcast = WsBroadcast::new( - sender, - Hooks { - persistent: topic_resp.save_message, - need_mgr: topic_resp.need_mgr, - topic_code: topic_resp.code, - funs: funs.clone(), - }, - context, - ); - let resend_result = broadcast.handle_req(req).await; - if let Err(error) = resend_result { - super::event_persistent_serv::EventPersistentServ::send_fail(id, error, &funs).await?; - } - TardisResult::Ok(()) - }); - } - Ok(()) -} diff --git a/backend/middlewares/event/src/serv/event_topic_serv.rs b/backend/middlewares/event/src/serv/event_topic_serv.rs index ffb94c6b6..f55dbc352 100644 --- a/backend/middlewares/event/src/serv/event_topic_serv.rs +++ b/backend/middlewares/event/src/serv/event_topic_serv.rs @@ -2,22 +2,18 @@ use async_trait::async_trait; use bios_basic::rbum::dto::rbum_item_dto::{RbumItemKernelAddReq, RbumItemKernelModifyReq}; use bios_basic::rbum::rbum_enumeration::RbumScopeLevelKind; use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation; +use bios_sdk_invoke::clients::event_client::mq_node; use tardis::basic::dto::TardisContext; +use tardis::basic::error::TardisError; use tardis::basic::result::TardisResult; use tardis::db::sea_orm::sea_query::SelectStatement; use tardis::db::sea_orm::{EntityName, Set}; -use tardis::{tardis_static, TardisFunsInst}; +use tardis::TardisFunsInst; use crate::domain::event_topic; use crate::dto::event_dto::{EventTopicAddOrModifyReq, EventTopicFilterReq, EventTopicInfoResp}; use crate::event_config::EventInfoManager; -use tardis::cluster::cluster_hashmap::ClusterStaticHashMap; - -tardis_static! { - pub(crate) topics: ClusterStaticHashMap = ClusterStaticHashMap::new("bios/event/topics"); -} - pub struct EventDefServ; #[async_trait] @@ -38,8 +34,8 @@ impl RbumItemCrudOperation TardisResult { Ok(RbumItemKernelAddReq { - code: Some(add_req.code.clone()), - name: add_req.name.clone(), + code: Some(add_req.code.clone().into()), + name: add_req.name.clone().into(), scope_level: Some(RbumScopeLevelKind::Root), ..Default::default() }) @@ -48,76 +44,62 @@ impl RbumItemCrudOperation TardisResult { Ok(event_topic::ActiveModel { id: Set(id.to_string()), - save_message: Set(add_req.save_message), - need_mgr: Set(add_req.need_mgr), - queue_size: Set(add_req.queue_size), - use_sk: Set(add_req.use_sk.as_deref().unwrap_or("").to_string()), - mgr_sk: Set(add_req.mgr_sk.as_deref().unwrap_or("").to_string()), + blocking: Set(add_req.blocking), + overflow_policy: Set(add_req.overflow_policy.clone()), + overflow_size: Set(add_req.overflow_size), + topic_code: Set(add_req.code.clone()), ..Default::default() }) } async fn after_add_item(id: &str, add_req: &mut EventTopicAddOrModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let key = add_req.code.to_string(); + let _key = add_req.code.to_string(); let value = Self::get_item(id, &EventTopicFilterReq::default(), funs, ctx).await?; - // topics().local().write().await.insert(key, value); - tardis::tokio::spawn(async { - let _ = topics().insert(key, value).await; - }); + mq_node().new_topic(value.into_topic_config()).await.map_err(|e| TardisError::internal_error(&e.to_string(), "event-fail-to-create-topic"))?; Ok(()) } async fn package_item_modify(_: &str, modify_req: &EventTopicAddOrModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult> { Ok(Some(RbumItemKernelModifyReq { - code: Some(modify_req.code.clone()), - name: Some(modify_req.name.clone()), + code: Some(modify_req.code.clone().into()), + name: Some(modify_req.name.clone().into()), ..Default::default() })) } async fn package_ext_modify(_: &str, modify_req: &EventTopicAddOrModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult> { let event_topic = event_topic::ActiveModel { - save_message: Set(modify_req.save_message), - need_mgr: Set(modify_req.need_mgr), - queue_size: Set(modify_req.queue_size), - use_sk: Set(modify_req.use_sk.as_deref().unwrap_or("").to_string()), - mgr_sk: Set(modify_req.mgr_sk.as_deref().unwrap_or("").to_string()), + blocking: Set(modify_req.blocking), + overflow_policy: Set(modify_req.overflow_policy.clone()), + overflow_size: Set(modify_req.overflow_size), + topic_code: Set(modify_req.code.clone()), ..Default::default() }; Ok(Some(event_topic)) } - async fn after_modify_item(id: &str, modify_req: &mut EventTopicAddOrModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let key = modify_req.code.to_string(); - let value = Self::get_item(id, &EventTopicFilterReq::default(), funs, ctx).await?; - topics().insert(key, value).await?; - Ok(()) - } + // async fn after_modify_item(id: &str, modify_req: &mut EventTopicAddOrModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + // Ok(()) + // } - async fn after_delete_item(id: &str, _: &Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let item = Self::get_item(id, &EventTopicFilterReq::default(), funs, ctx).await?; - topics().remove(item.code).await?; - Ok(()) - } + // async fn after_delete_item(id: &str, _: &Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + // Ok(()) + // } async fn package_ext_query(query: &mut SelectStatement, _: bool, _: &EventTopicFilterReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<()> { query - .column((event_topic::Entity, event_topic::Column::SaveMessage)) - .column((event_topic::Entity, event_topic::Column::NeedMgr)) - .column((event_topic::Entity, event_topic::Column::QueueSize)) - .column((event_topic::Entity, event_topic::Column::UseSk)) - .column((event_topic::Entity, event_topic::Column::MgrSk)); + .column((event_topic::Entity, event_topic::Column::Blocking)) + .column((event_topic::Entity, event_topic::Column::OverflowPolicy)) + .column((event_topic::Entity, event_topic::Column::OverflowSize)) + .column((event_topic::Entity, event_topic::Column::TopicCode)); Ok(()) } } impl EventDefServ { pub async fn init(funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let defs = Self::find_items(&EventTopicFilterReq::default(), None, None, funs, ctx).await?; - let mut cache_defs = topics().local().write().await; - for def in defs { - cache_defs.insert(def.code.to_string(), def); - } + // let defs = Self::find_items(&EventTopicFilterReq::default(), None, None, funs, ctx).await?; + Ok(()) } } diff --git a/backend/middlewares/event/test-vue/package-lock.json b/backend/middlewares/event/test-vue/package-lock.json deleted file mode 100644 index 50e0d89bd..000000000 --- a/backend/middlewares/event/test-vue/package-lock.json +++ /dev/null @@ -1,3313 +0,0 @@ -{ - "name": "event-test", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "event-test", - "version": "0.0.0", - "dependencies": { - "axios": "^1.6.0", - "vue": "^3.2.47", - "vue-router": "^4.1.6" - }, - "devDependencies": { - "@types/node": "^18.14.2", - "@vitejs/plugin-vue": "^4.0.0", - "@vue/tsconfig": "^0.1.3", - "npm-run-all": "^4.1.5", - "typescript": "~4.8.4", - "vite": "^4.5.2", - "vite-plugin-top-level-await": "^1.3.0", - "vite-plugin-wasm": "^3.2.2", - "vue-tsc": "^1.2.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.21.4", - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/plugin-virtual": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@swc/core": { - "version": "1.3.51", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.51", - "@swc/core-darwin-x64": "1.3.51", - "@swc/core-linux-arm-gnueabihf": "1.3.51", - "@swc/core-linux-arm64-gnu": "1.3.51", - "@swc/core-linux-arm64-musl": "1.3.51", - "@swc/core-linux-x64-gnu": "1.3.51", - "@swc/core-linux-x64-musl": "1.3.51", - "@swc/core-win32-arm64-msvc": "1.3.51", - "@swc/core-win32-ia32-msvc": "1.3.51", - "@swc/core-win32-x64-msvc": "1.3.51" - }, - "peerDependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.51", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/node": { - "version": "18.15.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitejs/plugin-vue": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@volar/language-core": { - "version": "1.3.0-alpha.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/source-map": "1.3.0-alpha.0" - } - }, - "node_modules/@volar/source-map": { - "version": "1.3.0-alpha.0", - "dev": true, - "license": "MIT", - "dependencies": { - "muggle-string": "^0.2.2" - } - }, - "node_modules/@volar/typescript": { - "version": "1.3.0-alpha.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "1.3.0-alpha.0" - } - }, - "node_modules/@volar/vue-language-core": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "1.3.0-alpha.0", - "@volar/source-map": "1.3.0-alpha.0", - "@vue/compiler-dom": "^3.2.47", - "@vue/compiler-sfc": "^3.2.47", - "@vue/reactivity": "^3.2.47", - "@vue/shared": "^3.2.47", - "minimatch": "^6.1.6", - "muggle-string": "^0.2.2", - "vue-template-compiler": "^2.7.14" - } - }, - "node_modules/@volar/vue-language-core/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@volar/vue-language-core/node_modules/minimatch": { - "version": "6.2.0", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@volar/vue-typescript": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/typescript": "1.3.0-alpha.0", - "@volar/vue-language-core": "1.2.0" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.5.0", - "license": "MIT" - }, - "node_modules/@vue/reactivity": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/shared": "3.2.47" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" - }, - "peerDependencies": { - "vue": "3.2.47" - } - }, - "node_modules/@vue/shared": { - "version": "3.2.47", - "license": "MIT" - }, - "node_modules/@vue/tsconfig": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.6.0", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/csstype": { - "version": "2.6.21", - "license": "MIT" - }, - "node_modules/de-indent": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/define-properties": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/has": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/he": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/muggle-string": { - "version": "0.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.6", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/pidtree": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.4.31", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/read-pkg": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "license": "MIT" - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/string.prototype.padend": { - "version": "3.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "4.8.4", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/uuid": { - "version": "9.0.0", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vite": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", - "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", - "dev": true, - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-plugin-top-level-await": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/plugin-virtual": "^3.0.1", - "@swc/core": "^1.3.10", - "uuid": "^9.0.0" - }, - "peerDependencies": { - "vite": ">=2.8" - } - }, - "node_modules/vite-plugin-wasm": { - "version": "3.2.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "vite": "^2 || ^3 || ^4" - } - }, - "node_modules/vue": { - "version": "3.2.47", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "node_modules/vue-router": { - "version": "4.1.6", - "license": "MIT", - "dependencies": { - "@vue/devtools-api": "^6.4.5" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.7.14", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "node_modules/vue-tsc": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/vue-language-core": "1.2.0", - "@volar/vue-typescript": "1.2.0" - }, - "bin": { - "vue-tsc": "bin/vue-tsc.js" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - } - }, - "dependencies": { - "@babel/parser": { - "version": "7.21.4" - }, - "@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "dev": true, - "optional": true - }, - "@rollup/plugin-virtual": { - "version": "3.0.1", - "dev": true, - "requires": {} - }, - "@swc/core": { - "version": "1.3.51", - "dev": true, - "requires": { - "@swc/core-darwin-arm64": "1.3.51", - "@swc/core-darwin-x64": "1.3.51", - "@swc/core-linux-arm-gnueabihf": "1.3.51", - "@swc/core-linux-arm64-gnu": "1.3.51", - "@swc/core-linux-arm64-musl": "1.3.51", - "@swc/core-linux-x64-gnu": "1.3.51", - "@swc/core-linux-x64-musl": "1.3.51", - "@swc/core-win32-arm64-msvc": "1.3.51", - "@swc/core-win32-ia32-msvc": "1.3.51", - "@swc/core-win32-x64-msvc": "1.3.51" - } - }, - "@swc/core-win32-x64-msvc": { - "version": "1.3.51", - "dev": true, - "optional": true - }, - "@types/node": { - "version": "18.15.11", - "dev": true - }, - "@vitejs/plugin-vue": { - "version": "4.1.0", - "dev": true, - "requires": {} - }, - "@volar/language-core": { - "version": "1.3.0-alpha.0", - "dev": true, - "requires": { - "@volar/source-map": "1.3.0-alpha.0" - } - }, - "@volar/source-map": { - "version": "1.3.0-alpha.0", - "dev": true, - "requires": { - "muggle-string": "^0.2.2" - } - }, - "@volar/typescript": { - "version": "1.3.0-alpha.0", - "dev": true, - "requires": { - "@volar/language-core": "1.3.0-alpha.0" - } - }, - "@volar/vue-language-core": { - "version": "1.2.0", - "dev": true, - "requires": { - "@volar/language-core": "1.3.0-alpha.0", - "@volar/source-map": "1.3.0-alpha.0", - "@vue/compiler-dom": "^3.2.47", - "@vue/compiler-sfc": "^3.2.47", - "@vue/reactivity": "^3.2.47", - "@vue/shared": "^3.2.47", - "minimatch": "^6.1.6", - "muggle-string": "^0.2.2", - "vue-template-compiler": "^2.7.14" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "6.2.0", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@volar/vue-typescript": { - "version": "1.2.0", - "dev": true, - "requires": { - "@volar/typescript": "1.3.0-alpha.0", - "@volar/vue-language-core": "1.2.0" - } - }, - "@vue/compiler-core": { - "version": "3.2.47", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-dom": { - "version": "3.2.47", - "requires": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.47", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-ssr": { - "version": "3.2.47", - "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/devtools-api": { - "version": "6.5.0" - }, - "@vue/reactivity": { - "version": "3.2.47", - "requires": { - "@vue/shared": "3.2.47" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.47", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/runtime-core": { - "version": "3.2.47", - "requires": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/runtime-dom": { - "version": "3.2.47", - "requires": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" - } - }, - "@vue/server-renderer": { - "version": "3.2.47", - "requires": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/shared": { - "version": "3.2.47" - }, - "@vue/tsconfig": { - "version": "0.1.3", - "dev": true, - "requires": {} - }, - "ansi-styles": { - "version": "3.2.1", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "asynckit": { - "version": "0.4.0" - }, - "available-typed-arrays": { - "version": "1.0.5", - "dev": true - }, - "axios": { - "version": "1.6.0", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "call-bind": { - "version": "1.0.2", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "chalk": { - "version": "2.4.2", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "dev": true - }, - "cross-spawn": { - "version": "6.0.5", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "csstype": { - "version": "2.6.21" - }, - "de-indent": { - "version": "1.0.2", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0" - }, - "error-ex": { - "version": "1.3.2", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.21.2", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - } - }, - "es-set-tostringtag": { - "version": "2.0.1", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "dev": true - }, - "estree-walker": { - "version": "2.0.2" - }, - "follow-redirects": { - "version": "1.15.2" - }, - "for-each": { - "version": "0.3.3", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "form-data": { - "version": "4.0.0", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functions-have-names": { - "version": "1.2.3", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.0", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "globalthis": { - "version": "1.0.3", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "gopd": { - "version": "1.0.1", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "dev": true - }, - "has": { - "version": "1.0.3", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-proto": { - "version": "1.0.1", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "he": { - "version": "1.2.0", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.9", - "dev": true - }, - "internal-slot": { - "version": "1.0.5", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "dev": true - }, - "is-core-module": { - "version": "2.12.0", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-regex": { - "version": "1.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-string": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.10", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "is-weakref": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "isexe": { - "version": "2.0.0", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "magic-string": { - "version": "0.25.9", - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "memorystream": { - "version": "0.3.1", - "dev": true - }, - "mime-db": { - "version": "1.52.0" - }, - "mime-types": { - "version": "2.1.35", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "muggle-string": { - "version": "0.2.2", - "dev": true - }, - "nanoid": { - "version": "3.3.6" - }, - "nice-try": { - "version": "1.0.5", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npm-run-all": { - "version": "4.1.5", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - } - }, - "object-inspect": { - "version": "1.12.3", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "parse-json": { - "version": "4.0.0", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-key": { - "version": "2.0.1", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "picocolors": { - "version": "1.0.0" - }, - "pidtree": { - "version": "0.3.1", - "dev": true - }, - "pify": { - "version": "3.0.0", - "dev": true - }, - "postcss": { - "version": "8.4.31", - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "proxy-from-env": { - "version": "1.1.0" - }, - "read-pkg": { - "version": "3.0.0", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "regexp.prototype.flags": { - "version": "1.5.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - } - }, - "resolve": { - "version": "1.22.2", - "dev": true, - "requires": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "safe-regex-test": { - "version": "1.0.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "semver": { - "version": "5.7.1", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "dev": true - }, - "shell-quote": { - "version": "1.8.1", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "source-map": { - "version": "0.6.1" - }, - "source-map-js": { - "version": "1.0.2" - }, - "sourcemap-codec": { - "version": "1.4.8" - }, - "spdx-correct": { - "version": "3.2.0", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "dev": true - }, - "string.prototype.padend": { - "version": "3.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trim": { - "version": "1.2.7", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.6", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimstart": { - "version": "1.0.6", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "strip-bom": { - "version": "3.0.0", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true - }, - "typed-array-length": { - "version": "1.0.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "typescript": { - "version": "4.8.4", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "uuid": { - "version": "9.0.0", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vite": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", - "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", - "dev": true, - "requires": { - "esbuild": "^0.18.10", - "fsevents": "~2.3.2", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - } - }, - "vite-plugin-top-level-await": { - "version": "1.3.0", - "dev": true, - "requires": { - "@rollup/plugin-virtual": "^3.0.1", - "@swc/core": "^1.3.10", - "uuid": "^9.0.0" - } - }, - "vite-plugin-wasm": { - "version": "3.2.2", - "dev": true, - "requires": {} - }, - "vue": { - "version": "3.2.47", - "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "vue-router": { - "version": "4.1.6", - "requires": { - "@vue/devtools-api": "^6.4.5" - } - }, - "vue-template-compiler": { - "version": "2.7.14", - "dev": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "vue-tsc": { - "version": "1.2.0", - "dev": true, - "requires": { - "@volar/vue-language-core": "1.2.0", - "@volar/vue-typescript": "1.2.0" - } - }, - "which": { - "version": "1.3.1", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-typed-array": { - "version": "1.1.9", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - } - } -} diff --git a/backend/middlewares/event/tests/test_event.rs b/backend/middlewares/event/tests/test_event.rs index 4b3b85ca2..8c9a480c7 100644 --- a/backend/middlewares/event/tests/test_event.rs +++ b/backend/middlewares/event/tests/test_event.rs @@ -8,12 +8,9 @@ use bios_mw_event::event_constants::DOMAIN_CODE; use bios_mw_event::event_initializer; use tardis::basic::dto::TardisContext; use tardis::basic::result::TardisResult; -use tardis::cluster::cluster_processor::set_local_node_id; use tardis::tokio::time::sleep; use tardis::{testcontainers, tokio, TardisFuns}; -mod test_event_with_event_code; -mod test_event_with_im; -mod test_event_without_mgr; + #[tokio::test(flavor = "multi_thread")] async fn test_event() -> TardisResult<()> { @@ -21,7 +18,6 @@ async fn test_event() -> TardisResult<()> { let docker = testcontainers::clients::Cli::default(); let _x = init_test_container::init(&docker, None).await?; - set_local_node_id(TardisFuns::field.nanoid()); init_data().await?; @@ -54,8 +50,5 @@ async fn init_data() -> TardisResult<()> { client.set_auth(&ctx)?; - test_event_without_mgr::test(&[&client]).await?; - test_event_with_event_code::test(&[&client]).await?; - test_event_with_im::test(&[&client]).await?; Ok(()) } diff --git a/backend/middlewares/event/tests/test_event_inmails.rs b/backend/middlewares/event/tests/test_event_inmails.rs deleted file mode 100644 index 834ea9ca2..000000000 --- a/backend/middlewares/event/tests/test_event_inmails.rs +++ /dev/null @@ -1,236 +0,0 @@ -use std::sync::Arc; -use std::time::Duration; - -use bios_basic::test::test_http_client::TestHttpClient; -use bios_mw_event::dto::event_dto::{EventListenerRegisterReq, EventListenerRegisterResp, EventMessageMgrWrap, EventTopicAddOrModifyReq}; -use serde::{Deserialize, Serialize}; -use tardis::basic::field::TrimString; -use tardis::basic::result::TardisResult; -use tardis::log::info; -use tardis::serde_json::json; -use tardis::web::tokio_tungstenite::tungstenite::Message; -use tardis::web::ws_processor::{TardisWebsocketMessage, TardisWebsocketMgrMessage, TardisWebsocketReq}; -use tardis::{rand, tardis_static, TardisFuns}; -use tokio::sync::Mutex; - -pub const USR_SK: &str = "ut001"; -pub const MGR_SK: &str = "mt001"; -pub const TOPIC_CODE: &str = "testinmails"; - -tardis_static! { - pub mailbox_alice: Arc>>; - pub mailbox_bob: Arc>>; - pub mailbox_clancy: Arc>>; -} - -pub enum Action<'a> { - Dm { peer: &'a str }, - Push { topic: &'a str }, - Broadcast {}, -} - -pub fn auth_action(from: &str, action: Action) -> bool { - match from { - "inmails/client/Alice" => match action { - Action::Dm { peer } => peer == "inmails/client/Bob", - Action::Push { topic } => topic == "publish", - Action::Broadcast {} => true, - }, - "inmails/client/Bob" => match action { - Action::Dm { peer } => peer == "inmails/client/Alice" || peer == "inmails/client/Clancy", - Action::Push { topic } => topic == "publish" || topic == "warning", - Action::Broadcast {} => false, - }, - "inmails/client/Clancy" => match action { - Action::Dm { peer } => peer == "inmails/client/Bob", - Action::Push { topic } => topic == "publish" || topic == "warning", - Action::Broadcast {} => false, - }, - _ => false, - } -} - -pub fn mgr_on_message(message: Message) -> Option { - let receive_msg = TardisFuns::json.str_to_obj::(message.to_string().as_str()).unwrap(); - let msg_id = receive_msg.msg_id.clone(); - dbg!(&receive_msg); - let mut ori_msg = TardisFuns::json.json_to_obj::(receive_msg.msg.clone()).unwrap(); - let from = ori_msg.ori_from_avatar.as_str(); - let Some(to) = ori_msg.ori_to_avatars.as_ref().and_then(|v| v.first()) else { - return None; - }; - let action = match receive_msg.event.as_deref() { - Some("dm") => Action::Dm { peer: to }, - Some("push") => Action::Push { topic: to }, - Some("broadcast") => { - ori_msg.ori_to_avatars = Some(vec!["inmails/broadcast".into()]); - Action::Broadcast {} - } - Some(_) => { - unreachable!("unknown event"); - } - None => { - return None; - } - }; - if auth_action(from, action) { - return Some(Message::text( - TardisFuns::json.obj_to_string(&receive_msg.into_req(msg_id, ori_msg.msg, ori_msg.ori_from_avatar, ori_msg.ori_to_avatars)).unwrap(), - )); - } - None -} -pub async fn test(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - prepare(http_clients).await?; - // mgr_node 1 - let url = add_listener(vec![], true, vec!["dm".into(), "push".into(), "broadcast".into()], http_clients).await?; - TardisFuns::ws_client(&url, |message| async move { mgr_on_message(message) }).await?; - - // mgr node 2 - let url = add_listener(vec![], true, vec!["todo".into()], http_clients).await?; - TardisFuns::ws_client(&url, |message| async move { mgr_on_message(message) }).await?; - - let url = add_listener( - vec!["inmails/client/alice".into()], - false, - vec!["dm".into(), "push".into(), "broadcast".into()], - http_clients, - ) - .await?; - let client_alice = TardisFuns::ws_client(&url, |message| async move { - info!("client alice receive message {message}"); - mailbox_alice().lock().await.push(TardisFuns::json.str_to_obj::(message.to_string().as_str()).unwrap()); - None - }) - .await?; - - let url = add_listener(vec!["inmails/client/bob".into()], false, vec!["dm".into(), "push".into(), "broadcast".into()], http_clients).await?; - let client_bob = TardisFuns::ws_client(&url, |message| async move { - info!("client bob receive message {message}"); - mailbox_bob().lock().await.push(TardisFuns::json.str_to_obj::(message.to_string().as_str()).unwrap()); - None - }) - .await?; - - let url = add_listener( - vec!["inmails/client/clancy".into(), "inmails/broadcast".into()], - false, - vec!["dm".into(), "push".into(), "broadcast".into()], - http_clients, - ) - .await?; - let client_clancy = TardisFuns::ws_client(&url, |message| async move { - info!("client clancy receive message {message}"); - mailbox_clancy().lock().await.push(TardisFuns::json.str_to_obj::(message.to_string().as_str()).unwrap()); - None - }) - .await?; - - client_bob - .send_obj(&TardisWebsocketReq { - to_avatars: Some(vec!["inmails/client/alice".into()]), - event: Some("dm".into()), - msg: TardisFuns::json.obj_to_json(&"hello bob").unwrap(), - from_avatar: "inmails/client/bob".into(), - ..Default::default() - }) - .await?; - tokio::time::sleep(Duration::from_secs(1)).await; - info!("{:?}", mailbox_alice().lock().await.pop()); - info!("{:?}", mailbox_alice().lock().await.pop()); - - // send to self should be none - client_bob - .send_obj(&TardisWebsocketReq { - to_avatars: Some(vec!["inmails/client/bob".into()]), - event: Some("dm".into()), - msg: TardisFuns::json - .obj_to_json(&InMails::Dm { - message: "halo".into(), - target: "uno".into(), - }) - .unwrap(), - from_avatar: "inmails/client/bob".into(), - ..Default::default() - }) - .await?; - tokio::time::sleep(Duration::from_secs(1)).await; - assert!(mailbox_bob().lock().await.pop().is_none()); - - // bob has no permission to send to a broadcast topic - client_bob - .send_obj(&TardisWebsocketReq { - to_avatars: None, - event: Some("broadcast".into()), - msg: json!("broadcast from bob"), - from_avatar: "inmails/client/bob".into(), - ..Default::default() - }) - .await?; - tokio::time::sleep(Duration::from_secs(1)).await; - assert!(mailbox_clancy().lock().await.pop().is_none()); - - // alice has permission to send to a broadcast topic - client_alice - .send_obj(&TardisWebsocketReq { - to_avatars: None, - event: Some("broadcast".into()), - msg: json!("broadcast from alice"), - from_avatar: "inmails/client/alice".into(), - ..Default::default() - }) - .await?; - tokio::time::sleep(Duration::from_secs(1)).await; - assert!(mailbox_clancy().lock().await.pop().is_none()); - Ok(()) -} - -async fn prepare(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let _: String = http_client - .post( - "/topic", - &EventTopicAddOrModifyReq { - code: TrimString(TOPIC_CODE), - name: TrimString("站内信".to_string()), - save_message: true, - need_mgr: true, - queue_size: 1024, - use_sk: Some(USR_SK.to_string()), - mgr_sk: Some(MGR_SK.to_string()), - }, - ) - .await; - Ok(()) -} - -async fn add_listener(avatars: Vec, mgr: bool, events: Vec, http_clients: &[&TestHttpClient]) -> TardisResult { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let resp: EventListenerRegisterResp = http_client - .post( - "/listener", - &EventListenerRegisterReq { - topic_code: TrimString(TOPIC_CODE), - topic_sk: if mgr { Some(MGR_SK.to_string()) } else { Some(USR_SK.to_string()) }, - events: if events.is_empty() { None } else { Some(events) }, - avatars, - subscribe_mode: !mgr, - }, - ) - .await; - Ok(resp.ws_addr) -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -struct EbWebsocketMessage { - pub content: String, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub enum InMails { - Subscribe { topic: String }, - Publish { topic: String, message: String }, - Dm { message: String, target: String }, -} diff --git a/backend/middlewares/event/tests/test_event_multi_node_server.rs b/backend/middlewares/event/tests/test_event_multi_node_server.rs deleted file mode 100644 index b2fecda67..000000000 --- a/backend/middlewares/event/tests/test_event_multi_node_server.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::env; -use std::time::Duration; - -use bios_basic::rbum::rbum_config::RbumConfig; -use bios_basic::test::test_http_client::TestHttpClient; -use bios_mw_event::event_constants::DOMAIN_CODE; -use bios_mw_event::event_initializer; -use tardis::basic::dto::TardisContext; -use tardis::basic::result::TardisResult; -use tardis::cluster::cluster_processor::set_local_node_id; -use tardis::test::test_container::TardisTestContainer; -use tardis::{testcontainers, tokio, TardisFuns}; - -use tokio::io::AsyncReadExt; -use tokio::process::Command; - -mod test_event_inmails; -mod test_event_with_event_code; -mod test_event_with_im; -mod test_event_without_mgr; -#[tokio::test(flavor = "multi_thread")] -async fn test_event() -> TardisResult<()> { - if let Ok(kind) = env::var("KIND") { - let db_url = env::var("DB").expect("DB is not set"); - let cache_url = env::var("CACHE").expect("CACHE is not set"); - let port = env::var("PORT").expect("PORT is not set").parse::().expect("invalid port"); - env::set_var("TARDIS_FW.DB.URL", &db_url); - env::set_var("TARDIS_FW.CACHE.URL", &cache_url); - env::set_var("PROFILE", port.to_string()); - server_side().await?; - } else { - env::set_var("RUST_LOG", "debug,tardis=trace,bios_mw_event=trace,test_event=trace,sqlx::query=off"); - let docker = testcontainers::clients::Cli::default(); - let reldb_container = TardisTestContainer::postgres_custom(None, &docker); - let port = reldb_container.get_host_port_ipv4(5432); - let db_url = format!("postgres://postgres:123456@127.0.0.1:{port}/test"); - env::set_var("TARDIS_FW.DB.URL", &db_url); - - let redis_container = TardisTestContainer::redis_custom(&docker); - let port = redis_container.get_host_port_ipv4(6379); - let redis_url = format!("redis://127.0.0.1:{port}/0"); - env::set_var("TARDIS_FW.CACHE.URL", &redis_url); - let program = env::current_exe()?; - for node_idx in 0..3 { - let program = program.clone(); - let db_url = db_url.clone(); - let redis_url = redis_url.clone(); - let port = 8080 + node_idx; - tokio::spawn(async move { - let mut child = if cfg!(target_os = "windows") { - Command::new("cmd") - .env("DB", &db_url) - .env("CACHE", &redis_url) - .env("PORT", port.to_string()) - .env("LS_COLORS", "rs=0:di=38;5;27:mh=44;38;5;15") - .env("KIND", "server") - .arg("/C") - .arg(program) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn()? - } else { - Command::new("sh") - .env("DB", &db_url) - .env("CACHE", &redis_url) - .env("PORT", port.to_string()) - .env("LS_COLORS", "rs=0:di=38;5;27:mh=44;38;5;15") - .env("KIND", "server") - .arg("-c") - .arg(program) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn()? - }; - let mut buf = [0; 1024]; - let mut err_buf = [0; 1024]; - let mut stdout = child.stdout.take().unwrap(); - let mut stderr = child.stderr.take().unwrap(); - loop { - tokio::select! { - result = stdout.read(&mut buf) => { - let size = result?; - if size != 0 { - println!("node[{node_idx}]/stdout:"); - println!("{}", String::from_utf8_lossy(&buf[..size])); - } - } - result = stderr.read(&mut err_buf) => { - let size = result?; - if size != 0 { - println!("node[{node_idx}]/stdout:"); - println!("{}", String::from_utf8_lossy(&err_buf[..size])); - } - } - exit_code = child.wait() => { - if let Ok(exit_code) = exit_code { - return TardisResult::Ok(exit_code.success()) - } else { - return TardisResult::Ok(false) - } - } - - }; - } - }); - tokio::time::sleep(Duration::from_secs(1)).await; - } - tokio::time::sleep(Duration::from_secs(15)).await; - client_side().await?; - } - - Ok(()) -} - -async fn server_side() -> TardisResult<()> { - TardisFuns::init(Some("tests/config")).await?; - set_local_node_id(TardisFuns::field.nanoid()); - // Initialize RBUM - let rbum_init_result = bios_basic::rbum::rbum_initializer::init(DOMAIN_CODE, RbumConfig::default()).await; - - let web_server = TardisFuns::web_server(); - // Initialize Event - event_initializer::init(web_server.as_ref()).await.expect("fail to initialize"); - web_server.start().await?; - web_server.await; - Ok(()) -} - -async fn client_side() -> TardisResult<()> { - TardisFuns::init(Some("tests/config")).await?; - - let ctx = TardisContext { - own_paths: "".to_string(), - ak: "".to_string(), - roles: vec![], - groups: vec![], - owner: "".to_string(), - ..Default::default() - }; - - // let mut client = TestHttpClient::new(format!("http://127.0.0.1:{}/{}",, DOMAIN_CODE)); - let client_set = [8080, 8081, 8082] - .into_iter() - .map(|port| { - let mut client = TestHttpClient::new(format!("http://127.0.0.1:{}/{}", port, DOMAIN_CODE)); - client.set_auth(&ctx).unwrap(); - client - }) - .collect::>(); - - // test_event_without_mgr::test(&client_set.iter().collect::>()).await?; - // test_event_with_event_code::test(&client_set.iter().collect::>()).await?; - // test_event_with_im::test(&client_set.iter().collect::>()).await?; - test_event_inmails::test(&client_set.iter().collect::>()).await?; - Ok(()) -} diff --git a/backend/middlewares/event/tests/test_event_with_event_code.rs b/backend/middlewares/event/tests/test_event_with_event_code.rs deleted file mode 100644 index 9cf48c490..000000000 --- a/backend/middlewares/event/tests/test_event_with_event_code.rs +++ /dev/null @@ -1,250 +0,0 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Duration; - -use bios_basic::test::test_http_client::TestHttpClient; -use bios_mw_event::dto::event_dto::{EventListenerRegisterReq, EventListenerRegisterResp, EventMessageMgrWrap, EventTopicAddOrModifyReq}; -use serde::{Deserialize, Serialize}; -use tardis::basic::field::TrimString; -use tardis::basic::result::TardisResult; -use tardis::serde_json::json; -use tardis::tokio::time::sleep; -use tardis::web::tokio_tungstenite::tungstenite::Message; -use tardis::web::ws_processor::{TardisWebsocketMessage, TardisWebsocketMgrMessage, TardisWebsocketReq, WS_SYSTEM_EVENT_AVATAR_ADD}; -use tardis::{rand, TardisFuns}; - -pub async fn test(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - static TEST_LOG_COUNTER: AtomicUsize = AtomicUsize::new(0); - static FEED_FROM_MGR_COUNTER: AtomicUsize = AtomicUsize::new(0); - static FEED_FROM_USER_COUNTER: AtomicUsize = AtomicUsize::new(0); - - prepare(http_clients).await?; - - // Register management listener - let url = add_listener(Vec::new(), true, vec![TrimString("test_log_append")], http_clients).await?; - let mgr_test_log_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let ori_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(ori_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - assert!(1 == 2); - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - assert!(1 == 2); - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed yyyy add" { - assert!(1 == 2); - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - let url = add_listener( - Vec::new(), - true, - vec![TrimString("feed_add".to_string()), TrimString(WS_SYSTEM_EVENT_AVATAR_ADD.to_string())], - http_clients, - ) - .await?; - let mgr_feed_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let msg_id = receive_msg.msg_id.clone(); - let ori_msg = TardisFuns::json.json_to_obj::(receive_msg.msg.clone()).unwrap(); - if receive_msg.event == Some(WS_SYSTEM_EVENT_AVATAR_ADD.to_string()) { - return Some(Message::text( - TardisFuns::json.obj_to_string(&receive_msg.into_req(msg_id, ori_msg.msg, ori_msg.ori_from_avatar, ori_msg.ori_to_avatars)).unwrap(), - )); - } - if receive_msg.event == Some("feed_add".to_string()) { - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - return Some(Message::text( - TardisFuns::json.obj_to_string(&receive_msg.into_req(msg_id, ori_msg.msg, ori_msg.ori_from_avatar, ori_msg.ori_to_avatars)).unwrap(), - )); - } - let raw_msg = TardisFuns::json.json_to_obj::(ori_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - assert!(1 == 2); - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - assert!(1 == 2); - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - // Register user listener - let url = add_listener(vec![TrimString("test_serv".to_string())], false, vec![], http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - assert!(1 == 2); - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed yyyy add" { - assert!(1 == 2); - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("test_serv".to_string()), TrimString("feed_serv".to_string())], false, vec![], http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed yyyy add" { - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("feed_serv".to_string())], false, vec![], http_clients).await?; - let feed1_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - assert!(1 == 2); - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed yyyy add" { - assert!(1 == 2); - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("others".to_string())], false, vec![], http_clients).await?; - let feed2_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "test xxxx" { - assert!(1 == 2); - TEST_LOG_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed xxxx add" { - FEED_FROM_MGR_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "feed yyyy add" { - FEED_FROM_USER_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - // send test log - mgr_test_log_client - .send_obj(&TardisWebsocketReq { - to_avatars: Some(vec!["test_serv".to_string()]), - event: Some("test_log_append".to_string()), - msg: TardisFuns::json.obj_to_json(&EbWebsocketMessage { content: "test xxxx".to_string() }).unwrap(), - ..Default::default() - }) - .await?; - - // add new avatar - feed2_client - .send_obj(&TardisWebsocketReq { - msg: json! {"feed_serv"}, - from_avatar: "others".to_string(), - event: Some(WS_SYSTEM_EVENT_AVATAR_ADD.to_string()), - ..Default::default() - }) - .await?; - sleep(Duration::from_millis(500)).await; - - // send feed from mgr - mgr_feed_client - .send_obj(&TardisWebsocketReq { - to_avatars: Some(vec!["feed_serv".to_string()]), - event: Some("feed_add".to_string()), - msg: TardisFuns::json - .obj_to_json(&EbWebsocketMessage { - content: "feed xxxx add".to_string(), - }) - .unwrap(), - ..Default::default() - }) - .await?; - - // send feed from user - feed1_client - .send_obj(&TardisWebsocketReq { - from_avatar: "feed_serv".to_string(), - to_avatars: Some(vec!["feed_serv".to_string()]), - event: Some("feed_add".to_string()), - msg: TardisFuns::json - .obj_to_json(&EbWebsocketMessage { - content: "feed yyyy add".to_string(), - }) - .unwrap(), - ..Default::default() - }) - .await?; - - sleep(Duration::from_millis(500)).await; - assert_eq!(TEST_LOG_COUNTER.load(Ordering::SeqCst), 2); - assert_eq!(FEED_FROM_MGR_COUNTER.load(Ordering::SeqCst), 3); - assert_eq!(FEED_FROM_USER_COUNTER.load(Ordering::SeqCst), 3); - Ok(()) -} - -async fn prepare(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let _: String = http_client - .post( - "/topic", - &EventTopicAddOrModifyReq { - code: TrimString("eb".to_string()), - name: TrimString("事件总线".to_string()), - save_message: true, - need_mgr: true, - queue_size: 1024, - use_sk: Some("ut001".to_string()), - mgr_sk: Some("mt001".to_string()), - }, - ) - .await; - Ok(()) -} - -async fn add_listener(avatars: Vec, mgr: bool, events: Vec, http_clients: &[&TestHttpClient]) -> TardisResult { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let resp: EventListenerRegisterResp = http_client - .post( - "/listener", - &EventListenerRegisterReq { - topic_code: TrimString("eb".to_string()), - topic_sk: if mgr { Some("mt001".to_string()) } else { Some("ut001".to_string()) }, - events: if events.is_empty() { None } else { Some(events) }, - avatars, - subscribe_mode: !mgr, - }, - ) - .await; - Ok(resp.ws_addr) -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -struct EbWebsocketMessage { - pub content: String, -} diff --git a/backend/middlewares/event/tests/test_event_with_im.rs b/backend/middlewares/event/tests/test_event_with_im.rs deleted file mode 100644 index c85923d39..000000000 --- a/backend/middlewares/event/tests/test_event_with_im.rs +++ /dev/null @@ -1,268 +0,0 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Duration; - -use bios_basic::test::test_http_client::TestHttpClient; -use bios_mw_event::dto::event_dto::{EventListenerRegisterReq, EventListenerRegisterResp, EventMessageMgrWrap, EventTopicAddOrModifyReq}; -use serde::{Deserialize, Serialize}; -use tardis::basic::field::TrimString; -use tardis::basic::result::TardisResult; -use tardis::tokio::time::sleep; -use tardis::web::tokio_tungstenite::tungstenite::Message; -use tardis::web::ws_processor::{TardisWebsocketMessage, TardisWebsocketMgrMessage, TardisWebsocketReq}; -use tardis::{rand, TardisFuns}; - -pub async fn test(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - static NOTIFY_COUNTER: AtomicUsize = AtomicUsize::new(0); - static U1_TO_U2_COUNTER: AtomicUsize = AtomicUsize::new(0); - static U2_TO_U1_COUNTER: AtomicUsize = AtomicUsize::new(0); - static TO_G1_COUNTER: AtomicUsize = AtomicUsize::new(0); - - prepare(http_clients).await?; - - // Register management listener - let url = add_listener(Vec::new(), true, http_clients).await?; - let mgr_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let msg_id = receive_msg.msg_id.clone(); - - let ori_msg = TardisFuns::json.json_to_obj::(receive_msg.msg.clone()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(ori_msg.msg.clone()).unwrap(); - if raw_msg.content == "系统升级" { - assert!(1 == 2); - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - Some(Message::text( - TardisFuns::json.obj_to_string(&receive_msg.into_req(msg_id, ori_msg.msg, ori_msg.ori_from_avatar, ori_msg.ori_to_avatars)).unwrap(), - )) - }) - .await?; - // Register user listener - let url = add_listener(vec![TrimString("user01".to_string()), TrimString("group01".to_string())], false, http_clients).await?; - let user01_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "系统升级" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - assert!(1 == 2); - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("user02".to_string())], false, http_clients).await?; - let user02_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "系统升级" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - assert!(1 == 2); - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - assert!(1 == 2); - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("user03".to_string()), TrimString("group01".to_string())], false, http_clients).await?; - let user03_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "系统升级" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - assert!(1 == 2); - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - assert!(1 == 2); - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - assert!(1 == 2); - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("user04".to_string()), TrimString("group01".to_string())], false, http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "系统升级" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - assert!(1 == 2); - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - assert!(1 == 2); - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - let url = add_listener(vec![TrimString("user04".to_string()), TrimString("group01".to_string())], false, http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - let raw_msg = TardisFuns::json.json_to_obj::(receive_msg.msg).unwrap(); - if raw_msg.content == "系统升级" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "你好" { - assert!(1 == 2); - U1_TO_U2_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "^_^" { - assert!(1 == 2); - U2_TO_U1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if raw_msg.content == "Hi" { - TO_G1_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - // notify - mgr_client - .send_obj(&TardisWebsocketReq { - msg: TardisFuns::json - .obj_to_json(&ImWebsocketMessage { - from: "管理员".to_string(), - content: "系统升级".to_string(), - }) - .unwrap(), - from_avatar: "_".to_string(), - to_avatars: None, - ..Default::default() - }) - .await?; - - // user01 send to user02 - user01_client - .send_obj(&TardisWebsocketReq { - msg: TardisFuns::json - .obj_to_json(&ImWebsocketMessage { - from: "用户1".to_string(), - content: "你好".to_string(), - }) - .unwrap(), - from_avatar: "user01".to_string(), - to_avatars: Some(vec!["user02".to_string()]), - ..Default::default() - }) - .await?; - - // user02 send to user01 - user02_client - .send_obj(&TardisWebsocketReq { - msg: TardisFuns::json - .obj_to_json(&ImWebsocketMessage { - from: "用户2".to_string(), - content: "^_^".to_string(), - }) - .unwrap(), - from_avatar: "user02".to_string(), - to_avatars: Some(vec!["user01".to_string()]), - ..Default::default() - }) - .await?; - - // user03 send to group01 - user03_client - .send_obj(&TardisWebsocketReq { - msg: TardisFuns::json - .obj_to_json(&ImWebsocketMessage { - from: "群组1".to_string(), - content: "Hi".to_string(), - }) - .unwrap(), - from_avatar: "user03".to_string(), - to_avatars: Some(vec!["group01".to_string()]), - ..Default::default() - }) - .await?; - - sleep(Duration::from_millis(500)).await; - assert_eq!(NOTIFY_COUNTER.load(Ordering::SeqCst), 5); - assert_eq!(U1_TO_U2_COUNTER.load(Ordering::SeqCst), 2); - assert_eq!(U2_TO_U1_COUNTER.load(Ordering::SeqCst), 2); - assert_eq!(TO_G1_COUNTER.load(Ordering::SeqCst), 4); - Ok(()) -} - -async fn prepare(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let _: String = http_client - .post( - "/topic", - &EventTopicAddOrModifyReq { - code: TrimString("im".to_string()), - name: TrimString("即时通讯".to_string()), - save_message: false, - need_mgr: true, - queue_size: 1024, - use_sk: Some("ut001".to_string()), - mgr_sk: Some("mt001".to_string()), - }, - ) - .await; - Ok(()) -} - -async fn add_listener(avatars: Vec, mgr: bool, http_clients: &[&TestHttpClient]) -> TardisResult { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let resp: EventListenerRegisterResp = http_client - .post( - "/listener", - &EventListenerRegisterReq { - topic_code: TrimString("im".to_string()), - topic_sk: if mgr { Some("mt001".to_string()) } else { Some("ut001".to_string()) }, - events: None, - avatars, - subscribe_mode: !mgr, - }, - ) - .await; - Ok(resp.ws_addr) -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -struct ImWebsocketMessage { - pub from: String, - pub content: String, -} diff --git a/backend/middlewares/event/tests/test_event_without_mgr.rs b/backend/middlewares/event/tests/test_event_without_mgr.rs deleted file mode 100644 index aa66a8980..000000000 --- a/backend/middlewares/event/tests/test_event_without_mgr.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Duration; - -use bios_basic::test::test_http_client::TestHttpClient; -use bios_mw_event::dto::event_dto::{EventListenerRegisterReq, EventListenerRegisterResp, EventTopicAddOrModifyReq}; -use tardis::basic::field::TrimString; -use tardis::basic::result::TardisResult; -use tardis::serde_json::json; -use tardis::tokio::time::sleep; -use tardis::web::tokio_tungstenite::tungstenite::Message; -use tardis::web::ws_processor::{TardisWebsocketMessage, TardisWebsocketReq}; -use tardis::{rand, TardisFuns}; - -pub async fn test(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - static NOTIFY_COUNTER: AtomicUsize = AtomicUsize::new(0); - - prepare(http_clients).await?; - - // Register user listener - let url = add_listener(vec![TrimString("doc001".to_string())], http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - if receive_msg.msg.get("block001").is_some() && receive_msg.msg.get("block001").unwrap().as_str().unwrap() == "xnfeonfd" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if receive_msg.msg.get("block002").is_some() && receive_msg.msg.get("block002").unwrap().as_str().unwrap() == "哈哈" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - let url = add_listener(vec![TrimString("doc001".to_string())], http_clients).await?; - TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - if receive_msg.msg.get("block001").is_some() && receive_msg.msg.get("block001").unwrap().as_str().unwrap() == "xnfeonfd" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if receive_msg.msg.get("block002").is_some() && receive_msg.msg.get("block002").unwrap().as_str().unwrap() == "哈哈" { - assert!(1 == 2); - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - Some(Message::text( - TardisFuns::json - .obj_to_string(&TardisWebsocketReq { - msg: json!({ - "block002": "哈哈" - }), - from_avatar: "doc001".to_string(), - ..Default::default() - }) - .unwrap(), - )) - }) - .await?; - - let url = add_listener(vec![TrimString("doc001".to_string())], http_clients).await?; - let doc01_client = TardisFuns::ws_client(&url, move |msg| async move { - let receive_msg = TardisFuns::json.str_to_obj::(msg.to_string().as_str()).unwrap(); - if receive_msg.msg.get("block001").is_some() && receive_msg.msg.get("block001").unwrap().as_str().unwrap() == "xnfeonfd" { - assert!(1 == 2); - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - if receive_msg.msg.get("block002").is_some() && receive_msg.msg.get("block002").unwrap().as_str().unwrap() == "哈哈" { - NOTIFY_COUNTER.fetch_add(1, Ordering::SeqCst); - } - None - }) - .await?; - - // notify - doc01_client - .send_obj(&TardisWebsocketReq { - msg: json!({ - "block001": "xnfeonfd" - }), - from_avatar: "doc001".to_string(), - ..Default::default() - }) - .await?; - - sleep(Duration::from_millis(500)).await; - assert_eq!(NOTIFY_COUNTER.load(Ordering::SeqCst), 4); - Ok(()) -} - -async fn prepare(http_clients: &[&TestHttpClient]) -> TardisResult<()> { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let _: String = http_client - .post( - "/topic", - &EventTopicAddOrModifyReq { - code: TrimString("coo".to_string()), - name: TrimString("协作".to_string()), - save_message: false, - need_mgr: false, - queue_size: 1024, - use_sk: Some("ut001".to_string()), - mgr_sk: None, - }, - ) - .await; - Ok(()) -} - -async fn add_listener(avatars: Vec, http_clients: &[&TestHttpClient]) -> TardisResult { - let idx = rand::random::() % http_clients.len(); - let http_client = &http_clients[idx]; - let resp: EventListenerRegisterResp = http_client - .post( - "/listener", - &EventListenerRegisterReq { - topic_code: TrimString("coo".to_string()), - topic_sk: Some("ut001".to_string()), - events: None, - avatars, - subscribe_mode: true, - }, - ) - .await; - Ok(resp.ws_addr) -} diff --git a/backend/middlewares/flow/src/event.rs b/backend/middlewares/flow/src/event.rs index 0b1e83441..5a485e7fb 100644 --- a/backend/middlewares/flow/src/event.rs +++ b/backend/middlewares/flow/src/event.rs @@ -1,19 +1,27 @@ use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter}, + event_client::{asteroid_mq::prelude::TopicCode, get_topic, mq_error, ContextHandler}, flow_client::{event::FLOW_AVATAR, FlowFrontChangeReq, FlowPostChangeReq}, }; -use tardis::basic::{dto::TardisContext, result::TardisResult}; +use tardis::basic::{dto::TardisContext, error::TardisError, result::TardisResult}; use crate::{flow_constants::get_tardis_inst, serv::flow_event_serv::FlowEventServ}; +pub const FLOW_TOPIC: TopicCode = TopicCode::const_new("flow"); -pub fn flow_register_events() { - if let Some(event_center) = BiosEventCenter::worker_queue() { - event_center.subscribe(handle_front_change); - event_center.subscribe(handle_post_change); - event_center.add_avatar(FLOW_AVATAR); +pub async fn handle_events() -> TardisResult<()> { + use bios_sdk_invoke::clients::event_client::asteroid_mq::prelude::*; + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic + .create_endpoint([Interest::new("*")]) + .await + .map_err(mq_error)? + .create_event_loop() + .with_handler(ContextHandler(handle_front_change)) + .with_handler(ContextHandler(handle_post_change)) + .spawn(); } -} + Ok(()) +} async fn handle_front_change(req: FlowFrontChangeReq, ctx: TardisContext) -> TardisResult<()> { let funs = get_tardis_inst(); FlowEventServ::do_front_change(&req.inst_id, &ctx, &funs).await?; diff --git a/backend/middlewares/flow/src/flow_config.rs b/backend/middlewares/flow/src/flow_config.rs index 375dba624..79c0ead9a 100644 --- a/backend/middlewares/flow/src/flow_config.rs +++ b/backend/middlewares/flow/src/flow_config.rs @@ -1,5 +1,5 @@ use bios_basic::{process::ci_processor::AppKeyConfig, rbum::rbum_config::RbumConfig}; -use bios_sdk_invoke::{clients::event_client::EventTopicConfig, invoke_config::InvokeConfig}; +use bios_sdk_invoke::{invoke_config::InvokeConfig}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use std::{fmt::Debug, sync::Mutex}; @@ -13,8 +13,7 @@ pub struct FlowConfig { pub rbum: RbumConfig, pub invoke: InvokeConfig, pub app_key: AppKeyConfig, - pub event: Option, - pub search_event: Option, + pub search_url: String, pub log_url: String, pub iam_url: String, @@ -26,8 +25,6 @@ impl Default for FlowConfig { rbum: Default::default(), invoke: Default::default(), app_key: Default::default(), - event: None, - search_event: None, search_url: "http://127.0.0.1:8080/spi-search".to_string(), log_url: "http://127.0.0.1:8080/spi-log".to_string(), iam_url: "http://127.0.0.1:8080/iam".to_string(), diff --git a/backend/middlewares/flow/src/flow_initializer.rs b/backend/middlewares/flow/src/flow_initializer.rs index 9e95f7f6b..2f6855a6b 100644 --- a/backend/middlewares/flow/src/flow_initializer.rs +++ b/backend/middlewares/flow/src/flow_initializer.rs @@ -37,7 +37,7 @@ use crate::{ flow_state_dto::FlowSysStateKind, flow_transition_dto::{FlowTransitionDoubleCheckInfo, FlowTransitionInitInfo}, }, - event::flow_register_events, + event::handle_events, flow_config::{BasicInfo, FlowBasicInfoManager, FlowConfig}, flow_constants, serv::{ @@ -50,7 +50,7 @@ use crate::{ pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { let funs = flow_constants::get_tardis_inst(); init_db(funs).await?; - flow_register_events(); + handle_events().await?; init_api(web_server).await } diff --git a/backend/middlewares/flow/src/serv/clients/search_client.rs b/backend/middlewares/flow/src/serv/clients/search_client.rs index e22c84343..7562f0f6c 100644 --- a/backend/middlewares/flow/src/serv/clients/search_client.rs +++ b/backend/middlewares/flow/src/serv/clients/search_client.rs @@ -2,7 +2,11 @@ use std::vec; use bios_basic::rbum::{dto::rbum_filer_dto::RbumBasicFilterReq, helper::rbum_scope_helper, rbum_enumeration::RbumScopeLevelKind, serv::rbum_item_serv::RbumItemCrudOperation}; use bios_sdk_invoke::{ - clients::{event_client::BiosEventCenter, flow_client::event::FLOW_AVATAR, spi_search_client::SpiSearchClient}, + clients::{ + event_client::{get_topic, EventCenterClient, SPI_RPC_TOPIC}, + flow_client::event::FLOW_AVATAR, + spi_search_client::SpiSearchClient, + }, dto::search_item_dto::{SearchItemAddReq, SearchItemModifyReq, SearchItemVisitKeysReq}, }; use serde_json::json; @@ -111,8 +115,8 @@ impl FlowSearchClient { }), kv_disable: None, }; - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center.modify_item_and_name(FLOW_AVATAR, SEARCH_TAG, &key, &modify_req, funs, ctx).await?; + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.modify_item_and_name(SEARCH_TAG, &key, &modify_req, funs, ctx).await?; } else { SpiSearchClient::modify_item_and_name(SEARCH_TAG, &key, &modify_req, funs, ctx).await?; } @@ -143,8 +147,8 @@ impl FlowSearchClient { }), kv_disable: None, }; - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center.add_item_and_name(FLOW_AVATAR, &add_req, Some(model_resp.name.clone()), funs, ctx).await?; + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.add_item_and_name(&add_req, Some(model_resp.name.clone()), funs, ctx).await?; } else { SpiSearchClient::add_item_and_name(&add_req, Some(model_resp.name.clone()), funs, ctx).await?; } @@ -154,9 +158,9 @@ impl FlowSearchClient { // model 全局搜索删除埋点方法 pub async fn delete_model_search(model_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center.delete_item_and_name(FLOW_AVATAR, SEARCH_TAG, model_id, funs, ctx).await?; - } else { + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.delete_item_and_name(SEARCH_TAG, model_id, funs, ctx).await?; + } else { SpiSearchClient::delete_item_and_name(SEARCH_TAG, model_id, funs, ctx).await?; } Ok(()) diff --git a/backend/middlewares/flow/src/serv/flow_event_serv.rs b/backend/middlewares/flow/src/serv/flow_event_serv.rs index f69bde395..7109eda90 100644 --- a/backend/middlewares/flow/src/serv/flow_event_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_event_serv.rs @@ -3,8 +3,7 @@ use std::{collections::HashMap, str::FromStr}; use async_recursion::async_recursion; use bios_basic::rbum::dto::rbum_filer_dto::RbumBasicFilterReq; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter, EventExt}, - flow_client::{event::FLOW_AVATAR, FlowFrontChangeReq}, + event_client::{get_topic, mq_error, EventAttributeExt}, flow_client::{event::FLOW_AVATAR, FlowFrontChangeReq} }; use rust_decimal::Decimal; use serde_json::{json, Value}; @@ -29,7 +28,7 @@ use crate::{ FlowTransitionActionByStateChangeInfo, FlowTransitionActionByVarChangeInfoChangedKind, FlowTransitionActionChangeAgg, FlowTransitionActionChangeKind, FlowTransitionFrontActionInfo, FlowTransitionFrontActionRightValue, StateChangeConditionOp, TagRelKind, }, - }, + }, event::FLOW_TOPIC, }; use super::{flow_external_serv::FlowExternalServ, flow_inst_serv::FlowInstServ, flow_model_serv::FlowModelServ, flow_state_serv::FlowStateServ}; @@ -314,8 +313,8 @@ impl FlowEventServ { funs, ) .await?; - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center.publish(FlowFrontChangeReq { inst_id: inst_id.to_string() }.with_source(FLOW_AVATAR).inject_context(funs, ctx)).await?; + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic.send_event(FlowFrontChangeReq { inst_id: inst_id.to_string() }.inject_context(funs, ctx).json()).await.map_err(mq_error)?; } else { FlowEventServ::do_front_change(&inst_id, ctx, funs).await?; } @@ -369,16 +368,9 @@ impl FlowEventServ { funs, ) .await?; - if let Some(event_center) = BiosEventCenter::worker_queue() { - event_center - .publish( - FlowFrontChangeReq { - inst_id: flow_inst_detail.id.to_string(), - } - .with_source(FLOW_AVATAR) - .inject_context(funs, ctx), - ) - .await?; + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic.send_event(FlowFrontChangeReq { inst_id: flow_inst_detail.id.to_string() }.inject_context(funs, ctx).json()).await.map_err(mq_error)?; + } else { FlowEventServ::do_front_change(&flow_inst_detail.id, ctx, funs).await?; } diff --git a/backend/middlewares/flow/src/serv/flow_inst_serv.rs b/backend/middlewares/flow/src/serv/flow_inst_serv.rs index 38ff87321..a125b0bea 100644 --- a/backend/middlewares/flow/src/serv/flow_inst_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_inst_serv.rs @@ -15,7 +15,7 @@ use bios_basic::{ }, }; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter, EventExt}, + event_client::{get_topic, mq_error, EventAttributeExt}, flow_client::{event::FLOW_AVATAR, FlowFrontChangeReq, FlowPostChangeReq}, }; use itertools::Itertools; @@ -48,6 +48,7 @@ use crate::{ flow_transition_dto::{FlowTransitionDetailResp, FlowTransitionFrontActionInfo}, flow_var_dto::FillType, }, + event::FLOW_TOPIC, flow_constants, serv::{flow_model_serv::FlowModelServ, flow_state_serv::FlowStateServ}, }; @@ -747,17 +748,18 @@ impl FlowInstServ { } pub async fn handle_post_changes(inst_id: &str, transition_id: &str, ctx: &TardisContext, funs: &TardisFunsInst) -> TardisResult<()> { - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center - .publish( + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic + .send_event( FlowPostChangeReq { inst_id: inst_id.to_string(), next_transition_id: transition_id.to_string(), } - .with_source(FLOW_AVATAR) - .inject_context(funs, ctx), + .inject_context(funs, ctx) + .json(), ) - .await?; + .await + .map_err(mq_error)?; } else { FlowEventServ::do_post_change(inst_id, transition_id, ctx, funs).await?; } @@ -765,8 +767,8 @@ impl FlowInstServ { } pub async fn handle_front_changes(inst_id: &str, ctx: &TardisContext, funs: &TardisFunsInst) -> TardisResult<()> { - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center.publish(FlowFrontChangeReq { inst_id: inst_id.to_string() }.with_source(FLOW_AVATAR).inject_context(funs, ctx)).await?; + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic.send_event(FlowFrontChangeReq { inst_id: inst_id.to_string() }.inject_context(funs, ctx).json()).await.map_err(mq_error)?; } else { FlowEventServ::do_front_change(inst_id, ctx, funs).await?; } @@ -1070,16 +1072,18 @@ impl FlowInstServ { funs.commit().await?; let funs = flow_constants::get_tardis_inst(); - if let Some(event_center) = TardisFuns::store().get_singleton::() { - event_center - .publish( + + if let Some(topic) = get_topic(&FLOW_TOPIC) { + topic + .send_event( FlowFrontChangeReq { inst_id: flow_inst_id.to_string(), } - .with_source(FLOW_AVATAR) - .inject_context(&funs, ctx), + .inject_context(&funs, ctx) + .json(), ) - .await?; + .await + .map_err(mq_error)?; } else { FlowEventServ::do_front_change(flow_inst_id, ctx, &funs).await?; } diff --git a/backend/middlewares/schedule/src/schedule_config.rs b/backend/middlewares/schedule/src/schedule_config.rs index a618d8ae6..9d5af025b 100644 --- a/backend/middlewares/schedule/src/schedule_config.rs +++ b/backend/middlewares/schedule/src/schedule_config.rs @@ -1,5 +1,5 @@ use bios_basic::{process::ci_processor::AppKeyConfig, rbum::rbum_config::RbumConfig}; -use bios_sdk_invoke::{clients::event_client::EventTopicConfig, invoke_config::InvokeConfig}; +use bios_sdk_invoke::{invoke_config::InvokeConfig}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -15,7 +15,6 @@ pub struct ScheduleConfig { pub distributed_lock_expire_sec: u32, /// The expire key prefix of the distributed lock, default "schedual:job:lock:" pub distributed_lock_key_prefix: String, - pub event: EventTopicConfig, } impl Default for ScheduleConfig { @@ -28,7 +27,6 @@ impl Default for ScheduleConfig { cache_key_job_changed_timer_sec: 30, distributed_lock_expire_sec: 30, distributed_lock_key_prefix: "schedual:job:lock:".to_string(), - event: EventTopicConfig::default(), } } } diff --git a/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event.rs b/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event.rs index 8be077ad4..f04264393 100644 --- a/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event.rs +++ b/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event.rs @@ -1,5 +1,6 @@ use std::sync::Arc; -mod schedule_event; +// we may change to this implements someday +// mod schedule_event; mod spi_log; pub use spi_log::*; use tardis::{basic::dto::TardisContext, futures::Stream, serde_json::Value, TardisFunsInst}; diff --git a/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event/schedule_event.rs b/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event/schedule_event.rs index 64ba3e7e0..fb2bb625f 100644 --- a/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event/schedule_event.rs +++ b/backend/middlewares/schedule/src/serv/schedule_job_serv_v2/event/schedule_event.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, Event, EventCenter, EventExt}, spi_log_client::LogItemAddReq, }; use serde::{Deserialize, Serialize}; diff --git a/backend/services/bios-all/Cargo.toml b/backend/services/bios-all/Cargo.toml index 8e4755f3b..b3485b650 100644 --- a/backend/services/bios-all/Cargo.toml +++ b/backend/services/bios-all/Cargo.toml @@ -43,4 +43,4 @@ bios-client-hwsms = { path = "../../../frontend/clients/hwsms", features = [ ] } # see [issue](https://github.com/kube-rs/kube/issues/1486) -json-patch = { version = "=1.2.0" } +json-patch = { version = "=1.2.0" } \ No newline at end of file diff --git a/backend/services/bios-all/Dockerfile b/backend/services/bios-all/Dockerfile index 9e74eb59a..97b8e70c9 100644 --- a/backend/services/bios-all/Dockerfile +++ b/backend/services/bios-all/Dockerfile @@ -33,6 +33,7 @@ EXPOSE 8080 EXPOSE 8848 # for nacos grpc EXPOSE 9848 +EXPOSE 9559 EXPOSE 10389 CMD ["./bios-serv-all"] diff --git a/backend/services/bios-all/build.sh b/backend/services/bios-all/build.sh index 0af837d02..907fb704c 100644 --- a/backend/services/bios-all/build.sh +++ b/backend/services/bios-all/build.sh @@ -1,7 +1,8 @@ REPO=$TAG + ### Rust if [ -z "$TARGET" ]; then - echo "Please choose an target:" + echo "Please choose a target:" target_options=("debug" "release") select opt in "${target_options[@]}" do @@ -44,4 +45,35 @@ if [ -z "$TAG" ]; then read TAG fi docker build -t $TAG ./ -docker push $TAG + + +if [ -z "$OUTPUT" ]; then + echo "Where do you want to output:" + target_options=("tar" "push") + select opt in "${target_options[@]}" + do + case $opt in + "tar") + echo "tar" + OUTPUT="tar" + break + ;; + "push") + echo "push" + OUTPUT="push" + break + ;; + *) + echo "invalid option" + ;; + esac + done +fi + + +if [ -z "$OUTPUT" ] || [ "$OUTPUT" = "tar" ]; then + docker save $TAG -o bios-serv-all.tar +else + docker push $TAG +fi + diff --git a/backend/services/bios-all/src/initializer.rs b/backend/services/bios-all/src/initializer.rs index 00f9e8235..d92fc59c8 100644 --- a/backend/services/bios-all/src/initializer.rs +++ b/backend/services/bios-all/src/initializer.rs @@ -1,10 +1,8 @@ use bios_reach::reach_send_channel::SendChannelMap; use tardis::basic::result::TardisResult; -use tardis::web::web_server::status_api::TardisStatusApi; use tardis::web::web_server::TardisWebServer; pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { - web_server.add_module("_tardis", TardisStatusApi).await; bios_mw_event::event_initializer::init(web_server).await?; bios_auth::auth_initializer::init(web_server).await?; @@ -31,4 +29,4 @@ pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { bios_mw_flow::flow_initializer::init(web_server).await?; Ok(()) -} +} \ No newline at end of file diff --git a/backend/spi/spi-conf/Cargo.toml b/backend/spi/spi-conf/Cargo.toml index 4205aa1a5..638b77e11 100644 --- a/backend/spi/spi-conf/Cargo.toml +++ b/backend/spi/spi-conf/Cargo.toml @@ -29,9 +29,9 @@ tardis = { workspace = true, features = [ bios-basic = { path = "../../basic", features = ["default"] } lazy_static = { workspace = true } jsonwebtoken = "9" -poem-grpc = { version = "0.3", optional = true } -prost-types = "0.12" -prost = "0.12" +poem-grpc = { version = "0.4", optional = true } +prost-types = "0.13" +prost = "0.13" strum = { version = "0.26", features = ["derive"] } tokio-stream = { version = "0.1.14", features = ["sync"] } bios-sdk-invoke = { path = "../../../frontend/sdks/invoke", features = [ diff --git a/backend/spi/spi-conf/src/api/nacos/grpc/proto.rs b/backend/spi/spi-conf/src/api/nacos/grpc/proto.rs index ba4bafecf..6c85c2f84 100644 --- a/backend/spi/spi-conf/src/api/nacos/grpc/proto.rs +++ b/backend/spi/spi-conf/src/api/nacos/grpc/proto.rs @@ -1,6 +1,7 @@ -use tardis::poem_grpc; +use tardis::{poem_grpc}; use tardis::web::poem; +use crate::api; // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -10,7 +11,10 @@ pub struct Metadata { #[prost(string, tag = "8")] pub client_ip: ::prost::alloc::string::String, #[prost(map = "string, string", tag = "7")] - pub headers: ::std::collections::HashMap<::prost::alloc::string::String, ::prost::alloc::string::String>, + pub headers: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -34,7 +38,12 @@ pub struct ConfigQueryRequest { } #[allow(unused_imports)] pub trait Request: Send + Sync + 'static { - fn request(&self, request: poem_grpc::Request) -> impl ::std::future::Future, poem_grpc::Status>> + Send; + fn request( + &self, + request: poem_grpc::Request, + ) -> impl ::std::future::Future< + Output = ::std::result::Result, poem_grpc::Status>, + > + Send; } #[allow(unused_imports)] #[derive(Clone)] @@ -52,36 +61,51 @@ impl poem::IntoEndpoint for RequestServer { type Endpoint = poem::endpoint::BoxEndpoint<'static, poem::Response>; #[allow(clippy::redundant_clone)] #[allow(clippy::let_and_return)] - fn into_endpoint(self) -> Self::Endpoint { + fn into_endpoint(self) -> as tardis::web::poem::IntoEndpoint>::Endpoint { use poem::endpoint::EndpointExt; let mut route = poem::Route::new(); #[allow(non_camel_case_types)] struct RequestrequestService(::std::sync::Arc); - impl poem_grpc::service::UnaryService for RequestrequestService { + impl poem_grpc::service::UnaryService + for RequestrequestService { type Response = Payload; - async fn call(&self, request: poem_grpc::Request) -> Result, poem_grpc::Status> { + async fn call( + &self, + request: poem_grpc::Request, + ) -> Result, poem_grpc::Status> { self.0.request(request).await } } - route = route.at( - "/request", - poem::endpoint::make({ - let svc = self.0.clone(); - move |req| { - let svc = svc.clone(); - async move { - let codec = as ::std::default::Default>::default(); - poem_grpc::server::GrpcServer::new(codec).unary(RequestrequestService(svc.clone()), req).await + route = route + .at( + "/request", + poem::endpoint::make({ + let svc = self.0.clone(); + move |req| { + let svc = svc.clone(); + async move { + let codec = as ::std::default::Default>::default(); + poem_grpc::server::GrpcServer::new(codec) + .unary(RequestrequestService(svc.clone()), req) + .await + } } + }), + ); + let ep = route + .before(|req| async move { + if req.version() != poem::http::Version::HTTP_2 { + return Err( + poem::Error::from_status( + poem::http::StatusCode::HTTP_VERSION_NOT_SUPPORTED, + ), + ); } - }), - ); - let ep = route.before(|req| async move { - if req.version() != poem::http::Version::HTTP_2 { - return Err(poem::Error::from_status(poem::http::StatusCode::HTTP_VERSION_NOT_SUPPORTED)); - } - Ok(req) - }); + Ok(req) + }); ep.boxed() } } @@ -90,7 +114,12 @@ pub trait BiRequestStream: Send + Sync + 'static { fn request_bi_stream( &self, request: poem_grpc::Request>, - ) -> impl ::std::future::Future>, poem_grpc::Status>> + Send; + ) -> impl ::std::future::Future< + Output = ::std::result::Result< + poem_grpc::Response>, + poem_grpc::Status, + >, + > + Send; } #[allow(unused_imports)] #[derive(Clone)] @@ -113,34 +142,54 @@ impl poem::IntoEndpoint for BiRequestStreamServer { let mut route = poem::Route::new(); #[allow(non_camel_case_types)] struct BiRequestStreamrequest_bi_streamService(::std::sync::Arc); - impl poem_grpc::service::BidirectionalStreamingService for BiRequestStreamrequest_bi_streamService { + impl< + T: BiRequestStream, + > poem_grpc::service::BidirectionalStreamingService + for BiRequestStreamrequest_bi_streamService { type Response = Payload; async fn call( &self, request: poem_grpc::Request>, - ) -> Result>, poem_grpc::Status> { + ) -> Result< + poem_grpc::Response>, + poem_grpc::Status, + > { self.0.request_bi_stream(request).await } } - route = route.at( - "/requestBiStream", - poem::endpoint::make({ - let svc = self.0.clone(); - move |req| { - let svc = svc.clone(); - async move { - let codec = as ::std::default::Default>::default(); - poem_grpc::server::GrpcServer::new(codec).bidirectional_streaming(BiRequestStreamrequest_bi_streamService(svc.clone()), req).await + route = route + .at( + "/requestBiStream", + poem::endpoint::make({ + let svc = self.0.clone(); + move |req| { + let svc = svc.clone(); + async move { + let codec = as ::std::default::Default>::default(); + poem_grpc::server::GrpcServer::new(codec) + .bidirectional_streaming( + BiRequestStreamrequest_bi_streamService(svc.clone()), + req, + ) + .await + } } + }), + ); + let ep = route + .before(|req| async move { + if req.version() != poem::http::Version::HTTP_2 { + return Err( + poem::Error::from_status( + poem::http::StatusCode::HTTP_VERSION_NOT_SUPPORTED, + ), + ); } - }), - ); - let ep = route.before(|req| async move { - if req.version() != poem::http::Version::HTTP_2 { - return Err(poem::Error::from_status(poem::http::StatusCode::HTTP_VERSION_NOT_SUPPORTED)); - } - Ok(req) - }); + Ok(req) + }); ep.boxed() } } diff --git a/backend/spi/spi-conf/src/serv/placeholder.rs b/backend/spi/spi-conf/src/serv/placeholder.rs index 7ad3830bb..5653fc508 100644 --- a/backend/spi/spi-conf/src/serv/placeholder.rs +++ b/backend/spi/spi-conf/src/serv/placeholder.rs @@ -13,6 +13,7 @@ use crate::conf_config::ConfConfig; tardis_static! { pub place_holder_regex: Regex = Regex::new(r"\$CERT\{(.+)\}").expect("invalid content replace regex"); + pub env_place_holder_regex: Regex = Regex::new(r"\$ENV\{(.+)\}").expect("invalid content replace regex"); } #[derive(Debug, Clone, Copy)] diff --git a/backend/spi/spi-kv/src/event.rs b/backend/spi/spi-kv/src/event.rs index 70d5263b5..df49adfee 100644 --- a/backend/spi/spi-kv/src/event.rs +++ b/backend/spi/spi-kv/src/event.rs @@ -1,7 +1,7 @@ use crate::{get_tardis_inst, serv}; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter}, - spi_kv_client::{event::KV_AVATAR, KvItemAddOrModifyReq, KvItemDeleteReq}, + event_client::{get_topic, mq_error, ContextHandler, SPI_RPC_TOPIC}, + spi_kv_client::{KvItemAddOrModifyReq, KvItemDeleteReq}, }; use tardis::basic::result::TardisResult; use tardis::{ @@ -21,10 +21,18 @@ async fn handle_kv_delete_event(req: KvItemDeleteReq, ctx: TardisContext) -> Tar serv::kv_item_serv::delete_item(req.key.trim().to_string(), &funs, &ctx).await?; Ok(()) } -pub fn register_kv_events() { - if let Some(bios_event_center) = BiosEventCenter::worker_queue() { - bios_event_center.subscribe(handle_kv_add_event); - bios_event_center.subscribe(handle_kv_delete_event); - bios_event_center.add_avatar(KV_AVATAR); - } + +pub async fn handle_events() -> TardisResult<()> { + use bios_sdk_invoke::clients::event_client::asteroid_mq::prelude::*; + let topic = get_topic(&SPI_RPC_TOPIC).expect("topic not initialized"); + + topic + .create_endpoint([Interest::new("kv/*")]) + .await + .map_err(mq_error)? + .create_event_loop() + .with_handler(ContextHandler(handle_kv_add_event)) + .with_handler(ContextHandler(handle_kv_delete_event)) + .spawn(); + Ok(()) } diff --git a/backend/spi/spi-kv/src/kv_initializer.rs b/backend/spi/spi-kv/src/kv_initializer.rs index f62c5c55e..7c6dc257a 100644 --- a/backend/spi/spi-kv/src/kv_initializer.rs +++ b/backend/spi/spi-kv/src/kv_initializer.rs @@ -11,7 +11,7 @@ use crate::{api::ci::kv_ci_item_api, kv_config::KvConfig, kv_constants::DOMAIN_C pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { info!("[BIOS.KV] Module initializing"); let mut funs = crate::get_tardis_inst(); - crate::event::register_kv_events(); + crate::event::handle_events().await?; bios_basic::rbum::rbum_initializer::init(funs.module_code(), funs.conf::().rbum.clone()).await?; funs.begin().await?; let ctx = spi_initializer::init(DOMAIN_CODE, &funs).await?; diff --git a/backend/spi/spi-log/src/event.rs b/backend/spi/spi-log/src/event.rs index 29c8ce85e..e2e36a4b7 100644 --- a/backend/spi/spi-log/src/event.rs +++ b/backend/spi/spi-log/src/event.rs @@ -1,7 +1,6 @@ use crate::{log_initializer::get_tardis_inst, serv}; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter}, - spi_log_client::{event::LOG_AVATAR, LogItemAddReq}, + event_client::{get_topic, mq_error, ContextHandler, SPI_RPC_TOPIC}, spi_log_client::{event::LOG_AVATAR, LogItemAddReq} }; use tardis::{ basic::{dto::TardisContext, result::TardisResult}, @@ -14,9 +13,17 @@ async fn handle_add_event(req: LogItemAddReq, ctx: TardisContext) -> TardisResul serv::log_item_serv::add(&mut req.into(), &funs, &ctx).await?; Ok(()) } -pub fn register_log_event() { - if let Some(bios_event_center) = BiosEventCenter::worker_queue() { - bios_event_center.subscribe(handle_add_event); - bios_event_center.add_avatar(LOG_AVATAR); - } -} + +pub async fn handle_events() -> TardisResult<()> { + use bios_sdk_invoke::clients::event_client::asteroid_mq::prelude::*; + let topic = get_topic(&SPI_RPC_TOPIC).expect("topic not initialized"); + + topic + .create_endpoint([Interest::new("log/*")]) + .await + .map_err(mq_error)? + .create_event_loop() + .with_handler(ContextHandler(handle_add_event)) + .spawn(); + Ok(()) +} \ No newline at end of file diff --git a/backend/spi/spi-log/src/log_config.rs b/backend/spi/spi-log/src/log_config.rs index 22323b9ec..dcb950a46 100644 --- a/backend/spi/spi-log/src/log_config.rs +++ b/backend/spi/spi-log/src/log_config.rs @@ -1,13 +1,11 @@ use bios_basic::rbum::rbum_config::RbumConfig; -use bios_sdk_invoke::clients::event_client::EventTopicConfig; use serde::{Deserialize, Serialize}; use std::fmt::Debug; #[derive(Debug, Serialize, Deserialize, Default, Clone)] #[serde(default)] pub struct LogConfig { - pub rbum: RbumConfig, - pub event: Option, + pub rbum: RbumConfig } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/backend/spi/spi-log/src/log_initializer.rs b/backend/spi/spi-log/src/log_initializer.rs index 7fcb964c8..932141bb6 100644 --- a/backend/spi/spi-log/src/log_initializer.rs +++ b/backend/spi/spi-log/src/log_initializer.rs @@ -16,7 +16,7 @@ pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { let ctx = spi_initializer::init(DOMAIN_CODE, &funs).await?; init_db(&funs, &ctx).await?; funs.commit().await?; - crate::event::register_log_event(); + crate::event::handle_events().await?; init_api(web_server).await?; info!("[BIOS.Log] Module initialized"); Ok(()) diff --git a/backend/spi/spi-search/src/event.rs b/backend/spi/spi-search/src/event.rs index 8fb7f94ca..ff4a892fa 100644 --- a/backend/spi/spi-search/src/event.rs +++ b/backend/spi/spi-search/src/event.rs @@ -1,7 +1,7 @@ use bios_sdk_invoke::{ clients::{ - event_client::{BiosEventCenter, EventCenter}, - spi_search_client::event::SEARCH_AVATAR, + event_client::{get_topic, mq_error,ContextHandler, SPI_RPC_TOPIC}, + }, dto::search_item_dto::{SearchEventItemDeleteReq, SearchEventItemModifyReq, SearchItemAddReq}, }; @@ -28,11 +28,18 @@ async fn handle_delete_event(req: SearchEventItemDeleteReq, ctx: TardisContext) Ok(()) } -pub(crate) fn register_search_events() { - if let Some(bios_event_center) = BiosEventCenter::worker_queue() { - bios_event_center.subscribe(handle_modify_event); - bios_event_center.subscribe(handle_add_event); - bios_event_center.subscribe(handle_delete_event); - bios_event_center.add_avatar(SEARCH_AVATAR); - } -} +pub async fn handle_events() -> TardisResult<()> { + use bios_sdk_invoke::clients::event_client::asteroid_mq::prelude::*; + let topic = get_topic(&SPI_RPC_TOPIC).expect("topic not initialized"); + + topic + .create_endpoint([Interest::new("search/*")]) + .await + .map_err(mq_error)? + .create_event_loop() + .with_handler(ContextHandler(handle_modify_event)) + .with_handler(ContextHandler(handle_add_event)) + .with_handler(ContextHandler(handle_delete_event)) + .spawn(); + Ok(()) +} \ No newline at end of file diff --git a/backend/spi/spi-search/src/search_config.rs b/backend/spi/spi-search/src/search_config.rs index 37b3ebb7a..577922405 100644 --- a/backend/spi/spi-search/src/search_config.rs +++ b/backend/spi/spi-search/src/search_config.rs @@ -1,5 +1,4 @@ use bios_basic::rbum::rbum_config::RbumConfig; -use bios_sdk_invoke::clients::event_client::EventTopicConfig; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -7,7 +6,6 @@ use std::fmt::Debug; #[serde(default)] pub struct SearchConfig { pub rbum: RbumConfig, - pub event: Option, pub split_strategy_rule_config: SplitStrategyRuleConfig, } diff --git a/backend/spi/spi-search/src/search_initializer.rs b/backend/spi/spi-search/src/search_initializer.rs index 70d73184f..9388a203a 100644 --- a/backend/spi/spi-search/src/search_initializer.rs +++ b/backend/spi/spi-search/src/search_initializer.rs @@ -11,7 +11,7 @@ use crate::{api::ci::search_ci_item_api, search_config::SearchConfig, search_con pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { info!("[BIOS.Search] Module initializing"); let mut funs = crate::get_tardis_inst(); - crate::event::register_search_events(); + crate::event::handle_events().await?; bios_basic::rbum::rbum_initializer::init(funs.module_code(), funs.conf::().rbum.clone()).await?; funs.begin().await?; let ctx = spi_initializer::init(DOMAIN_CODE, &funs).await?; diff --git a/backend/supports/iam/src/basic/serv/clients/iam_log_client.rs b/backend/supports/iam/src/basic/serv/clients/iam_log_client.rs index 060843905..449caf1df 100644 --- a/backend/supports/iam/src/basic/serv/clients/iam_log_client.rs +++ b/backend/supports/iam/src/basic/serv/clients/iam_log_client.rs @@ -6,16 +6,13 @@ use bios_basic::{ }, }; use bios_sdk_invoke::clients::{ - event_client::{BiosEventCenter, EventCenter, EventExt}, + event_client::{get_topic, mq_error, EventAttributeExt, SPI_RPC_TOPIC}, spi_log_client::{LogItemAddReq, SpiLogClient}, }; use serde::Serialize; use tardis::{ - basic::{dto::TardisContext, result::TardisResult}, - chrono::{DateTime, Utc}, - serde_json::json, - tokio, TardisFuns, TardisFunsInst, + basic::{dto::TardisContext, result::TardisResult}, chrono::{DateTime, Utc}, futures::TryFutureExt, serde_json::json, tokio, TardisFuns, TardisFunsInst }; use crate::{ @@ -150,8 +147,8 @@ impl IamLogClient { owner, own_paths, }; - if let Some(ws_client) = BiosEventCenter::worker_queue() { - ws_client.publish(add_req.with_source(IAM_AVATAR).inject_context(funs, ctx)).await?; + if let Some(topic) = get_topic(&SPI_RPC_TOPIC) { + topic.send_event(add_req.inject_context(funs, ctx).json()).map_err(mq_error).await?; } else { SpiLogClient::add(&add_req, funs, ctx).await?; } diff --git a/backend/supports/iam/src/basic/serv/clients/iam_search_client.rs b/backend/supports/iam/src/basic/serv/clients/iam_search_client.rs index 919bd498a..e14d05814 100644 --- a/backend/supports/iam/src/basic/serv/clients/iam_search_client.rs +++ b/backend/supports/iam/src/basic/serv/clients/iam_search_client.rs @@ -2,7 +2,10 @@ use std::collections::HashSet; use bios_basic::rbum::{dto::rbum_filer_dto::RbumBasicFilterReq, serv::rbum_item_serv::RbumItemCrudOperation}; use bios_sdk_invoke::{ - clients::{event_client::BiosEventCenter, spi_search_client::SpiSearchClient}, + clients::{ + event_client::{get_topic, EventCenterClient, SPI_RPC_TOPIC}, + spi_search_client::SpiSearchClient, + }, dto::search_item_dto::{SearchItemAddReq, SearchItemModifyReq, SearchItemVisitKeysReq}, }; use itertools::Itertools; @@ -182,8 +185,8 @@ impl IamSearchClient { }), kv_disable: Some(account_resp.disabled), }; - if let Some(event_center) = BiosEventCenter::worker_queue() { - event_center.modify_item_and_name(IAM_AVATAR, &tag, &key, &modify_req, funs, ctx).await?; + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.modify_item_and_name(&tag, &key, &modify_req, funs, ctx).await?; } else { SpiSearchClient::modify_item_and_name(&tag, &key, &modify_req, funs, ctx).await?; } @@ -228,8 +231,8 @@ impl IamSearchClient { }), kv_disable: Some(account_resp.disabled), }; - if let Some(event_center) = BiosEventCenter::worker_queue() { - event_center.add_item_and_name(IAM_AVATAR, &add_req, Some(account_resp.name), funs, ctx).await?; + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.add_item_and_name(&add_req, Some(account_resp.name), funs, ctx).await?; } else { SpiSearchClient::add_item_and_name(&add_req, Some(account_resp.name), funs, ctx).await?; } @@ -240,8 +243,8 @@ impl IamSearchClient { // account 全局搜索删除埋点方法 pub async fn delete_account_search(account_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { let tag = funs.conf::().spi.search_account_tag.clone(); - if let Some(event_center) = BiosEventCenter::worker_queue() { - event_center.delete_item_and_name(IAM_AVATAR, &tag, account_id, funs, ctx).await?; + if let Some(_topic) = get_topic(&SPI_RPC_TOPIC) { + EventCenterClient { topic_code: SPI_RPC_TOPIC }.delete_item_and_name( &tag, account_id, funs, ctx).await?; } else { SpiSearchClient::delete_item_and_name(&tag, account_id, funs, ctx).await?; } diff --git a/backend/supports/iam/src/iam_config.rs b/backend/supports/iam/src/iam_config.rs index d84b8d038..c5da9d0bc 100644 --- a/backend/supports/iam/src/iam_config.rs +++ b/backend/supports/iam/src/iam_config.rs @@ -1,7 +1,6 @@ use std::fmt::Debug; use std::sync::Mutex; -use bios_sdk_invoke::clients::event_client::EventTopicConfig; use bios_sdk_invoke::invoke_config::InvokeConfig; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -18,10 +17,6 @@ use tardis::web::poem::http::HeaderName; pub struct IamConfig { pub rbum: RbumConfig, pub in_event: bool, - pub iam_event_bus: EventTopicConfig, - pub iam_send_event_bus: EventTopicConfig, - pub log_event: EventTopicConfig, - pub search_event: EventTopicConfig, pub invoke: InvokeConfig, // token -> (token_kind, account_id) // accessToken(token_kind = TokenOauth2) -> (token_kind, rel_iam_item_id, ak, SetCateIds) @@ -146,10 +141,6 @@ impl Default for IamConfig { IamConfig { rbum: Default::default(), in_event: false, - iam_event_bus: EventTopicConfig::default(), - iam_send_event_bus: EventTopicConfig::default(), - log_event: EventTopicConfig::default(), - search_event: EventTopicConfig::default(), invoke: InvokeConfig::default(), cache_key_token_info_: "iam:cache:token:info:".to_string(), cache_key_aksk_info_: "iam:cache:aksk:info:".to_string(), diff --git a/frontend/sdks/invoke/Cargo.toml b/frontend/sdks/invoke/Cargo.toml index 032b307ac..8f97e8884 100644 --- a/frontend/sdks/invoke/Cargo.toml +++ b/frontend/sdks/invoke/Cargo.toml @@ -37,6 +37,7 @@ tardis = { workspace = true, features = [ ] } simple-invoke-client-macro = { path = "../simple-invoke-client-macro", optional = true } crossbeam = "0.8" +asteroid-mq = { workspace = true, features = ["cluster-k8s", "json"] } [dev-dependencies] tardis = { workspace = true, features = ["test"] } simple-invoke-client-macro = { path = "../simple-invoke-client-macro" } @@ -44,3 +45,4 @@ simple-invoke-client-macro = { path = "../simple-invoke-client-macro" } [[test]] name = "test_macros" required-features = ["macro"] + diff --git a/frontend/sdks/invoke/src/clients/event_client.rs b/frontend/sdks/invoke/src/clients/event_client.rs index e7c54d6b8..99413793c 100644 --- a/frontend/sdks/invoke/src/clients/event_client.rs +++ b/frontend/sdks/invoke/src/clients/event_client.rs @@ -1,25 +1,11 @@ -use std::{ - collections::HashMap, - future::Future, - iter, - marker::PhantomData, - pin::Pin, - sync::{Arc, OnceLock}, - time::Duration, -}; +use std::{future::Future, iter, marker::PhantomData}; -use crossbeam::sync::ShardedLock; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use tardis::{ - basic::{component::ComponentKey, dto::TardisContext, error::TardisError, result::TardisResult}, - log::{debug, trace, warn}, - serde_json, tokio, + basic::{dto::TardisContext, error::TardisError, result::TardisResult}, web::{ poem_openapi::{self, Object}, - tokio_tungstenite::tungstenite::Message, web_resp::{TardisResp, Void}, - ws_client::TardisWSClient, - ws_processor::{TardisWebsocketMessage, TardisWebsocketReq}, }, TardisFuns, TardisFunsInst, }; @@ -114,406 +100,31 @@ pub struct EventTopicAddOrModifyReq { pub mgr_sk: Option, } -/****************************************************************************************************************** - * Event Client - ******************************************************************************************************************/ - -// GLOBAL EVENT BUS -pub const TOPIC_BIOS_WORKER_QUEUE: &str = "bios/worker-queue"; -pub const TOPIC_BIOS_PUB_SUB: &str = "bios/pub-sub"; -pub const TOPIC_PUBLIC: &str = "public"; - -#[derive(Serialize, Deserialize, Debug, Default, Clone)] -#[serde(default)] -pub struct EventTopicConfig { - pub topic_code: String, - pub topic_sk: Option, - pub events: Option>, - pub avatars: Vec, - pub subscribe_mode: bool, - pub base_url: String, - pub in_event: bool, -} - -impl From for EventListenerRegisterReq { - fn from(val: EventTopicConfig) -> Self { - EventListenerRegisterReq { - topic_code: val.topic_code, - topic_sk: val.topic_sk, - events: val.events, - avatars: val.avatars, - subscribe_mode: val.subscribe_mode, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(default)] -pub struct EventCenterConfig { - pub base_url: String, - pub topic_sk: String, - pub topic_code: String, - /// The phrase "subscribe" here is **extremely** bad. - /// - /// The difference between subscribe and not subscribe is actually - /// the difference between a pub/sub system and a worker queue. - /// - /// We may need to change this to a more meaningful name. - pub subscribe: bool, - pub avatars: Vec, -} - -impl Default for EventCenterConfig { - fn default() -> Self { - Self { - base_url: "http://localhost:8080".to_string(), - topic_sk: String::default(), - topic_code: TOPIC_BIOS_WORKER_QUEUE.to_string(), - subscribe: false, - avatars: vec![], - } - } -} -type WsEventCenterHandler = dyn Fn(serde_json::Value) -> Pin> + Send>> + Send + Sync; -type WsHandlersMap = HashMap<&'static str, Vec>>; - -#[derive(Clone)] -struct WsEventCenter { - cfg: Arc, - handlers: Arc>, - avatars: Arc>>, - ws_client: Arc>, -} - -impl From for WsEventCenter { - fn from(cfg: EventCenterConfig) -> Self { - Self { - avatars: Arc::new(ShardedLock::new(cfg.avatars.clone())), - cfg: Arc::new(cfg), - handlers: Arc::new(ShardedLock::new(HashMap::new())), - ws_client: Arc::new(OnceLock::new()), - } - } -} - -impl From> for WsEventCenter { - fn from(cfg: Arc) -> Self { - Self { - avatars: Arc::new(ShardedLock::new(cfg.avatars.clone())), - handlers: Arc::new(ShardedLock::new(HashMap::new())), - ws_client: Arc::new(OnceLock::new()), - cfg, - } - } -} - -impl std::fmt::Debug for WsEventCenter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let handlers_key = self.handlers.read().expect("should never be poisoned").iter().map(|(k, v)| (*k, v.len())).collect::>(); - f.debug_struct("WsEventCenter").field("handlers", &handlers_key).field("ws_client", &self.ws_client).finish() - } -} - -impl EventCenter for WsEventCenter { - fn init(&self) -> TardisResult<()> { - if self.ws_client.get().is_some() { - return Ok(()); - } - let this = self.clone(); - const RETRY_INTERVAL: Duration = Duration::from_secs(1); - tokio::spawn(async move { - let config = this.cfg.clone(); - let url = config.base_url.as_str(); - let funs = TardisFuns::inst("", None); - // wait for web server to start - loop { - if TardisFuns::web_server().is_running().await { - break; - } else { - tokio::task::yield_now().await - } - } - let events = this.handlers.read().expect("never poisoned").keys().map(|s| String::from(*s)).collect::>(); - let avatars = this.avatars.read().expect("never poisoned").clone(); - let client = EventClient::new(url, &funs); - let resp = client - .register(&EventListenerRegisterReq { - topic_code: config.topic_code.to_string(), - topic_sk: Some(config.topic_sk.clone()), - events: Some(events), - avatars, - subscribe_mode: config.subscribe, - }) - .await - .expect("fail to register event center"); - let ws_client = loop { - let ws_client = { - let this = this.clone(); - TardisFuns::ws_client(&resp.ws_addr, move |message| { - let this = this.clone(); - async move { - let Message::Text(text) = message else { return None }; - let Ok(TardisWebsocketMessage { msg, event, .. }) = TardisFuns::json.str_to_obj(&text) else { - return None; - }; - if let Some(evt) = event { - let evt: Arc = Arc::from(evt); - let handlers = { this.handlers.read().expect("never poisoned").get(evt.as_ref()).cloned().unwrap_or_default() }; - for h in handlers { - let evt = evt.clone(); - let msg = msg.clone(); - tokio::spawn(async move { - let result = (h)(msg.clone()).await; - if let Err(e) = result { - warn!("encounter an error when processing event [{evt}]: {e}"); - } - }); - } - } - None - } - }) - .await - }; - match ws_client { - Ok(ws_client) => break ws_client, - Err(e) => { - warn!("fail to connect event center {e}"); - tokio::time::sleep(RETRY_INTERVAL).await; - continue; - } - } - }; - this.ws_client.get_or_init(|| ws_client); - loop { - if let Err(e) = this.ws_client.get().expect("should be initialized").reconnect().await { - warn!("ws client fails to reconnect server {e}"); - tokio::time::sleep(RETRY_INTERVAL).await; - } - } - }); - Ok(()) - } - - async fn publish(&self, event: E) -> TardisResult<()> { - trace!("[EventCenter] publish event [{code}]: {req:?}", code = E::CODE, req = event); - if let Some(client) = self.ws_client.get() { - client - .send_obj(&TardisWebsocketReq { - msg_id: event.id(), - msg: TardisFuns::json.obj_to_json(&event)?, - from_avatar: event.source(), - to_avatars: event.targets(), - event: Some(E::CODE.to_string()), - ignore_self: Some(false), - ..Default::default() - }) - .await - } else { - Err(TardisError::internal_error("event center not initialized", "")) - } - } - - fn subscribe>(&self, handler: H) { - let wrapped_handler: Arc = Arc::new(move |value: serde_json::Value| { - let handler = handler.clone(); - Box::pin(async move { - trace!("[EventCenter] handling event [{code}]: {req}", code = H::Event::CODE, req = value); - let event: H::Event = serde_json::from_value(value).map_err(|e| TardisError::internal_error(&format!("can't deserialize event message: {e}"), ""))?; - handler.handle(event).await - }) - }); - let key = H::Event::CODE; - self.handlers.write().expect("never poisoned").entry(key).or_default().push(wrapped_handler); - } -} - -pub trait EventCenter { - fn init(&self) -> TardisResult<()>; - fn publish(&self, event: E) -> impl Future>; - fn subscribe>(&self, handler: H); -} - -impl EventCenter for Arc -where - T: EventCenter, -{ - fn init(&self) -> TardisResult<()> { - T::init(self) - } - - fn publish(&self, event: E) -> impl Future> { - self.as_ref().publish(event) - } - - fn subscribe>(&self, handler: H) { - self.as_ref().subscribe(handler) - } -} -#[derive(Debug, Clone)] -pub struct BiosEventCenter { - inner: WsEventCenter, +#[derive(Debug, Serialize, Deserialize)] +pub struct ContextEvent { + pub ctx: TardisContext, + pub event: T, } -impl BiosEventCenter { - pub fn add_avatar(&self, avatar: impl Into) { - self.inner.avatars.write().expect("never poisoned").push(avatar.into()); - } - pub fn from_config(config: EventCenterConfig) -> Self { - Self { - inner: WsEventCenter::from(config), - } - } - pub fn from_domain(domain: &str) -> Self { - #[derive(Deserialize)] - struct EventConfigView { - event_center: EventCenterConfig, - } - let cfg = TardisFuns::cs_config::(domain); +impl ContextEvent { + pub fn from_funs(funs: &TardisFunsInst, event: T) -> Self { Self { - inner: WsEventCenter::from(cfg.event_center.clone()), + ctx: TardisContext { + ak: funs.invoke_conf_spi_app_id(), + ..Default::default() + }, + event, } } - #[deprecated = "There's no global instance by now..."] - pub fn global() -> Option { - TardisFuns::store().get_singleton::() - } - #[inline(always)] - pub fn worker_queue() -> Option { - TardisFuns::store().get(TOPIC_BIOS_WORKER_QUEUE.as_bytes()) - } - #[inline(always)] - pub fn set_as_worker_queue(&self) { - TardisFuns::store().insert(ComponentKey::named(TOPIC_BIOS_WORKER_QUEUE.as_bytes()), self.clone()); - } - #[inline(always)] - pub fn pub_sub() -> Option { - TardisFuns::store().get(TOPIC_BIOS_PUB_SUB.as_bytes()) - } - #[inline(always)] - pub fn set_pub_sub(self) { - TardisFuns::store().insert(ComponentKey::named(TOPIC_BIOS_PUB_SUB.as_bytes()), self); - } - #[inline(always)] - pub fn public() -> Option { - TardisFuns::store().get(TOPIC_PUBLIC.as_bytes()) - } - #[inline(always)] - pub fn set_public(self) { - TardisFuns::store().insert(ComponentKey::named(TOPIC_PUBLIC.as_bytes()), self); - } -} - -impl EventCenter for BiosEventCenter { - /// 异步初始化,启动一个初始化任务,将会在webserver加载后运行 - fn init(&self) -> TardisResult<()> { - self.inner.init() - } - - /// 发布事件 - async fn publish(&self, event: E) -> TardisResult<()> { - self.inner.publish(event).await - } - - /// 订阅事件 - fn subscribe>(&self, handler: H) { - debug!("subscribe event handler for event [{}]", H::Event::CODE); - self.inner.subscribe(handler); - } } -/****************************************************************************************************************** - * Event Trait - ******************************************************************************************************************/ - -pub trait Event: Serialize + DeserializeOwned + std::fmt::Debug { - const CODE: &'static str; - fn source(&self) -> String { - String::default() - } - fn targets(&self) -> Option> { - Self::CODE.split_once('/').map(|(service, _)| vec![service.to_string()]) - } - fn id(&self) -> Option { - None - } -} -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct WithSource { - #[serde(flatten)] - inner: E, - #[serde(skip)] - source: String, -} - -impl Event for WithSource -where - E: Event, -{ - const CODE: &'static str = E::CODE; - fn source(&self) -> String { - self.source.clone() - } - fn targets(&self) -> Option> { - self.inner.targets() - } - fn id(&self) -> Option { - self.inner.id() - } -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct WithTargets { - #[serde(flatten)] - inner: E, - #[serde(skip)] - targets: Option>, -} - -impl Event for WithTargets +impl asteroid_mq::prelude::EventAttribute for ContextEvent where - E: Event, + T: asteroid_mq::prelude::EventAttribute, { - const CODE: &'static str = E::CODE; - fn source(&self) -> String { - self.inner.source() - } - fn targets(&self) -> Option> { - self.targets.clone() - } - fn id(&self) -> Option { - self.inner.id() - } -} - -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct WithId { - #[serde(flatten)] - inner: E, - #[serde(skip)] - id: Option, -} - -impl Event for WithId -where - E: Event, -{ - const CODE: &'static str = E::CODE; - fn source(&self) -> String { - self.inner.source() - } - fn targets(&self) -> Option> { - self.inner.targets() - } - fn id(&self) -> Option { - self.id.clone() - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ContextEvent { - pub ctx: TardisContext, - pub event: T, + const BROADCAST: bool = T::BROADCAST; + const EXPECT_ACK_KIND: asteroid_mq::prelude::MessageAckExpectKind = T::EXPECT_ACK_KIND; + const SUBJECT: asteroid_mq::prelude::Subject = T::SUBJECT; } impl ContextEvent { @@ -523,111 +134,71 @@ impl ContextEvent { } } -impl Event for ContextEvent { - const CODE: &'static str = E::CODE; - #[inline(always)] - fn source(&self) -> String { - self.event.source() - } - #[inline(always)] - fn targets(&self) -> Option> { - self.event.targets() - } +/// Adapter for event with a tardis context +#[derive(Debug, Clone)] +pub struct FnContextEventHandler(PhantomData); +use asteroid_mq::{ + event_handler::json::Json, + prelude::{EventAttribute, Topic, TopicCode}, +}; +#[derive(Debug, Clone)] +pub struct ContextHandler(pub F); +pub struct EventCenterClient { + pub topic_code: TopicCode, } -pub trait EventExt { - #[inline(always)] - fn with_source(self, source: impl Into) -> WithSource - where - Self: Sized, - { - WithSource { - inner: self, - source: source.into(), - } - } - #[inline(always)] - fn with_targets(self, targets: impl Into>>) -> WithTargets - where - Self: Sized, - { - WithTargets { - inner: self, - targets: targets.into(), - } - } - #[inline(always)] - fn with_context(self, ctx: TardisContext) -> ContextEvent - where - Self: Sized, - { - ContextEvent { ctx, event: self } + +impl EventCenterClient { + pub fn get_topic(&self) -> TardisResult { + mq_node().get_topic(&self.topic_code).ok_or_else(|| TardisError::internal_error(&self.topic_code.to_string(), "topic-not-initialized")) } - #[inline(always)] +} +pub trait EventAttributeExt: EventAttribute { fn inject_context(self, funs: &TardisFunsInst, ctx: &TardisContext) -> ContextEvent where Self: Sized, { - ContextEvent { - ctx: funs.invoke_conf_inject_context(ctx), - event: self, - } - } - #[inline(always)] - fn with_id(self, id: Option) -> WithId - where - Self: Sized, - { - WithId { inner: self, id } + let mut ctx = ctx.clone(); + ctx.ak = funs.invoke_conf_spi_app_id(); + ContextEvent { ctx, event: self } } - #[inline(always)] - fn with_nanoid(self) -> WithId + fn json(self) -> Json where - Self: Sized, + Self: Serialize + DeserializeOwned, { - WithId { - inner: self, - id: Some(TardisFuns::field.nanoid()), - } + Json(self) } } -impl EventExt for E where E: Event {} - -/****************************************************************************************************************** - * Event Handler - ******************************************************************************************************************/ +impl EventAttributeExt for T where T: EventAttribute {} -pub trait EventHandler: Clone + Sync + Send + 'static { - type Event: Event; - fn handle(self, event: Self::Event) -> impl Future> + Send; -} -/// Adapter for event without a tardis context -#[derive(Debug, Clone)] -pub struct FnEventHandler(PhantomData); -impl EventHandler> for F +impl asteroid_mq::event_handler::Handler> for ContextHandler where - E: Event, - F: Fn(E) -> Fut + Clone + Send + Sync + 'static, + Json>: asteroid_mq::event_handler::Event, + E: Serialize + DeserializeOwned + Send, + F: Fn(E, TardisContext) -> Fut + Clone + Send + Sync + 'static, Fut: Future> + Send, { - type Event = E; - fn handle(self, event: E) -> impl Future> + Send { - (self)(event) + type Event = Json>; + type Error = TardisError; + fn handle(self, event: Json>) -> impl Future> + Send { + let (ctx, evt) = event.0.unpack(); + (self.0)(evt, ctx) } } -/// Adapter for event with a tardis context -#[derive(Debug, Clone)] -pub struct FnContextEventHandler(PhantomData); -impl EventHandler> for F -where - ContextEvent: Event, - F: Fn(E, TardisContext) -> Fut + Clone + Send + Sync + 'static, - Fut: Future> + Send, -{ - type Event = ContextEvent; - fn handle(self, event: ContextEvent) -> impl Future> + Send { - let (ctx, evt) = event.unpack(); - (self)(evt, ctx) - } +pub fn mq_node() -> asteroid_mq::prelude::Node { + TardisFuns::store().get_singleton::().expect("mq node not initialized") +} +pub fn mq_node_opt() -> Option { + TardisFuns::store().get_singleton::() +} +pub fn get_topic(code: &TopicCode) -> Option { + mq_node_opt()?.get_topic(code) +} +pub const SPI_RPC_TOPIC: TopicCode = TopicCode::const_new("spi"); + + +pub fn mq_error(err: asteroid_mq::Error) -> TardisError { + TardisError::internal_error(&err.to_string(), "mq-error") } +pub use asteroid_mq; diff --git a/frontend/sdks/invoke/src/clients/flow_client.rs b/frontend/sdks/invoke/src/clients/flow_client.rs index 0a90cc97b..86a582074 100644 --- a/frontend/sdks/invoke/src/clients/flow_client.rs +++ b/frontend/sdks/invoke/src/clients/flow_client.rs @@ -1,24 +1,19 @@ use serde::{Deserialize, Serialize}; pub mod event { - use crate::clients::event_client::Event; + use asteroid_mq::prelude::*; + use super::{FlowFrontChangeReq, FlowPostChangeReq}; pub const FLOW_AVATAR: &str = "flow"; pub const EVENT_FRONT_CHANGE: &str = "flow/front_change"; pub const EVENT_POST_CHANGE: &str = "flow/post_change"; - impl Event for FlowFrontChangeReq { - const CODE: &'static str = EVENT_FRONT_CHANGE; - fn targets(&self) -> Option> { - Some(vec![FLOW_AVATAR.to_string()]) - } + impl EventAttribute for FlowFrontChangeReq { + const SUBJECT: Subject = Subject::const_new(b"flow/front_change"); } - impl Event for FlowPostChangeReq { - const CODE: &'static str = EVENT_POST_CHANGE; - fn targets(&self) -> Option> { - Some(vec![FLOW_AVATAR.to_string()]) - } + impl EventAttribute for FlowPostChangeReq { + const SUBJECT: Subject = Subject::const_new(b"flow/post_change"); } } diff --git a/frontend/sdks/invoke/src/clients/spi_kv_client.rs b/frontend/sdks/invoke/src/clients/spi_kv_client.rs index f7b35ea66..8dc29d2be 100644 --- a/frontend/sdks/invoke/src/clients/spi_kv_client.rs +++ b/frontend/sdks/invoke/src/clients/spi_kv_client.rs @@ -12,17 +12,13 @@ use crate::invoke_enumeration::InvokeModuleKind; use super::base_spi_client::BaseSpiClient; pub mod event { - use crate::clients::event_client::Event; - pub const KV_AVATAR: &str = "spi-kv"; - - const EVENT_ADD_KV: &str = "spi-kv/add"; - const EVENT_DELETE_KV: &str = "spi-kv/delete"; - - impl Event for super::KvItemAddOrModifyReq { - const CODE: &'static str = EVENT_ADD_KV; + use asteroid_mq::prelude::*; + impl EventAttribute for super::KvItemAddOrModifyReq { + const SUBJECT: Subject = Subject::const_new(b"kv/add"); + } - impl Event for super::KvItemDeleteReq { - const CODE: &'static str = EVENT_DELETE_KV; + impl EventAttribute for super::KvItemDeleteReq { + const SUBJECT: Subject = Subject::const_new(b"kv/delete"); } } #[derive(Clone, Debug, Default)] diff --git a/frontend/sdks/invoke/src/clients/spi_log_client.rs b/frontend/sdks/invoke/src/clients/spi_log_client.rs index 15844938a..b3345c065 100644 --- a/frontend/sdks/invoke/src/clients/spi_log_client.rs +++ b/frontend/sdks/invoke/src/clients/spi_log_client.rs @@ -14,13 +14,13 @@ use tardis::{ use crate::{clients::base_spi_client::BaseSpiClient, invoke_constants::DYNAMIC_LOG, invoke_enumeration::InvokeModuleKind}; pub mod event { - use crate::clients::event_client::Event; + use asteroid_mq::prelude::*; + - const EVENT_ADD_LOG: &str = "spi-log/add"; pub const LOG_AVATAR: &str = "spi-log"; - impl Event for super::LogItemAddReq { - const CODE: &'static str = EVENT_ADD_LOG; + impl EventAttribute for super::LogItemAddReq { + const SUBJECT: Subject = Subject::const_new(b"log/add"); } } #[derive(Debug, Default, Clone)] diff --git a/frontend/sdks/invoke/src/clients/spi_search_client.rs b/frontend/sdks/invoke/src/clients/spi_search_client.rs index 2fb6aa0f5..d5e5c527b 100644 --- a/frontend/sdks/invoke/src/clients/spi_search_client.rs +++ b/frontend/sdks/invoke/src/clients/spi_search_client.rs @@ -2,40 +2,35 @@ use tardis::basic::dto::TardisContext; use tardis::basic::result::TardisResult; use tardis::TardisFunsInst; +use crate::clients::event_client::mq_error; use crate::dto::search_item_dto::{SearchEventItemDeleteReq, SearchEventItemModifyReq, SearchItemAddReq, SearchItemModifyReq}; use crate::invoke_enumeration::InvokeModuleKind; use super::base_spi_client::BaseSpiClient; -use super::event_client::{BiosEventCenter, EventCenter, EventExt}; +use super::event_client::{mq_node, ContextEvent, EventAttributeExt, EventCenterClient}; use super::spi_kv_client::{KvItemAddOrModifyReq, KvItemDeleteReq, SpiKvClient}; pub struct SpiSearchClient; pub mod event { + use crate::dto::search_item_dto::{SearchEventItemDeleteReq, SearchEventItemModifyReq, SearchItemAddReq, SearchItemModifyReq}; + use asteroid_mq::prelude::*; use serde::{Deserialize, Serialize}; - - use crate::{ - clients::event_client::Event, - dto::search_item_dto::{SearchEventItemDeleteReq, SearchEventItemModifyReq, SearchItemAddReq, SearchItemModifyReq}, - }; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SearchItemModifyEventPayload { pub tag: String, pub key: String, pub req: SearchItemModifyReq, } - const EVENT_ADD_SEARCH: &str = "spi-search/add"; - const EVENT_MODIFY_SEARCH: &str = "spi-search/modify"; - const EVENT_DELETE_SEARCH: &str = "spi-search/delete"; - pub const SEARCH_AVATAR: &str = "spi-search"; - impl Event for SearchItemAddReq { - const CODE: &'static str = EVENT_ADD_SEARCH; + + impl EventAttribute for SearchItemAddReq { + const SUBJECT: Subject = Subject::const_new(b"spi-search/add"); } - impl Event for SearchEventItemModifyReq { - const CODE: &'static str = EVENT_MODIFY_SEARCH; + impl EventAttribute for SearchEventItemModifyReq { + const SUBJECT: Subject = Subject::const_new(b"spi-search/modify"); } - impl Event for SearchEventItemDeleteReq { - const CODE: &'static str = EVENT_DELETE_SEARCH; + impl EventAttribute for SearchEventItemDeleteReq { + const SUBJECT: Subject = Subject::const_new(b"spi-search/delete"); } } @@ -69,68 +64,83 @@ impl SpiSearchClient { } } -impl BiosEventCenter { - pub async fn add_item_and_name(&self, source: &str, add_req: &SearchItemAddReq, name: Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - self.publish(add_req.clone().with_source(source).inject_context(funs, ctx)).await?; +impl EventCenterClient { + pub async fn add_item_and_name(&self, add_req: &SearchItemAddReq, name: Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let topic = self.get_topic()?; + use super::event_client::EventAttributeExt; + topic.send_event(add_req.clone().inject_context(funs, ctx).json()).await.map_err(mq_error)?; let name = if let Some(name) = name.clone() { name } else { add_req.title.clone() }; - self.publish( - KvItemAddOrModifyReq { - key: format!("{}:{}", add_req.tag, add_req.key), - value: tardis::serde_json::Value::String(name), - ..Default::default() - } - .with_source(source) - .inject_context(funs, ctx), - ) - .await?; - Ok(()) - } - - pub async fn modify_item_and_name(&self, source: &str, tag: &str, key: &str, modify_req: &SearchItemModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - self.publish( - SearchEventItemModifyReq { - tag: tag.to_string(), - key: key.to_string(), - item: modify_req.clone(), - } - .with_source(source) - .inject_context(funs, ctx), - ) - .await?; - if modify_req.title.is_some() || modify_req.name.is_some() { - let name = modify_req.name.clone().unwrap_or(modify_req.title.clone().unwrap_or("".to_string())); - self.publish( + topic + .send_event( KvItemAddOrModifyReq { - key: format!("{}:{}", tag, key), + key: format!("{}:{}", add_req.tag, add_req.key), value: tardis::serde_json::Value::String(name), ..Default::default() } - .with_source(source) - .inject_context(funs, ctx), + .inject_context(funs, ctx) + .json(), ) - .await?; + .await + .map_err(mq_error)?; + + Ok(()) + } + + pub async fn modify_item_and_name(&self, tag: &str, key: &str, modify_req: &SearchItemModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let topic = self.get_topic()?; + topic + .send_event( + SearchEventItemModifyReq { + tag: tag.to_string(), + key: key.to_string(), + item: modify_req.clone(), + } + .inject_context(funs, ctx) + .json(), + ) + .await + .map_err(mq_error)?; + if modify_req.title.is_some() || modify_req.name.is_some() { + let name = modify_req.name.clone().unwrap_or(modify_req.title.clone().unwrap_or("".to_string())); + topic + .send_event( + KvItemAddOrModifyReq { + key: format!("{}:{}", tag, key), + value: tardis::serde_json::Value::String(name), + ..Default::default() + } + .inject_context(funs, ctx) + .json(), + ) + .await + .map_err(mq_error)?; } Ok(()) } - pub async fn delete_item_and_name(&self, source: &str, tag: &str, key: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - self.publish( - SearchEventItemDeleteReq { - tag: tag.to_string(), - key: key.to_string(), - } - .with_source(source) - .inject_context(funs, ctx), - ) - .await?; - self.publish( - KvItemDeleteReq { - key: format!("__k_n__:{}:{}", tag, key), - } - .with_source(source) - .inject_context(funs, ctx), - ) - .await?; + pub async fn delete_item_and_name(&self, tag: &str, key: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let topic = self.get_topic()?; + topic + .send_event( + SearchEventItemDeleteReq { + tag: tag.to_string(), + key: key.to_string(), + } + .inject_context(funs, ctx) + .json(), + ) + .await + .map_err(mq_error)?; + topic + .send_event( + KvItemDeleteReq { + key: format!("__k_n__:{}:{}", tag, key), + } + .inject_context(funs, ctx) + .json(), + ) + .await + .map_err(mq_error)?; Ok(()) } }