diff --git a/Cargo.toml b/Cargo.toml index ba3cfb4..4a6cc94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tokio-cron-scheduler = { version = "0" } uuid = { version = "0", features = ["serde", "v4", "v5"] } -beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.81-snapshot" } -beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.67-snapshot" } +beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.83-snapshot" } +beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.69-snapshot" } [build-dependencies] diff --git a/src/api/game/api.rs b/src/api/game/api.rs index 5ab5231..d41e2e4 100644 --- a/src/api/game/api.rs +++ b/src/api/game/api.rs @@ -142,14 +142,8 @@ impl Api { }); } - let user_id = match r.user_id { - Some(v) => v, - None => "".to_string(), - }; - let url = match r.url { - Some(v) => v, - None => "".to_string(), - }; + let user_id = r.user_id.unwrap_or(0); + let url = r.url.unwrap_or("".to_string()); let balance = r.balance.unwrap_or(0); Ok(models::GetGameUrlResponse { diff --git a/src/api/game/models.rs b/src/api/game/models.rs index ab285f7..93b8245 100644 --- a/src/api/game/models.rs +++ b/src/api/game/models.rs @@ -45,14 +45,14 @@ pub struct _GetGameUrlResponse { pub code: i64, pub msg: Option, #[serde(rename = "userId")] - pub user_id: Option, + pub user_id: Option, pub url: Option, pub balance: Option, } #[derive(Debug)] pub struct GetGameUrlResponse { - pub user_id: String, + pub user_id: i64, pub url: String, pub balance: i64, } diff --git a/src/compositions/member/composition.rs b/src/compositions/member/composition.rs new file mode 100644 index 0000000..9e2ae37 --- /dev/null +++ b/src/compositions/member/composition.rs @@ -0,0 +1,122 @@ +use super::models; +use crate::repositories; +use beteran_common_rust as bcr; +use beteran_protobuf_rust as bpr; +use prost::Message; +use std::net::{IpAddr, Ipv4Addr}; + +pub struct Composition { + connection_broker: nats::asynk::Connection, + member_repository: repositories::member::repository::Repository, +} + +impl std::fmt::Debug for Composition { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("Composition of members").finish() + } +} + +impl Composition { + /// + pub fn new(connection_broker: nats::asynk::Connection) -> Composition { + Composition { + connection_broker, + member_repository: repositories::member::repository::Repository::new(), + } + } + + /// + pub async fn select_by_member_id( + &self, + conn: &diesel::PgConnection, + member_id: uuid::Uuid, + ) -> Result, bcr::error::rpc::Error> { + let m = match self + .member_repository + .select_by_member_id(conn, member_id) + .map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + }) + })? { + Some(m) => m, + None => { + return Ok(None); + } + }; + + let ss_get_member_req = bpr::ss::member::GetMemberRequest { + client: Some(bpr::models::core::network::Client { + client_ip: self + .connection_broker + .client_ip() + .unwrap_or(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))) + .to_string(), + site_url: None, + access_token: None, + }), + request: Some(bpr::ss::member::get_member_request::Request { + id: m.member_id.to_string(), + }), + }; + + let ss_get_member_res_msg = self + .connection_broker + .request( + bpr::ss::member::SUBJECT_GET_MEMBER, + ss_get_member_req.encode_to_vec(), + ) + .await + .map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + }) + })?; + + let ss_get_member_res = + bpr::ss::member::GetMemberByUsernameResponse::decode(ss_get_member_res_msg.data.as_slice()) + .map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + }) + })?; + + if let Some(e) = ss_get_member_res.error { + return Err(bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + })); + } + + match ss_get_member_res.result { + Some(r) => match r.member { + Some(mm) => { + return Ok(Some(models::MemberModel { + id: m.id, + balance: m.balance, + balance_bota: m.balance_bota, + balance_sum: m.balance_sum, + companies: m.companies, + oriental_play: m.oriental_play, + member: mm, + created_at: m.created_at, + updated_at: m.updated_at, + })) + } + None => { + return Ok(None); + } + }, + None => { + return Ok(None); + } + }; + } +} diff --git a/src/compositions/member/mod.rs b/src/compositions/member/mod.rs index e69de29..b77534a 100644 --- a/src/compositions/member/mod.rs +++ b/src/compositions/member/mod.rs @@ -0,0 +1,2 @@ +pub mod composition; +pub mod models; diff --git a/src/compositions/member/models.rs b/src/compositions/member/models.rs new file mode 100644 index 0000000..680d4c6 --- /dev/null +++ b/src/compositions/member/models.rs @@ -0,0 +1,24 @@ +use beteran_protobuf_rust as bpr; + +/// +#[derive(PartialEq, Debug, Clone)] +pub struct MemberModel { + /// + pub id: i64, + /// + pub balance: i64, + /// + pub balance_bota: i64, + /// + pub balance_sum: i64, + /// + pub companies: i64, + /// + pub oriental_play: String, + /// + pub member: bpr::models::member::MemberModel, + /// + pub created_at: i64, + /// + pub updated_at: i64, +} diff --git a/src/main.rs b/src/main.rs index fd348dc..9b8dd46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,11 +29,11 @@ async fn main() -> Result<(), Box> { None => "".to_string(), }; - let url_server_broker = match env::var_os("URL_BROKER") { + let url_broker = match env::var_os("URL_BROKER") { Some(v) => v.into_string().unwrap(), None => "".to_string(), }; - let queue_server_broker = match env::var_os("QUEUE_BROKER") { + let queue_broker = match env::var_os("QUEUE_BROKER") { Some(v) => v.into_string().unwrap(), None => "".to_string(), }; @@ -66,15 +66,15 @@ async fn main() -> Result<(), Box> { embedded_migrations::run(&conn)?; - let server_broker_opts = nats::asynk::Options::new(); - let connection_server_broker = server_broker_opts.connect(url_server_broker).await?; + let broker_opts = nats::asynk::Options::new(); + let connection_broker = broker_opts.connect(url_broker).await?; let vendor_synchronizer = synchronizations::vendor::synchronizer::Synchronizer::new(pool.clone(), api_config.clone()); let game_synchronizer = synchronizations::game::synchronizer::Synchronizer::new(pool.clone(), api_config.clone()); let member_synchronizer = synchronizations::member::synchronizer::Synchronizer::new( - connection_server_broker.clone(), + connection_broker.clone(), pool.clone(), api_config.clone(), ); @@ -85,44 +85,41 @@ async fn main() -> Result<(), Box> { ); let vendor_service = services::vendor::service::Service::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), pool.clone(), ); let game_service = services::game::service::Service::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), pool.clone(), + api_config.clone(), ); - let member_service = services::member::service::Service::new( - connection_server_broker.clone(), - queue_server_broker.clone(), - ); + let member_service = + services::member::service::Service::new(connection_broker.clone(), queue_broker.clone()); let member_account_service = services::member_account::service::Service::new( - connection_server_broker.clone(), - queue_server_broker.clone(), - ); - let betting_service = services::betting::service::Service::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), ); + let betting_service = + services::betting::service::Service::new(connection_broker.clone(), queue_broker.clone()); let member_event_handler = events::member::event::EventHandler::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), pool.clone(), api_config.clone(), ); let member_bank_deposit_event_handler = events::member_bank_deposit::event::EventHandler::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), pool.clone(), member_account_synchronizer.clone(), api_config.clone(), ); let member_bank_withdraw_event_handler = events::member_bank_withdraw::event::EventHandler::new( - connection_server_broker.clone(), - queue_server_broker.clone(), + connection_broker.clone(), + queue_broker.clone(), pool.clone(), member_account_synchronizer.clone(), api_config.clone(), diff --git a/src/services/game/service.rs b/src/services/game/service.rs index 2722854..b4e1525 100644 --- a/src/services/game/service.rs +++ b/src/services/game/service.rs @@ -1,3 +1,6 @@ +use crate::api; +use crate::compositions; +use crate::core; use crate::repositories; use beteran_common_rust as bcr; use beteran_protobuf_rust as bpr; @@ -6,13 +9,17 @@ use diesel::{ PgConnection, }; use prost::Message; +use std::str::FromStr; /// pub struct Service { connection_broker: nats::asynk::Connection, queue_broker: String, pool: Pool>, + member_composition: compositions::member::composition::Composition, game_repository: repositories::game::repository::Repository, + api_config: core::config::ApiConfig, + game_api: api::game::api::Api, } impl std::fmt::Debug for Service { @@ -27,17 +34,21 @@ impl Service { connection_broker: nats::asynk::Connection, queue_broker: String, pool: Pool>, + api_config: core::config::ApiConfig, ) -> Service { Service { - connection_broker, + connection_broker: connection_broker.clone(), queue_broker, pool, + api_config: api_config.clone(), + member_composition: compositions::member::composition::Composition::new(connection_broker), game_repository: repositories::game::repository::Repository::new(), + game_api: api::game::api::Api::new(api_config), } } pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box> { - futures::try_join!(self.list_games()).map(|_| ()) + futures::try_join!(self.list_games(), self.get_game_url()).map(|_| ()) } async fn list_games(&self) -> Result<(), Box> { @@ -188,7 +199,149 @@ impl Service { Ok(()) } - async fn execute_game(&self) -> Result<(), Box> { + async fn get_game_url(&self) -> Result<(), Box> { + let s = self + .connection_broker + .queue_subscribe( + bpr::ss::api::game::SUBJECT_GET_GAME_URL, + self.queue_broker.as_str(), + ) + .await?; + + while let Some(message) = s.next().await { + if let Err(e) = async { + let req = + bpr::ss::api::game::GetGameUrlRequest::decode(message.data.as_slice()).map_err(|e| { + bcr::error::rpc::Error::InvalidRequest(bcr::error::rpc::InvalidRequest { + message: format!("invalid request: {}", e), + }) + })?; + + let client = match req.client { + Some(c) => c, + None => { + return Err(bcr::error::rpc::Error::InvalidParams( + bcr::error::rpc::InvalidParams { + message: "invalid client information".to_string(), + detail: bcr::error::rpc::InvalidParamsDetail { + location: "request".to_string(), + param: "client".to_string(), + value: "".to_string(), + error_type: bcr::error::rpc::InvalidParamsType::Required, + message: "".to_string(), + }, + }, + )); + } + }; + let request = match req.request { + Some(r) => r, + None => { + return Err(bcr::error::rpc::Error::InvalidParams( + bcr::error::rpc::InvalidParams { + message: "invalid request information".to_string(), + detail: bcr::error::rpc::InvalidParamsDetail { + location: "request".to_string(), + param: "request".to_string(), + value: "".to_string(), + error_type: bcr::error::rpc::InvalidParamsType::Required, + message: "".to_string(), + }, + }, + )); + } + }; + + let vendor_key = request.vendor_key.clone(); + let game_key = request.game_key.clone(); + + let member_id = uuid::Uuid::from_str(request.member_id.as_str()).map_err(|e| { + bcr::error::rpc::Error::InvalidParams(bcr::error::rpc::InvalidParams { + message: "invalid member_id param".to_string(), + detail: bcr::error::rpc::InvalidParamsDetail { + location: "event".to_string(), + param: "member_id".to_string(), + value: request.member_id.clone(), + error_type: bcr::error::rpc::InvalidParamsType::Required, + message: e.to_string(), + }, + }) + })?; + + let conn = self.pool.get().map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + }) + })?; + + let result = match self + .member_composition + .select_by_member_id(&conn, member_id) + .await? + { + Some(m) => { + let req = api::game::models::GetGameUrlRequest { + vendor_key, + game_key, + username: m.member.username.clone(), + nickname: m.member.nickname.clone(), + site_username: m.member.username.clone(), + group_key: m.member.parent_member.map(|p| p.username.clone()), + amount: m.balance_sum, + request_key: None, + }; + let res = self.game_api.get_game_url(req).await.map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {:?}", e), + data: None, + }) + })?; + + Some(bpr::ss::api::game::get_game_url_response::Result { + user_id: res.user_id as u64, + balance: res.balance as u64, + url: res.url, + }) + } + None => None, + }; + + message + .respond( + bpr::ss::api::game::GetGameUrlResponse { + error: None, + result, + } + .encode_to_vec(), + ) + .await + .map_err(|e| { + bcr::error::rpc::Error::Server(bcr::error::rpc::Server { + code: bpr::protobuf::rpc::Error::SERVER_00, + message: format!("server {}", e), + data: None, + }) + })?; + + Ok::<(), bcr::error::rpc::Error>(()) + } + .await + { + message + .respond( + bpr::ss::api::game::GetGameUrlResponse { + error: Some(bpr::protobuf::rpc::Error::from(e)), + result: None, + } + .encode_to_vec(), + ) + .await?; + } + } + Ok(()) } }