From 0db6f75d614c1446943c83a22c7acab29e23627e Mon Sep 17 00:00:00 2001 From: PARK BYUNG JUN Date: Wed, 17 Aug 2022 17:45:00 +0000 Subject: [PATCH] implemented --- .vscode/launch.json | 6 +- Cargo.toml | 1 + migrations/202208041000_initialize/down.sql | 1 + migrations/202208041000_initialize/up.sql | 16 ++ .../down.sql | 2 + .../up.sql | 8 + .../down.sql | 3 + .../up.sql | 19 ++ .../202208051200_api_kgon_member/up.sql | 3 - .../down.sql | 1 - .../up.sql | 4 - .../down.sql | 2 - .../up.sql | 4 - .../202208061200_api_kgon_vendor/down.sql | 6 + .../202208061200_api_kgon_vendor/up.sql | 12 +- .../down.sql | 0 .../up.sql | 4 - .../202208061300_api_kgon_game/down.sql | 6 + migrations/202208061300_api_kgon_game/up.sql | 5 + .../down.sql | 0 .../up.sql | 4 - src/api/betting/api.rs | 38 +-- src/api/core/mod.rs | 1 + src/api/core/models.rs | 5 + src/api/game/api.rs | 130 +++++----- src/api/game/models.rs | 41 ++-- src/api/member/api.rs | 99 ++++---- src/api/member/models.rs | 19 +- src/api/member_account/api.rs | 130 ++++++---- src/api/member_account/models.rs | 27 ++- src/api/mod.rs | 2 + src/api/vendor/api.rs | 76 ++++++ src/api/vendor/mod.rs | 7 + src/api/vendor/models.rs | 29 +++ src/core/config.rs | 6 + src/core/mod.rs | 1 + src/main.rs | 54 +++-- src/repositories/game/models.rs | 22 ++ src/repositories/game/repository.rs | 43 +++- src/repositories/member/models.rs | 20 +- src/repositories/member/repository.rs | 19 +- src/repositories/member/schema.rs | 2 +- src/repositories/mod.rs | 2 + src/repositories/synchronization/mod.rs | 9 + src/repositories/synchronization/models.rs | 39 +++ .../synchronization/repository.rs | 103 ++++++++ src/repositories/synchronization/schema.rs | 16 ++ .../synchronization_history/mod.rs | 9 + .../synchronization_history/models.rs | 56 +++++ .../synchronization_history/repository.rs | 160 +++++++++++++ .../synchronization_history/schema.rs | 22 ++ src/repositories/vendor/models.rs | 34 ++- src/repositories/vendor/repository.rs | 45 +++- src/repositories/vendor/schema.rs | 2 +- src/schedulers/balance/scheduler.rs | 225 +++++++++++++++++- src/schedulers/game/scheduler.rs | 155 +++++++++++- src/schedulers/member/scheduler.rs | 130 +++++++++- src/schedulers/vendor/scheduler.rs | 165 +++++++++---- src/services/betting/service.rs | 35 +-- src/services/game/service.rs | 25 +- src/services/member/service.rs | 23 +- src/services/member_account/service.rs | 36 +-- 62 files changed, 1757 insertions(+), 412 deletions(-) create mode 100644 migrations/202208041000_initialize/down.sql create mode 100644 migrations/202208041000_initialize/up.sql create mode 100644 migrations/202208051000_api_kgon_synchronization/down.sql create mode 100644 migrations/202208051000_api_kgon_synchronization/up.sql create mode 100644 migrations/202208051010_api_kgon_synchronization_history/down.sql create mode 100644 migrations/202208051010_api_kgon_synchronization_history/up.sql delete mode 100644 migrations/202208051210_api_kgon_synchronization_member/down.sql delete mode 100644 migrations/202208051210_api_kgon_synchronization_member/up.sql delete mode 100644 migrations/202208051410_api_kgon_synchronization_balance/down.sql delete mode 100644 migrations/202208051410_api_kgon_synchronization_balance/up.sql delete mode 100644 migrations/202208061210_api_kgon_synchronization_vendor/down.sql delete mode 100644 migrations/202208061210_api_kgon_synchronization_vendor/up.sql delete mode 100644 migrations/202208061310_api_kgon_synchronization_game/down.sql delete mode 100644 migrations/202208061310_api_kgon_synchronization_game/up.sql create mode 100644 src/api/core/mod.rs create mode 100644 src/api/core/models.rs create mode 100644 src/api/vendor/api.rs create mode 100644 src/api/vendor/mod.rs create mode 100644 src/api/vendor/models.rs create mode 100644 src/core/config.rs create mode 100644 src/core/mod.rs create mode 100644 src/repositories/synchronization/mod.rs create mode 100644 src/repositories/synchronization/models.rs create mode 100644 src/repositories/synchronization/repository.rs create mode 100644 src/repositories/synchronization/schema.rs create mode 100644 src/repositories/synchronization_history/mod.rs create mode 100644 src/repositories/synchronization_history/models.rs create mode 100644 src/repositories/synchronization_history/repository.rs create mode 100644 src/repositories/synchronization_history/schema.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index 0af3c8f..b2a5769 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,8 +23,9 @@ "URL_DATABASE": "postgresql://beteran:qwer5795QWER@192.168.50.200:25432/beteran", "URL_BROKER": "nats://192.168.50.200:4222", "QUEUE_BROKER": "bet.beteran", - "K_SECRET": "c23d770b873b2ce95747abc57052beb0", + "K_URL": "https://dev-mw.kgonapi.com", "K_USERNAME": "Turbo77", + "K_SECRET": "c23d770b873b2ce95747abc57052beb0", }, "args": [], "cwd": "${workspaceFolder}" @@ -49,8 +50,9 @@ "URL_DATABASE": "postgresql://beteran:qwer5795QWER@192.168.50.200:25432/beteran", "URL_BROKER": "nats://192.168.50.200:4222", "QUEUE_BROKER": "bet.beteran", - "K_SECRET": "c23d770b873b2ce95747abc57052beb0", + "K_URL": "https://dev-mw.kgonapi.com", "K_USERNAME": "Turbo77", + "K_SECRET": "c23d770b873b2ce95747abc57052beb0", }, "args": [], "cwd": "${workspaceFolder}" diff --git a/Cargo.toml b/Cargo.toml index 25d1e23..136cdaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ futures = { version = "0", default-features = false, features = [ "async-await", ] } nats = { version = "0" } +once_cell = { version = "1" } openssl = { version = "0", features = ["vendored"] } prost = { version = "0" } reqwest = { version = "0", features = ["json"] } diff --git a/migrations/202208041000_initialize/down.sql b/migrations/202208041000_initialize/down.sql new file mode 100644 index 0000000..aa2775c --- /dev/null +++ b/migrations/202208041000_initialize/down.sql @@ -0,0 +1 @@ +DROP FUNCTION update_synchronizations; \ No newline at end of file diff --git a/migrations/202208041000_initialize/up.sql b/migrations/202208041000_initialize/up.sql new file mode 100644 index 0000000..a6ec84f --- /dev/null +++ b/migrations/202208041000_initialize/up.sql @@ -0,0 +1,16 @@ +CREATE OR REPLACE FUNCTION update_synchronizations() +RETURNS TRIGGER AS $$ +BEGIN + INSERT INTO api_kgon_synchronizations + (item, last_code, synchronized_at) + VALUES + (NEW.item, NEW.code, (extract(epoch from now()) * 1000)) + ON CONFLICT (item) + DO UPDATE + SET + last_code = NEW.code, + synchronized_at = (extract(epoch from now()) * 1000); + + RETURN NEW; +END; +$$ language 'plpgsql'; diff --git a/migrations/202208051000_api_kgon_synchronization/down.sql b/migrations/202208051000_api_kgon_synchronization/down.sql new file mode 100644 index 0000000..96056bb --- /dev/null +++ b/migrations/202208051000_api_kgon_synchronization/down.sql @@ -0,0 +1,2 @@ +CREATE UNIQUE INDEX uidx_api_kgon_synchronizations_item; +DROP TABLE api_kgon_synchronization_members; diff --git a/migrations/202208051000_api_kgon_synchronization/up.sql b/migrations/202208051000_api_kgon_synchronization/up.sql new file mode 100644 index 0000000..88601ad --- /dev/null +++ b/migrations/202208051000_api_kgon_synchronization/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS api_kgon_synchronizations ( + id SERIAL PRIMARY KEY; + item TEXT NOT NULL, + last_code BIGINT NOT NULL, + synchronized_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) +); + +CREATE UNIQUE INDEX uidx_api_kgon_synchronizations_item ON api_kgon_synchronizations (item); diff --git a/migrations/202208051010_api_kgon_synchronization_history/down.sql b/migrations/202208051010_api_kgon_synchronization_history/down.sql new file mode 100644 index 0000000..d8f30c7 --- /dev/null +++ b/migrations/202208051010_api_kgon_synchronization_history/down.sql @@ -0,0 +1,3 @@ +DROP TRIGGER tg_api_kgon_synchronization_history_synchronizations; +DROP INDEX idx_api_kgon_synchronization_history_item; +DROP TABLE api_kgon_synchronization_members; diff --git a/migrations/202208051010_api_kgon_synchronization_history/up.sql b/migrations/202208051010_api_kgon_synchronization_history/up.sql new file mode 100644 index 0000000..320fabe --- /dev/null +++ b/migrations/202208051010_api_kgon_synchronization_history/up.sql @@ -0,0 +1,19 @@ +CREATE TABLE IF NOT EXISTS api_kgon_synchronization_history ( + id SERIAL PRIMARY KEY; + item TEXT NOT NULL, + start_at BIGINT NOT NULL, + complete_at BIGINT NOT NULL, + code BIGINT NOT NULL, + message TEXT, + created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) +); + +CREATE INDEX idx_api_kgon_synchronization_history_item ON api_kgon_synchronization_history (item); + + +-- trigger (synchronized_at) +CREATE TRIGGER tg_api_kgon_synchronization_history_synchronizations + BEFORE UPDATE + ON api_kgon_synchronization_history + FOR EACH ROW + EXECUTE PROCEDURE update_synchronizations(); diff --git a/migrations/202208051200_api_kgon_member/up.sql b/migrations/202208051200_api_kgon_member/up.sql index 266f785..35fe26c 100644 --- a/migrations/202208051200_api_kgon_member/up.sql +++ b/migrations/202208051200_api_kgon_member/up.sql @@ -22,6 +22,3 @@ CREATE TRIGGER tg_api_kgon_members_updated_at ON api_kgon_members FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column(); - - - diff --git a/migrations/202208051210_api_kgon_synchronization_member/down.sql b/migrations/202208051210_api_kgon_synchronization_member/down.sql deleted file mode 100644 index 714f512..0000000 --- a/migrations/202208051210_api_kgon_synchronization_member/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE api_kgon_synchronization_members; diff --git a/migrations/202208051210_api_kgon_synchronization_member/up.sql b/migrations/202208051210_api_kgon_synchronization_member/up.sql deleted file mode 100644 index dd2414f..0000000 --- a/migrations/202208051210_api_kgon_synchronization_member/up.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE IF NOT EXISTS api_kgon_synchronization_members ( - id BIGSERIAL PRIMARY KEY; - created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) -); diff --git a/migrations/202208051410_api_kgon_synchronization_balance/down.sql b/migrations/202208051410_api_kgon_synchronization_balance/down.sql deleted file mode 100644 index 58771eb..0000000 --- a/migrations/202208051410_api_kgon_synchronization_balance/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP TRIGGER tg_api_kgon_balances_updated_at; -DROP TABLE api_kgon_balances; diff --git a/migrations/202208051410_api_kgon_synchronization_balance/up.sql b/migrations/202208051410_api_kgon_synchronization_balance/up.sql deleted file mode 100644 index d5274eb..0000000 --- a/migrations/202208051410_api_kgon_synchronization_balance/up.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE IF NOT EXISTS api_kgon_synchronization_balances ( - id BIGSERIAL PRIMARY KEY; - created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) -); diff --git a/migrations/202208061200_api_kgon_vendor/down.sql b/migrations/202208061200_api_kgon_vendor/down.sql index e69de29..23474a4 100644 --- a/migrations/202208061200_api_kgon_vendor/down.sql +++ b/migrations/202208061200_api_kgon_vendor/down.sql @@ -0,0 +1,6 @@ +DROP INDEX idx_api_kgon_vendors_company_id; +DROP INDEX idx_api_kgon_vendors_vendor_id; +DROP INDEX idx_api_kgon_vendors_key; +DROP INDEX idx_api_kgon_vendors_category; +DROP TRIGGER tg_api_kgon_vendors_updated_at; +DROP TABLE api_kgon_vendors; diff --git a/migrations/202208061200_api_kgon_vendor/up.sql b/migrations/202208061200_api_kgon_vendor/up.sql index 6ae325e..4be6ecd 100644 --- a/migrations/202208061200_api_kgon_vendor/up.sql +++ b/migrations/202208061200_api_kgon_vendor/up.sql @@ -4,19 +4,21 @@ CREATE TABLE IF NOT EXISTS api_kgon_vendors ( vendor_id BIGINT NOT NULL, max_bet_casino BIGINT NOT NULL, max_bet_slot BIGINT NOT NULL, - is_enable BOOLEAN NOT NULL, + is_enable CHAR(1) NOT NULL, bet_count BIGINT NOT NULL, key TEXT NOT NULL, name TEXT NOT NULL, category TEXT NOT NULL, created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000), updated_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000), - PRIMARY KEY (id), - CONSTRAINT fk_api_kgon_vendors_parent_id - FOREIGN KEY(parent_id) - REFERENCES roles(id) + PRIMARY KEY (id) ); +CREATE INDEX idx_api_kgon_vendors_company_id ON api_kgon_vendors (company_id); +CREATE INDEX idx_api_kgon_vendors_vendor_id ON api_kgon_vendors (vendor_id); +CREATE INDEX idx_api_kgon_vendors_key ON api_kgon_vendors (key); +CREATE INDEX idx_api_kgon_vendors_category ON api_kgon_vendors (category); + -- trigger (updated_at) CREATE TRIGGER tg_api_kgon_vendors_updated_at BEFORE UPDATE diff --git a/migrations/202208061210_api_kgon_synchronization_vendor/down.sql b/migrations/202208061210_api_kgon_synchronization_vendor/down.sql deleted file mode 100644 index e69de29..0000000 diff --git a/migrations/202208061210_api_kgon_synchronization_vendor/up.sql b/migrations/202208061210_api_kgon_synchronization_vendor/up.sql deleted file mode 100644 index 53f8fd4..0000000 --- a/migrations/202208061210_api_kgon_synchronization_vendor/up.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE IF NOT EXISTS api_kgon_synchronization_vendors ( - id BIGSERIAL PRIMARY KEY; - created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) -); diff --git a/migrations/202208061300_api_kgon_game/down.sql b/migrations/202208061300_api_kgon_game/down.sql index e69de29..b369db3 100644 --- a/migrations/202208061300_api_kgon_game/down.sql +++ b/migrations/202208061300_api_kgon_game/down.sql @@ -0,0 +1,6 @@ +DROP INDEX idx_api_kgon_games_vendor_id; +DROP INDEX idx_api_kgon_games_key; +DROP INDEX idx_api_kgon_games_category; +DROP INDEX idx_api_kgon_games_game_type; +DROP TRIGGER tg_api_kgon_games_updated_at; +DROP TABLE api_kgon_games; diff --git a/migrations/202208061300_api_kgon_game/up.sql b/migrations/202208061300_api_kgon_game/up.sql index 5a4eae5..57aa603 100644 --- a/migrations/202208061300_api_kgon_game/up.sql +++ b/migrations/202208061300_api_kgon_game/up.sql @@ -15,6 +15,11 @@ CREATE TABLE IF NOT EXISTS api_kgon_games ( REFERENCES api_kgon_vendors(id) ); +CREATE INDEX idx_api_kgon_games_vendor_id ON api_kgon_games (vendor_id); +CREATE INDEX idx_api_kgon_games_key ON api_kgon_games (key); +CREATE INDEX idx_api_kgon_games_category ON api_kgon_games (category); +CREATE INDEX idx_api_kgon_games_game_type ON api_kgon_games (game_type); + -- trigger (updated_at) CREATE TRIGGER tg_api_kgon_games_updated_at BEFORE UPDATE diff --git a/migrations/202208061310_api_kgon_synchronization_game/down.sql b/migrations/202208061310_api_kgon_synchronization_game/down.sql deleted file mode 100644 index e69de29..0000000 diff --git a/migrations/202208061310_api_kgon_synchronization_game/up.sql b/migrations/202208061310_api_kgon_synchronization_game/up.sql deleted file mode 100644 index 32acd5c..0000000 --- a/migrations/202208061310_api_kgon_synchronization_game/up.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE IF NOT EXISTS api_kgon_synchronization_games ( - id BIGSERIAL PRIMARY KEY; - created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000) -); diff --git a/src/api/betting/api.rs b/src/api/betting/api.rs index eab45ed..1d820b0 100644 --- a/src/api/betting/api.rs +++ b/src/api/betting/api.rs @@ -1,11 +1,11 @@ use super::models; -use std::{collections::HashMap, time::Duration}; +use crate::core; +use std::collections::HashMap; /// pub struct Api { client: reqwest::Client, - k_secret: String, - k_username: String, + api_config: core::config::ApiConfig, } impl std::fmt::Debug for Api { @@ -16,11 +16,10 @@ impl std::fmt::Debug for Api { impl Api { /// - pub fn new(k_secret: &str, k_username: &str) -> Api { + pub fn new(api_config: core::config::ApiConfig) -> Api { Api { client: reqwest::Client::new(), - k_secret: k_secret.to_string(), - k_username: k_username.to_string(), + api_config, } } @@ -51,14 +50,14 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/transaction") + .post(format!("{}/transaction", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .send() .await { @@ -88,14 +87,14 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/pragmatic/history") + .post(format!("{}/pragmatic/history", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await @@ -126,14 +125,17 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/evolution/transaction/detail") + .post(format!( + "{}/evolution/transaction/detail", + self.api_config.k_url + )) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await @@ -175,14 +177,14 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/statistic") + .post(format!("{}/statistic", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs new file mode 100644 index 0000000..c446ac8 --- /dev/null +++ b/src/api/core/mod.rs @@ -0,0 +1 @@ +pub mod models; diff --git a/src/api/core/models.rs b/src/api/core/models.rs new file mode 100644 index 0000000..e1ece92 --- /dev/null +++ b/src/api/core/models.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub struct Error { + pub code: i64, + pub msg: Option, +} diff --git a/src/api/game/api.rs b/src/api/game/api.rs index 5dbfa46..ff8fb7d 100644 --- a/src/api/game/api.rs +++ b/src/api/game/api.rs @@ -1,11 +1,12 @@ use super::models; +use crate::api::core::models::Error; +use crate::core; use std::{collections::HashMap, time::Duration}; /// pub struct Api { client: reqwest::Client, - k_secret: String, - k_username: String, + api_config: core::config::ApiConfig, } impl std::fmt::Debug for Api { @@ -16,90 +17,71 @@ impl std::fmt::Debug for Api { impl Api { /// - pub fn new(k_secret: &str, k_username: &str) -> Api { + pub fn new(api_config: core::config::ApiConfig) -> Api { Api { client: reqwest::Client::new(), - k_secret: k_secret.to_string(), - k_username: k_username.to_string(), + api_config, } } /// - pub async fn find_vendors( + pub async fn list_games( &self, - data: models::FindVendorsRequest, - ) -> Result { - let res = match self - .client - .post("https://dev-mw.kgonapi.com/vendors") - .header(reqwest::header::ACCEPT, "application/json") - .header( - reqwest::header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) - .send() - .await - { - Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); - } - }; - - match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), - }, - _ => Err(models::Error { code: 0, msg: None }), - } - } - - /// - pub async fn find_games( - &self, - data: models::FindGamesRequest, - ) -> Result { + data: models::ListGamesRequest, + ) -> Result { let mut params = HashMap::new(); params.insert("vendorKey", data.vendor_key); let res = match self .client - .post("https://dev-mw.kgonapi.com/games") + .post(format!("{}/games", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); } }; match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::ListGamesResponse { games: r.games }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { + code: -1, + msg: None, + }), } } /// - pub async fn play( - &self, - data: models::PlayRequest, - ) -> Result { + pub async fn play(&self, data: models::PlayRequest) -> Result { let mut params = HashMap::new(); params.insert("vendorKey", data.vendor_key); @@ -120,31 +102,53 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/play") + .post(format!("{}/play", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .timeout(Duration::from_secs(10)) .send() .await { Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); } }; match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::PlayResponse { + user_id: r.user_id, + url: r.url, + balance: r.balance, + }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { + code: -1, + msg: None, + }), } } } diff --git a/src/api/game/models.rs b/src/api/game/models.rs index 5df3e3d..74a9125 100644 --- a/src/api/game/models.rs +++ b/src/api/game/models.rs @@ -1,28 +1,32 @@ use serde::{Deserialize, Serialize}; - -pub struct Error { - pub code: i64, - pub msg: Option, -} - -pub struct FindVendorsRequest {} +use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug)] -pub struct FindVendorsResponse { - pub code: i64, - pub msg: Option, - pub vendors: Vec, +pub struct Game { + pub id: i64, + pub key: String, + pub names: HashMap, + pub platform: String, + pub category: String, + #[serde(rename = "type")] + pub game_type: String, + pub image: Option, } -pub struct FindGamesRequest { +pub struct ListGamesRequest { pub vendor_key: String, } #[derive(Serialize, Deserialize, Debug)] -pub struct FindGamesResponse { +pub struct _ListGamesResponse { pub code: i64, pub msg: Option, - pub games: Vec, + pub games: Vec, +} + +#[derive(Debug)] +pub struct ListGamesResponse { + pub games: Vec, } pub struct PlayRequest { @@ -37,7 +41,7 @@ pub struct PlayRequest { } #[derive(Serialize, Deserialize, Debug)] -pub struct PlayResponse { +pub struct _PlayResponse { pub code: i64, pub msg: Option, #[serde(rename = "userId")] @@ -45,3 +49,10 @@ pub struct PlayResponse { pub url: String, pub balance: i64, } + +#[derive(Debug)] +pub struct PlayResponse { + pub user_id: String, + pub url: String, + pub balance: i64, +} diff --git a/src/api/member/api.rs b/src/api/member/api.rs index 8e62486..3d7a905 100644 --- a/src/api/member/api.rs +++ b/src/api/member/api.rs @@ -1,12 +1,12 @@ use super::models; +use crate::api::core::models::Error; +use crate::core; use std::collections::HashMap; /// pub struct Api { client: reqwest::Client, - url: String, - k_secret: String, - k_username: String, + api_config: core::config::ApiConfig, } impl std::fmt::Debug for Api { @@ -17,12 +17,10 @@ impl std::fmt::Debug for Api { impl Api { /// - pub fn new(url: &str, k_secret: &str, k_username: &str) -> Api { + pub fn new(api_config: core::config::ApiConfig) -> Api { Api { client: reqwest::Client::new(), - url: url.to_string(), - k_secret: k_secret.to_string(), - k_username: k_username.to_string(), + api_config, } } @@ -30,7 +28,7 @@ impl Api { pub async fn list_members( &self, data: models::ListMembersRequest, - ) -> Result { + ) -> Result { let mut params = HashMap::new(); if let Some(group_key) = data.group_key { @@ -39,30 +37,48 @@ impl Api { let res = match self .client - .post(format!("{}/users", self.url)) + .post(format!("{}/users", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); } }; match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::ListMembersResponse { users: r.users }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { + code: -1, + msg: None, + }), } } @@ -70,7 +86,7 @@ impl Api { pub async fn save_member( &self, data: models::SaveMemberRequest, - ) -> Result { + ) -> Result { let mut params = HashMap::new(); params.insert("username", data.username); @@ -83,65 +99,30 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/register") + .post(format!("{}/register", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, Err(err) => { - return Err(models::Error { code: 0, msg: None }); + return Err(Error { code: 0, msg: None }); } }; match res.status() { reqwest::StatusCode::OK => match res.json::().await { Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + Err(e) => Err(Error { code: 0, msg: None }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { code: 0, msg: None }), } } } - -#[cfg(test)] -mod tests { - use super::super::models; - use super::*; - - #[tokio::test] - async fn find_members() { - let repository = Api::new("c23d770b873b2ce95747abc57052beb0", "Turbo77"); - - let r = repository - .find_members(models::FindMembersRequest { group_key: None }) - .await - .expect(""); - - println!("members: {:?}", r); - } - - #[tokio::test] - async fn save_member() { - let repository = Api::new("c23d770b873b2ce95747abc57052beb0", "Turbo77"); - - let r = repository - .save_member(models::SaveMemberRequest { - username: "".to_string(), - nickname: "".to_string(), - site_username: "".to_string(), - group_key: None, - }) - .await - .expect(""); - - println!("member: {:?}", r); - } -} diff --git a/src/api/member/models.rs b/src/api/member/models.rs index 4ae48b7..5deb137 100644 --- a/src/api/member/models.rs +++ b/src/api/member/models.rs @@ -1,18 +1,12 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug)] -pub struct Error { - pub code: i64, - pub msg: Option, -} - #[derive(Serialize, Deserialize, Debug)] pub struct ListMembersRequest { pub group_key: Option, } #[derive(Serialize, Deserialize, Debug)] -pub struct FindMember { +pub struct Member { pub id: i64, pub username: String, pub cash: i64, @@ -20,14 +14,19 @@ pub struct FindMember { pub nickname: String, pub site_username: String, pub group_key: Option, - pub oriental_play: Option, + pub oriental_play: String, } #[derive(Serialize, Deserialize, Debug)] -pub struct ListMembersResponse { +pub struct _ListMembersResponse { pub code: i64, pub msg: Option, - pub users: Vec, + pub users: Vec, +} + +#[derive(Debug)] +pub struct ListMembersResponse { + pub users: Vec, } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/api/member_account/api.rs b/src/api/member_account/api.rs index 836936b..92617ea 100644 --- a/src/api/member_account/api.rs +++ b/src/api/member_account/api.rs @@ -1,11 +1,12 @@ use super::models; +use crate::api::core::models::Error; +use crate::core; use std::collections::HashMap; /// pub struct Api { client: reqwest::Client, - k_secret: String, - k_username: String, + api_config: core::config::ApiConfig, } impl std::fmt::Debug for Api { @@ -16,82 +17,125 @@ impl std::fmt::Debug for Api { impl Api { /// - pub fn new(k_secret: &str, k_username: &str) -> Api { + pub fn new(api_config: core::config::ApiConfig) -> Api { Api { client: reqwest::Client::new(), - k_secret: k_secret.to_string(), - k_username: k_username.to_string(), + api_config, } } /// - pub async fn find_balance( + pub async fn get_balance_for_user( &self, - data: models::FindBalanceRequest, - ) -> Result { + data: models::GetBalanceForUserRequest, + ) -> Result { let mut params = HashMap::new(); params.insert("username", data.username); let res = match self .client - .post("https://dev-mw.kgonapi.com/balance") + .post(format!("{}/balance", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); } }; match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::GetBalanceForUserResponse { + balance: r.balance, + balance_bota: r.balance_bota, + balance_sum: r.balance_sum, + companies: r.companies, + }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { + code: -1, + msg: None, + }), } } /// - pub async fn find_partner_balance( + pub async fn get_balance_for_partner( &self, - data: models::FindPartnerBalanceRequest, - ) -> Result { + data: models::GetBalanceForPartnerRequest, + ) -> Result { let res = match self .client - .post("https://dev-mw.kgonapi.com/partner/balance") + .post(format!("{}/partner/balance", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .send() .await { Ok(res) => res, - Err(err) => { - return Err(models::Error { code: 0, msg: None }); + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); } }; match res.status() { - reqwest::StatusCode::OK => match res.json::().await { - Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::GetBalanceForPartnerResponse { + balance: r.balance, + balance_bota: r.balance_bota, + }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { + code: -1, + msg: None, + }), } } @@ -99,7 +143,7 @@ impl Api { pub async fn save_deposit( &self, data: models::SaveDepositRequest, - ) -> Result { + ) -> Result { let mut params = HashMap::new(); params.insert("username", data.username); @@ -113,30 +157,30 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/deposit") + .post(format!("{}/deposit", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, Err(err) => { - return Err(models::Error { code: 0, msg: None }); + return Err(Error { code: 0, msg: None }); } }; match res.status() { reqwest::StatusCode::OK => match res.json::().await { Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + Err(e) => Err(Error { code: 0, msg: None }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { code: 0, msg: None }), } } @@ -144,7 +188,7 @@ impl Api { pub async fn save_withdraw( &self, data: models::SaveWithdrawRequest, - ) -> Result { + ) -> Result { let mut params = HashMap::new(); params.insert("username", data.username); @@ -154,30 +198,30 @@ impl Api { let res = match self .client - .post("https://dev-mw.kgonapi.com/withdraw") + .post(format!("{}/withdraw", self.api_config.k_url)) .header(reqwest::header::ACCEPT, "application/json") .header( reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded", ) - .header("k-secret", self.k_secret.as_str()) - .header("k-username", self.k_username.as_str()) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) .form(¶ms) .send() .await { Ok(res) => res, Err(err) => { - return Err(models::Error { code: 0, msg: None }); + return Err(Error { code: 0, msg: None }); } }; match res.status() { reqwest::StatusCode::OK => match res.json::().await { Ok(r) => Ok(r), - Err(e) => Err(models::Error { code: 0, msg: None }), + Err(e) => Err(Error { code: 0, msg: None }), }, - _ => Err(models::Error { code: 0, msg: None }), + _ => Err(Error { code: 0, msg: None }), } } } diff --git a/src/api/member_account/models.rs b/src/api/member_account/models.rs index f8f58a9..bd2fadc 100644 --- a/src/api/member_account/models.rs +++ b/src/api/member_account/models.rs @@ -1,16 +1,11 @@ use serde::{Deserialize, Serialize}; -pub struct Error { - pub code: i64, - pub msg: Option, -} - -pub struct FindBalanceRequest { +pub struct GetBalanceForUserRequest { pub username: String, } #[derive(Serialize, Deserialize, Debug)] -pub struct FindBalanceResponse { +pub struct _GetBalanceForUserResponse { pub code: i64, pub msg: Option, pub balance: i64, @@ -19,16 +14,30 @@ pub struct FindBalanceResponse { pub companies: i64, } -pub struct FindPartnerBalanceRequest {} +#[derive(Serialize, Deserialize, Debug)] +pub struct GetBalanceForUserResponse { + pub balance: i64, + pub balance_bota: i64, + pub balance_sum: i64, + pub companies: i64, +} + +pub struct GetBalanceForPartnerRequest {} #[derive(Serialize, Deserialize, Debug)] -pub struct FindPartnerBalanceResponse { +pub struct _GetBalanceForPartnerResponse { pub code: i64, pub msg: Option, pub balance: i64, pub balance_bota: i64, } +#[derive(Serialize, Deserialize, Debug)] +pub struct GetBalanceForPartnerResponse { + pub balance: i64, + pub balance_bota: i64, +} + pub struct SaveDepositRequest { pub username: String, pub cash_type: Option, diff --git a/src/api/mod.rs b/src/api/mod.rs index 0e5fc3e..4bb32ef 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,4 +1,6 @@ pub mod betting; +pub mod core; pub mod game; pub mod member; pub mod member_account; +pub mod vendor; diff --git a/src/api/vendor/api.rs b/src/api/vendor/api.rs new file mode 100644 index 0000000..3853e27 --- /dev/null +++ b/src/api/vendor/api.rs @@ -0,0 +1,76 @@ +use super::models; +use crate::api::core::models::Error; +use crate::core; + +/// +pub struct Api { + client: reqwest::Client, + api_config: core::config::ApiConfig, +} + +impl std::fmt::Debug for Api { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("Api of api.kgon.identity").finish() + } +} + +impl Api { + /// + pub fn new(api_config: core::config::ApiConfig) -> Api { + Api { + client: reqwest::Client::new(), + api_config, + } + } + + /// + pub async fn list_vendors( + &self, + data: models::ListVendorsRequest, + ) -> Result { + let res = match self + .client + .post(format!("{}/vendors", self.api_config.k_url)) + .header(reqwest::header::ACCEPT, "application/json") + .header( + reqwest::header::CONTENT_TYPE, + "application/x-www-form-urlencoded", + ) + .header("k-secret", self.api_config.k_secret.as_str()) + .header("k-username", self.api_config.k_username.as_str()) + .send() + .await + { + Ok(res) => res, + Err(e) => { + return Err(Error { + code: -1, + msg: Some(e.to_string()), + }); + } + }; + + match res.status() { + reqwest::StatusCode::OK => match res.json::().await { + Ok(r) => { + if r.code != 0 { + return Err(Error { + code: r.code, + msg: r.msg, + }); + } + + Ok(models::ListVendorsResponse { vendors: r.vendors }) + } + Err(e) => Err(Error { + code: -1, + msg: Some(e.to_string()), + }), + }, + _ => Err(Error { + code: -1, + msg: None, + }), + } + } +} diff --git a/src/api/vendor/mod.rs b/src/api/vendor/mod.rs new file mode 100644 index 0000000..b6d267a --- /dev/null +++ b/src/api/vendor/mod.rs @@ -0,0 +1,7 @@ +//! +//! + +/// +pub mod api; +/// +pub mod models; diff --git a/src/api/vendor/models.rs b/src/api/vendor/models.rs new file mode 100644 index 0000000..bc918eb --- /dev/null +++ b/src/api/vendor/models.rs @@ -0,0 +1,29 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Vendor { + pub id: i64, + pub company_id: i64, + pub vendor_id: i64, + pub max_bet_casino: i64, + pub max_bet_slot: i64, + pub is_enable: String, + pub bet_count: i64, + pub key: String, + pub name: String, + pub category: String, +} + +pub struct ListVendorsRequest {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct _ListVendorsResponse { + pub code: i64, + pub msg: Option, + pub vendors: Vec, +} + +#[derive(Debug)] +pub struct ListVendorsResponse { + pub vendors: Vec, +} diff --git a/src/core/config.rs b/src/core/config.rs new file mode 100644 index 0000000..64a82af --- /dev/null +++ b/src/core/config.rs @@ -0,0 +1,6 @@ +#[derive(Debug, Clone)] +pub struct ApiConfig { + pub k_url: String, + pub k_username: String, + pub k_secret: String, +} diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..ef68c36 --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1 @@ +pub mod config; diff --git a/src/main.rs b/src/main.rs index 74371a8..e2b7416 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use std::env; mod api; mod compositions; +mod core; mod repositories; mod schedulers; mod services; @@ -35,7 +36,7 @@ async fn main() -> Result<(), Box> { None => "".to_string(), }; - let k_secret = match env::var_os("K_SECRET") { + let k_url = match env::var_os("K_URL") { Some(v) => v.into_string().unwrap(), None => "".to_string(), }; @@ -43,8 +44,16 @@ async fn main() -> Result<(), Box> { Some(v) => v.into_string().unwrap(), None => "".to_string(), }; + let k_secret = match env::var_os("K_SECRET") { + Some(v) => v.into_string().unwrap(), + None => "".to_string(), + }; - let mut sched = tokio_cron_scheduler::JobScheduler::new().await?; + let api_config = core::config::ApiConfig { + k_url, + k_username, + k_secret, + }; let manager = ConnectionManager::::new(url_db); let pool = Pool::builder() @@ -61,35 +70,48 @@ async fn main() -> Result<(), Box> { let member_service = services::member::service::Service::new( connection_server_broker.clone(), queue_server_broker.clone(), - k_secret.clone(), - k_username.clone(), ); let member_account_service = services::member_account::service::Service::new( connection_server_broker.clone(), queue_server_broker.clone(), - k_secret.clone(), - k_username.clone(), ); let game_service = services::game::service::Service::new( connection_server_broker.clone(), queue_server_broker.clone(), - k_secret.clone(), - k_username.clone(), ); let betting_service = services::betting::service::Service::new( connection_server_broker.clone(), queue_server_broker.clone(), - k_secret.clone(), - k_username.clone(), ); - let vendor_scheduler = schedulers::vendor::scheduler::Scheduler::new(pool.clone(), sched.clone()); - vendor_scheduler.queue().await; + let mut sched = tokio_cron_scheduler::JobScheduler::new().await?; - let start = sched.start().await; - if start.is_err() { - panic!("Error starting scheduler"); - } + let member_scheduler = schedulers::member::scheduler::Scheduler::get_instance( + pool.clone(), + sched.clone(), + api_config.clone(), + )?; + member_scheduler.queue().await; + let balance_scheduler = schedulers::balance::scheduler::Scheduler::get_instance( + pool.clone(), + sched.clone(), + api_config.clone(), + )?; + balance_scheduler.queue().await; + let vendor_scheduler = schedulers::vendor::scheduler::Scheduler::get_instance( + pool.clone(), + sched.clone(), + api_config.clone(), + )?; + vendor_scheduler.queue().await; + let game_scheduler = schedulers::game::scheduler::Scheduler::get_instance( + pool.clone(), + sched.clone(), + api_config.clone(), + )?; + game_scheduler.queue().await; + + let _h_scheduler = sched.start().await?; println!("Server service [beteran-api-kgon-server-service] is started"); diff --git a/src/repositories/game/models.rs b/src/repositories/game/models.rs index 5d461a0..a762de6 100644 --- a/src/repositories/game/models.rs +++ b/src/repositories/game/models.rs @@ -67,6 +67,28 @@ pub struct ModifyGame { pub image: Option, } +/// +#[derive(Insertable, AsChangeset, Debug, Clone)] +#[table_name = "api_kgon_games"] +pub struct UpsertGame { + /// + pub id: i64, + /// + pub vendor_id: i64, + /// + pub key: String, + /// + pub names: String, + /// + pub platform: String, + /// + pub category: String, + /// + pub game_type: String, + /// + pub image: Option, +} + /// #[derive(Debug, Clone)] pub struct FindAllSearch { diff --git a/src/repositories/game/repository.rs b/src/repositories/game/repository.rs index 7438a0a..2c48769 100644 --- a/src/repositories/game/repository.rs +++ b/src/repositories/game/repository.rs @@ -39,6 +39,33 @@ impl Repository { Ok(inserted) } + /// + pub fn upserts( + &self, + conn: &diesel::PgConnection, + upsert_games: Vec, + ) -> Result { + use api_kgon_games::dsl; + use diesel::pg::upsert::excluded; + + let affected = diesel::insert_into(api_kgon_games::table) + .values(upsert_games) + .on_conflict(dsl::id) + .do_update() + .set(( + dsl::vendor_id.eq(excluded(dsl::vendor_id)), + dsl::key.eq(excluded(dsl::key)), + dsl::names.eq(excluded(dsl::names)), + dsl::platform.eq(excluded(dsl::platform)), + dsl::category.eq(excluded(dsl::category)), + dsl::game_type.eq(excluded(dsl::game_type)), + dsl::image.eq(excluded(dsl::image)), + )) + .execute(conn)?; + + Ok(affected) + } + /// pub fn select( &self, @@ -66,16 +93,16 @@ impl Repository { if let Some(sp) = s.vendor_id { q = q.filter(api_kgon_games::dsl::vendor_id.eq(sp)); } - if let Some(sp) = s.key_like { + if let Some(sp) = &s.key_like { q = q.filter(api_kgon_games::dsl::key.like(sp)); } - if let Some(sp) = s.platform_like { + if let Some(sp) = &s.platform_like { q = q.filter(api_kgon_games::dsl::platform.like(sp)); } - if let Some(sp) = s.category_like { + if let Some(sp) = &s.category_like { q = q.filter(api_kgon_games::dsl::category.like(sp)); } - if let Some(sp) = s.game_type_like { + if let Some(sp) = &s.game_type_like { q = q.filter(api_kgon_games::dsl::game_type.like(sp)); } } @@ -95,16 +122,16 @@ impl Repository { if let Some(sp) = s.vendor_id { q = q.filter(api_kgon_games::dsl::vendor_id.eq(sp)); } - if let Some(sp) = s.key_like { + if let Some(sp) = &s.key_like { q = q.filter(api_kgon_games::dsl::key.like(sp)); } - if let Some(sp) = s.platform_like { + if let Some(sp) = &s.platform_like { q = q.filter(api_kgon_games::dsl::platform.like(sp)); } - if let Some(sp) = s.category_like { + if let Some(sp) = &s.category_like { q = q.filter(api_kgon_games::dsl::category.like(sp)); } - if let Some(sp) = s.game_type_like { + if let Some(sp) = &s.game_type_like { q = q.filter(api_kgon_games::dsl::game_type.like(sp)); } } diff --git a/src/repositories/member/models.rs b/src/repositories/member/models.rs index 0b8d7e5..947bdd9 100644 --- a/src/repositories/member/models.rs +++ b/src/repositories/member/models.rs @@ -16,7 +16,7 @@ pub struct Member { /// pub companies: i64, /// - pub oriental_play: bool, + pub oriental_play: String, /// pub member_id: uuid::Uuid, /// @@ -40,7 +40,7 @@ pub struct NewMember { /// pub companies: i64, /// - pub oriental_play: bool, + pub oriental_play: String, /// pub member_id: uuid::Uuid, } @@ -49,6 +49,18 @@ pub struct NewMember { #[derive(AsChangeset, Debug, Clone)] #[table_name = "api_kgon_members"] pub struct ModifyMember { + /// + pub balance: i64, + /// + pub balance_bota: i64, + /// + pub oriental_play: String, +} + +/// +#[derive(AsChangeset, Debug, Clone)] +#[table_name = "api_kgon_members"] +pub struct ModifyMemberForBalance { /// pub balance: i64, /// @@ -57,15 +69,13 @@ pub struct ModifyMember { pub balance_sum: i64, /// pub companies: i64, - /// - pub oriental_play: bool, } /// #[derive(Debug, Clone)] pub struct FindAllSearch { /// - pub oriental_play: Option, + pub oriental_play: Option, } /// #[derive(Debug, Clone)] diff --git a/src/repositories/member/repository.rs b/src/repositories/member/repository.rs index 2f959cf..1898d6e 100644 --- a/src/repositories/member/repository.rs +++ b/src/repositories/member/repository.rs @@ -86,7 +86,7 @@ impl Repository { let mut q = api_kgon_members::table.into_boxed(); if let Some(s) = &find_all.search { - if let Some(sp) = s.oriental_play { + if let Some(sp) = &s.oriental_play { q = q.filter(api_kgon_members::dsl::oriental_play.eq(sp)); } } @@ -103,7 +103,7 @@ impl Repository { let mut q = api_kgon_members::table.into_boxed(); if let Some(s) = &find_all.search { - if let Some(sp) = s.oriental_play { + if let Some(sp) = &s.oriental_play { q = q.filter(api_kgon_members::dsl::oriental_play.eq(sp)); } } @@ -189,6 +189,21 @@ impl Repository { .map(|c| c as u64) } + /// + pub fn update_balance( + &self, + conn: &diesel::PgConnection, + id: i64, + modify: &models::ModifyMemberForBalance, + ) -> Result { + use api_kgon_members::dsl; + + diesel::update(dsl::api_kgon_members.filter(dsl::id.eq(id))) + .set(modify) + .execute(conn) + .map(|c| c as u64) + } + /// pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result { use api_kgon_members::dsl; diff --git a/src/repositories/member/schema.rs b/src/repositories/member/schema.rs index d9c6ec7..dafaa84 100644 --- a/src/repositories/member/schema.rs +++ b/src/repositories/member/schema.rs @@ -15,7 +15,7 @@ table! { /// companies -> BigInt, /// - oriental_play -> Bool, + oriental_play -> Text, /// member_id -> Uuid, /// diff --git a/src/repositories/mod.rs b/src/repositories/mod.rs index d2a9a94..5ad1b99 100644 --- a/src/repositories/mod.rs +++ b/src/repositories/mod.rs @@ -1,4 +1,6 @@ pub mod balance; pub mod game; pub mod member; +pub mod synchronization; +pub mod synchronization_history; pub mod vendor; diff --git a/src/repositories/synchronization/mod.rs b/src/repositories/synchronization/mod.rs new file mode 100644 index 0000000..bef7c9e --- /dev/null +++ b/src/repositories/synchronization/mod.rs @@ -0,0 +1,9 @@ +//! +//! + +/// +pub mod models; +/// +pub mod repository; +/// +pub mod schema; diff --git a/src/repositories/synchronization/models.rs b/src/repositories/synchronization/models.rs new file mode 100644 index 0000000..5399930 --- /dev/null +++ b/src/repositories/synchronization/models.rs @@ -0,0 +1,39 @@ +use super::schema::api_kgon_synchronizations; + +pub static ITEM_MEMBERS: &str = "members"; +pub static ITEM_BALANCE_PARTNER: &str = "balance_partner"; +pub static ITEM_BALANCE_USER: &str = "balance_user"; +pub static ITEM_VENDORS: &str = "vendors"; +pub static ITEM_GAMES: &str = "games"; + +/// +#[derive(Eq, Hash, Identifiable, Queryable, PartialEq, Debug, Clone)] +#[table_name = "api_kgon_synchronizations"] +pub struct Synchronization { + /// + pub id: i64, + /// + pub item: String, + /// + pub last_code: i64, + /// + pub synchronized_at: i64, +} + +/// +#[derive(Insertable, Debug, Clone)] +#[table_name = "api_kgon_synchronizations"] +pub struct NewSynchronization { + /// + pub item: String, + /// + pub last_code: i64, +} + +/// +#[derive(AsChangeset, Debug, Clone)] +#[table_name = "api_kgon_synchronizations"] +pub struct ModifySynchronization { + /// + pub last_code: i64, +} diff --git a/src/repositories/synchronization/repository.rs b/src/repositories/synchronization/repository.rs new file mode 100644 index 0000000..9e6e552 --- /dev/null +++ b/src/repositories/synchronization/repository.rs @@ -0,0 +1,103 @@ +//! +//! +use super::{models, schema::api_kgon_synchronizations}; +use diesel::prelude::*; +use diesel::result::Error; + +/// +pub struct Repository {} + +impl std::fmt::Debug for Repository { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("Repository of api_kgon_synchronizations") + .finish() + } +} + +impl Default for Repository { + fn default() -> Self { + Self::new() + } +} + +impl Repository { + /// + pub fn new() -> Repository { + Repository {} + } + + /// + pub fn insert( + &self, + conn: &diesel::PgConnection, + new_member: &models::NewSynchronization, + ) -> Result { + let inserted = diesel::insert_into(api_kgon_synchronizations::table) + .values(new_member) + .get_result::(conn)?; + + Ok(inserted) + } + + /// + pub fn select( + &self, + conn: &diesel::PgConnection, + id: i64, + ) -> Result, Error> { + match api_kgon_synchronizations::table + .find(id) + .first::(conn) + { + Ok(m) => Ok(Some(m)), + Err(e) => match e { + diesel::result::Error::NotFound => Ok(None), + _ => Err(e), + }, + } + } + + /// + pub fn select_by_item( + &self, + conn: &diesel::PgConnection, + item: String, + ) -> Result, Error> { + use api_kgon_synchronizations::dsl; + + match api_kgon_synchronizations::table + .filter(dsl::item.eq(item)) + .first::(conn) + { + Ok(m) => Ok(Some(m)), + Err(e) => match e { + diesel::result::Error::NotFound => Ok(None), + _ => Err(e), + }, + } + } + + /// + pub fn update( + &self, + conn: &diesel::PgConnection, + id: i64, + modify: &models::ModifySynchronization, + ) -> Result { + use api_kgon_synchronizations::dsl; + + diesel::update(dsl::api_kgon_synchronizations.filter(dsl::id.eq(id))) + .set(modify) + .execute(conn) + .map(|c| c as u64) + } + + /// + pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result { + use api_kgon_synchronizations::dsl; + + diesel::delete(api_kgon_synchronizations::table.filter(dsl::id.eq(id))) + .execute(conn) + .map(|c| c as u64) + } +} diff --git a/src/repositories/synchronization/schema.rs b/src/repositories/synchronization/schema.rs new file mode 100644 index 0000000..e881f55 --- /dev/null +++ b/src/repositories/synchronization/schema.rs @@ -0,0 +1,16 @@ +//! +//! + +table! { + /// + api_kgon_synchronizations(id) { + /// + id -> BigInt, + /// + item -> Text, + /// + last_code -> BigInt, + /// + synchronized_at -> BigInt, + } +} diff --git a/src/repositories/synchronization_history/mod.rs b/src/repositories/synchronization_history/mod.rs new file mode 100644 index 0000000..bef7c9e --- /dev/null +++ b/src/repositories/synchronization_history/mod.rs @@ -0,0 +1,9 @@ +//! +//! + +/// +pub mod models; +/// +pub mod repository; +/// +pub mod schema; diff --git a/src/repositories/synchronization_history/models.rs b/src/repositories/synchronization_history/models.rs new file mode 100644 index 0000000..5730800 --- /dev/null +++ b/src/repositories/synchronization_history/models.rs @@ -0,0 +1,56 @@ +use super::schema::api_kgon_synchronization_history; +use beteran_common_rust as bcr; + +/// +#[derive(Eq, Hash, Identifiable, Queryable, PartialEq, Debug, Clone)] +#[table_name = "api_kgon_synchronization_history"] +pub struct SynchronizationHistory { + /// + pub id: i64, + /// + pub item: String, + /// + pub start_at: i64, + /// + pub complete_at: i64, + /// + pub code: i64, + /// + pub message: Option, + /// + pub created_at: i64, +} + +/// +#[derive(Insertable, Debug, Clone)] +#[table_name = "api_kgon_synchronization_history"] +pub struct NewSynchronizationHistory { + /// + pub item: String, + /// + pub start_at: i64, + /// + pub complete_at: i64, + /// + pub code: i64, + /// + pub message: Option, +} + +/// +#[derive(Debug, Clone)] +pub struct FindAllSearch { + /// + pub item: Option, + /// + pub code: Option, +} +/// +#[derive(Debug, Clone)] +pub struct FindAll { + pub search: Option, + /// + pub pagination: Option, + /// + pub sorts: Option>, +} diff --git a/src/repositories/synchronization_history/repository.rs b/src/repositories/synchronization_history/repository.rs new file mode 100644 index 0000000..7859648 --- /dev/null +++ b/src/repositories/synchronization_history/repository.rs @@ -0,0 +1,160 @@ +//! +//! +use super::{models, schema::api_kgon_synchronization_history}; +use beteran_common_rust as bcr; +use diesel::prelude::*; +use diesel::result::Error; + +/// +pub struct Repository {} + +impl std::fmt::Debug for Repository { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("Repository of api_kgon_synchronization_history") + .finish() + } +} + +impl Default for Repository { + fn default() -> Self { + Self::new() + } +} + +impl Repository { + /// + pub fn new() -> Repository { + Repository {} + } + + /// + pub fn insert( + &self, + conn: &diesel::PgConnection, + new_member: &models::NewSynchronizationHistory, + ) -> Result { + let inserted = diesel::insert_into(api_kgon_synchronization_history::table) + .values(new_member) + .get_result::(conn)?; + + Ok(inserted) + } + + /// + pub fn select( + &self, + conn: &diesel::PgConnection, + id: i64, + ) -> Result, Error> { + match api_kgon_synchronization_history::table + .find(id) + .first::(conn) + { + Ok(m) => Ok(Some(m)), + Err(e) => match e { + diesel::result::Error::NotFound => Ok(None), + _ => Err(e), + }, + } + } + + /// + pub fn select_all_count( + &self, + conn: &diesel::PgConnection, + find_all: &models::FindAll, + ) -> Result { + let mut q = api_kgon_synchronization_history::table.into_boxed(); + + if let Some(s) = &find_all.search { + if let Some(sp) = &s.item { + q = q.filter(api_kgon_synchronization_history::dsl::item.eq(sp)); + } + if let Some(sp) = s.code { + q = q.filter(api_kgon_synchronization_history::dsl::code.eq(sp)); + } + } + + q.count().get_result(conn) + } + + /// + pub fn select_all( + &self, + conn: &diesel::PgConnection, + find_all: &models::FindAll, + ) -> Result, Error> { + let mut q = api_kgon_synchronization_history::table.into_boxed(); + + if let Some(s) = &find_all.search { + if let Some(sp) = &s.item { + q = q.filter(api_kgon_synchronization_history::dsl::item.eq(sp)); + } + if let Some(sp) = s.code { + q = q.filter(api_kgon_synchronization_history::dsl::code.eq(sp)); + } + } + + if let Some(p) = &find_all.pagination { + let page = p.page.unwrap_or(1); + + if let Some(page_size) = p.page_size { + q = q.offset(((page - 1) * page_size) as i64); + q = q.limit(page_size as i64); + } + } + if let Some(orderbys) = &find_all.sorts { + for s in orderbys { + match s { + bcr::models::pagination::Sort::ASC(property) => match property.as_str() { + "item" => { + q = q.order_by(api_kgon_synchronization_history::item.asc()); + } + "start_at" => { + q = q.order_by(api_kgon_synchronization_history::start_at.asc()); + } + "complete_at" => { + q = q.order_by(api_kgon_synchronization_history::complete_at.asc()); + } + "code" => { + q = q.order_by(api_kgon_synchronization_history::code.asc()); + } + "created_at" => { + q = q.order_by(api_kgon_synchronization_history::created_at.asc()); + } + _ => {} + }, + bcr::models::pagination::Sort::DESC(property) => match property.as_str() { + "item" => { + q = q.order_by(api_kgon_synchronization_history::item.desc()); + } + "start_at" => { + q = q.order_by(api_kgon_synchronization_history::start_at.desc()); + } + "complete_at" => { + q = q.order_by(api_kgon_synchronization_history::complete_at.desc()); + } + "code" => { + q = q.order_by(api_kgon_synchronization_history::code.desc()); + } + "created_at" => { + q = q.order_by(api_kgon_synchronization_history::created_at.desc()); + } + _ => {} + }, + }; + } + } + + q.load::(conn) + } + + /// + pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result { + use api_kgon_synchronization_history::dsl; + + diesel::delete(api_kgon_synchronization_history::table.filter(dsl::id.eq(id))) + .execute(conn) + .map(|c| c as u64) + } +} diff --git a/src/repositories/synchronization_history/schema.rs b/src/repositories/synchronization_history/schema.rs new file mode 100644 index 0000000..5be09b3 --- /dev/null +++ b/src/repositories/synchronization_history/schema.rs @@ -0,0 +1,22 @@ +//! +//! + +table! { + /// + api_kgon_synchronization_history(id) { + /// + id -> BigInt, + /// + item -> Text, + /// + start_at -> BigInt, + /// + complete_at -> BigInt, + /// + code -> BigInt, + /// + message -> Nullable, + /// + created_at -> BigInt, + } +} diff --git a/src/repositories/vendor/models.rs b/src/repositories/vendor/models.rs index d26031d..f8ddb60 100644 --- a/src/repositories/vendor/models.rs +++ b/src/repositories/vendor/models.rs @@ -22,7 +22,7 @@ pub struct Vendor { /// pub max_bet_slot: i64, /// - pub is_enable: bool, + pub is_enable: String, /// pub bet_count: i64, /// @@ -52,7 +52,7 @@ pub struct NewVendor { /// pub max_bet_slot: i64, /// - pub is_enable: bool, + pub is_enable: String, /// pub bet_count: i64, } @@ -76,7 +76,33 @@ pub struct ModifyVendor { /// pub max_bet_slot: i64, /// - pub is_enable: bool, + pub is_enable: String, + /// + pub bet_count: i64, +} + +/// +#[derive(Insertable, AsChangeset, Debug, Clone)] +#[table_name = "api_kgon_vendors"] +pub struct UpsertVendor { + /// + pub id: i64, + /// + pub company_id: i64, + /// + pub vendor_id: i64, + /// + pub key: String, + /// + pub name: String, + /// + pub category: String, + /// + pub max_bet_casino: i64, + /// + pub max_bet_slot: i64, + /// + pub is_enable: String, /// pub bet_count: i64, } @@ -95,7 +121,7 @@ pub struct FindAllSearch { /// pub category_like: Option, /// - pub is_enable: Option, + pub is_enable: Option, } /// #[derive(Debug, Clone)] diff --git a/src/repositories/vendor/repository.rs b/src/repositories/vendor/repository.rs index db69782..bbc70f1 100644 --- a/src/repositories/vendor/repository.rs +++ b/src/repositories/vendor/repository.rs @@ -39,6 +39,35 @@ impl Repository { Ok(inserted) } + /// + pub fn upserts( + &self, + conn: &diesel::PgConnection, + upsert_vendors: Vec, + ) -> Result { + use api_kgon_vendors::dsl; + use diesel::pg::upsert::excluded; + + let affected = diesel::insert_into(api_kgon_vendors::table) + .values(upsert_vendors) + .on_conflict(dsl::id) + .do_update() + .set(( + dsl::company_id.eq(excluded(dsl::company_id)), + dsl::vendor_id.eq(excluded(dsl::vendor_id)), + dsl::key.eq(excluded(dsl::key)), + dsl::name.eq(excluded(dsl::name)), + dsl::category.eq(excluded(dsl::category)), + dsl::max_bet_casino.eq(excluded(dsl::max_bet_casino)), + dsl::max_bet_slot.eq(excluded(dsl::max_bet_slot)), + dsl::is_enable.eq(excluded(dsl::is_enable)), + dsl::bet_count.eq(excluded(dsl::bet_count)), + )) + .execute(conn)?; + + Ok(affected) + } + /// pub fn select( &self, @@ -72,16 +101,16 @@ impl Repository { if let Some(sp) = s.vendor_id { q = q.filter(api_kgon_vendors::dsl::vendor_id.eq(sp)); } - if let Some(sp) = s.key_like { + if let Some(sp) = &s.key_like { q = q.filter(api_kgon_vendors::dsl::key.like(sp)); } - if let Some(sp) = s.name_like { + if let Some(sp) = &s.name_like { q = q.filter(api_kgon_vendors::dsl::name.like(sp)); } - if let Some(sp) = s.category_like { + if let Some(sp) = &s.category_like { q = q.filter(api_kgon_vendors::dsl::category.like(sp)); } - if let Some(sp) = s.is_enable { + if let Some(sp) = &s.is_enable { q = q.filter(api_kgon_vendors::dsl::is_enable.eq(sp)); } } @@ -104,16 +133,16 @@ impl Repository { if let Some(sp) = s.vendor_id { q = q.filter(api_kgon_vendors::dsl::vendor_id.eq(sp)); } - if let Some(sp) = s.key_like { + if let Some(sp) = &s.key_like { q = q.filter(api_kgon_vendors::dsl::key.like(sp)); } - if let Some(sp) = s.name_like { + if let Some(sp) = &s.name_like { q = q.filter(api_kgon_vendors::dsl::name.like(sp)); } - if let Some(sp) = s.category_like { + if let Some(sp) = &s.category_like { q = q.filter(api_kgon_vendors::dsl::category.like(sp)); } - if let Some(sp) = s.is_enable { + if let Some(sp) = &s.is_enable { q = q.filter(api_kgon_vendors::dsl::is_enable.eq(sp)); } } diff --git a/src/repositories/vendor/schema.rs b/src/repositories/vendor/schema.rs index 4d3729f..1da6328 100644 --- a/src/repositories/vendor/schema.rs +++ b/src/repositories/vendor/schema.rs @@ -21,7 +21,7 @@ table! { /// max_bet_slot -> BigInt, /// - is_enable -> Bool, + is_enable -> Text, /// bet_count -> BigInt, /// diff --git a/src/schedulers/balance/scheduler.rs b/src/schedulers/balance/scheduler.rs index 90f4a48..b580aef 100644 --- a/src/schedulers/balance/scheduler.rs +++ b/src/schedulers/balance/scheduler.rs @@ -1,5 +1,27 @@ +use crate::api; +use crate::core; +use crate::repositories; +use diesel::{ + r2d2::{ConnectionManager, Pool}, + PgConnection, +}; +use once_cell::sync::OnceCell; +use std::sync::Arc; +use tokio_cron_scheduler::{Job, JobScheduler}; + +static G_INSTANCE: OnceCell> = OnceCell::new(); + /// -pub struct Scheduler {} +pub struct Scheduler { + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + synchronization_history_repository: repositories::synchronization_history::repository::Repository, + balance_repository: repositories::balance::repository::Repository, + member_repository: repositories::member::repository::Repository, + member_api: api::member::api::Api, + member_account_api: api::member_account::api::Api, +} impl std::fmt::Debug for Scheduler { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -9,7 +31,204 @@ impl std::fmt::Debug for Scheduler { impl Scheduler { /// - pub fn new() -> Scheduler { - Scheduler {} + pub fn get_instance( + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + ) -> Result<&'static Arc, Box> { + let instance = G_INSTANCE + .get_or_try_init(|| -> Result, Box> { + let s = Scheduler { + pool, + sched, + api_config: api_config.clone(), + synchronization_history_repository: + repositories::synchronization_history::repository::Repository::new(), + balance_repository: repositories::balance::repository::Repository::new(), + member_repository: repositories::member::repository::Repository::new(), + member_api: api::member::api::Api::new(api_config.clone()), + member_account_api: api::member_account::api::Api::new(api_config.clone()), + }; + + Ok(Arc::new(s)) + }) + .expect(""); + + Ok(instance) + } + + pub async fn queue(&'static self) -> Result<(), std::boxed::Box> { + self.balance_for_user().await?; + self.balance_for_partner().await?; + + Ok(()) + } + + async fn add_history( + &'static self, + conn: &diesel::PgConnection, + item: String, + start_at: i64, + code: i64, + message: Option, + ) -> Result<(), Box> { + let complete_at = (chrono::Utc::now()).timestamp(); + + self + .synchronization_history_repository + .insert( + conn, + &repositories::synchronization_history::models::NewSynchronizationHistory { + item, + start_at, + complete_at, + code, + message, + }, + ) + .expect("synchronization_history insert"); + + Ok(()) + } + + async fn balance_for_user(&'static self) -> Result<(), Box> { + let j_synchronization = Job::new_async("0 0 0/1 * * *", move |_uuid, _l| { + Box::pin(async move { + let start_at = (chrono::Utc::now()).timestamp(); + let conn = self.pool.get().expect("conn"); + + let req = api::member::models::ListMembersRequest { group_key: None }; + let res = match self.member_api.list_members(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_BALANCE_USER.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("list_members"); + + for u in res.users { + let req = api::member_account::models::GetBalanceForUserRequest { + username: u.site_username, + }; + let res = match self.member_account_api.get_balance_for_user(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_BALANCE_USER.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("get_balance_for_user"); + + let modify_member = repositories::member::models::ModifyMemberForBalance { + balance: res.balance, + balance_bota: res.balance_bota, + balance_sum: res.balance_sum, + companies: res.companies, + }; + + self + .member_repository + .update_balance(&conn, u.id, &modify_member) + .expect("member update_balance"); + } + + self.add_history( + &conn, + repositories::synchronization::models::ITEM_BALANCE_USER.to_string(), + start_at, + 0, + None, + ); + }) + })?; + + self.sched.add(j_synchronization).await; + + Ok(()) + } + + async fn balance_for_partner(&'static self) -> Result<(), Box> { + let j_synchronization = Job::new_async("0 0 0/1 * * *", move |_uuid, _l| { + Box::pin(async move { + let start_at = (chrono::Utc::now()).timestamp(); + let conn = self.pool.get().expect("conn"); + + let req = api::member_account::models::GetBalanceForPartnerRequest {}; + let res = match self.member_account_api.get_balance_for_partner(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_BALANCE_PARTNER.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("list_members"); + + match self + .balance_repository + .select(&conn) + .expect("balance select") + { + Some(b) => { + self + .balance_repository + .update( + &conn, + b.id, + &repositories::balance::models::ModifyBalance { + balance: res.balance, + balance_bota: res.balance_bota, + }, + ) + .expect("balance update"); + } + None => { + self + .balance_repository + .insert( + &conn, + &repositories::balance::models::NewBalance { + balance: res.balance, + balance_bota: res.balance_bota, + }, + ) + .expect("balance insert"); + } + } + + self.add_history( + &conn, + repositories::synchronization::models::ITEM_BALANCE_PARTNER.to_string(), + start_at, + 0, + None, + ); + }) + })?; + + self.sched.add(j_synchronization).await; + + Ok(()) } } diff --git a/src/schedulers/game/scheduler.rs b/src/schedulers/game/scheduler.rs index 90f4a48..5cdb035 100644 --- a/src/schedulers/game/scheduler.rs +++ b/src/schedulers/game/scheduler.rs @@ -1,5 +1,26 @@ +use crate::api; +use crate::core; +use crate::repositories; +use diesel::{ + r2d2::{ConnectionManager, Pool}, + PgConnection, +}; +use once_cell::sync::OnceCell; +use std::sync::Arc; +use tokio_cron_scheduler::{Job, JobScheduler}; + +static G_INSTANCE: OnceCell> = OnceCell::new(); + /// -pub struct Scheduler {} +pub struct Scheduler { + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + synchronization_history_repository: repositories::synchronization_history::repository::Repository, + vendor_repository: repositories::vendor::repository::Repository, + game_repository: repositories::game::repository::Repository, + game_api: api::game::api::Api, +} impl std::fmt::Debug for Scheduler { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -9,7 +30,135 @@ impl std::fmt::Debug for Scheduler { impl Scheduler { /// - pub fn new() -> Scheduler { - Scheduler {} + pub fn get_instance( + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + ) -> Result<&'static Arc, Box> { + let instance = G_INSTANCE + .get_or_try_init(|| -> Result, Box> { + let s = Scheduler { + pool, + sched, + api_config: api_config.clone(), + synchronization_history_repository: + repositories::synchronization_history::repository::Repository::new(), + vendor_repository: repositories::vendor::repository::Repository::new(), + game_repository: repositories::game::repository::Repository::new(), + game_api: api::game::api::Api::new(api_config.clone()), + }; + + Ok(Arc::new(s)) + }) + .expect(""); + + Ok(instance) + } + + pub async fn queue(&'static self) -> Result<(), std::boxed::Box> { + self.list_vendors().await?; + + Ok(()) + } + + async fn add_history( + &'static self, + conn: &diesel::PgConnection, + item: String, + start_at: i64, + code: i64, + message: Option, + ) -> Result<(), Box> { + let complete_at = (chrono::Utc::now()).timestamp(); + + self + .synchronization_history_repository + .insert( + conn, + &repositories::synchronization_history::models::NewSynchronizationHistory { + item, + start_at, + complete_at, + code, + message, + }, + ) + .expect("synchronization_history insert"); + + Ok(()) + } + + async fn list_vendors(&'static self) -> Result<(), Box> { + let j_synchronization = Job::new_async("0 0 0/1 * * *", move |_uuid, _l| { + Box::pin(async move { + let start_at = (chrono::Utc::now()).timestamp(); + let conn = self.pool.get().expect("conn"); + + let vendors = self + .vendor_repository + .select_all( + &conn, + &repositories::vendor::models::FindAll { + pagination: None, + sorts: None, + search: None, + }, + ) + .expect("vendor select_all"); + + let mut upsert_games: Vec = vec![]; + + for v in vendors { + let req = api::game::models::ListGamesRequest { + vendor_key: v.key.clone(), + }; + let res = match self.game_api.list_games(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_VENDORS.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("list_games"); + + for g in res.games { + upsert_games.push(repositories::game::models::UpsertGame { + id: g.id, + vendor_id: v.id, + key: g.key.clone(), + names: serde_json::to_string(&g.names).expect("names"), + platform: g.platform.clone(), + category: g.category.clone(), + game_type: g.game_type.clone(), + image: g.image, + }); + } + } + + let affected = self + .game_repository + .upserts(&conn, upsert_games) + .expect("game upsert"); + + self.add_history( + &conn, + repositories::synchronization::models::ITEM_GAMES.to_string(), + start_at, + 0, + None, + ); + }) + })?; + + self.sched.add(j_synchronization).await; + + Ok(()) } } diff --git a/src/schedulers/member/scheduler.rs b/src/schedulers/member/scheduler.rs index e483b19..43ed92b 100644 --- a/src/schedulers/member/scheduler.rs +++ b/src/schedulers/member/scheduler.rs @@ -1,7 +1,25 @@ -use tokio_cron_scheduler::{Job, JobScheduler, JobToRun}; +use crate::api; +use crate::core; +use crate::repositories; +use diesel::{ + r2d2::{ConnectionManager, Pool}, + PgConnection, +}; +use once_cell::sync::OnceCell; +use std::sync::Arc; +use tokio_cron_scheduler::{Job, JobScheduler}; + +static G_INSTANCE: OnceCell> = OnceCell::new(); /// -pub struct Scheduler {} +pub struct Scheduler { + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + synchronization_history_repository: repositories::synchronization_history::repository::Repository, + member_repository: repositories::member::repository::Repository, + member_api: api::member::api::Api, +} impl std::fmt::Debug for Scheduler { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -11,9 +29,111 @@ impl std::fmt::Debug for Scheduler { impl Scheduler { /// - pub fn new() -> Scheduler { - let mut sched = JobScheduler::new(); + pub fn get_instance( + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + ) -> Result<&'static Arc, Box> { + let instance = G_INSTANCE + .get_or_try_init(|| -> Result, Box> { + let s = Scheduler { + pool, + sched, + api_config: api_config.clone(), + synchronization_history_repository: + repositories::synchronization_history::repository::Repository::new(), + member_repository: repositories::member::repository::Repository::new(), + member_api: api::member::api::Api::new(api_config.clone()), + }; - Scheduler {} + Ok(Arc::new(s)) + }) + .expect(""); + + Ok(instance) + } + + pub async fn queue(&'static self) -> Result<(), std::boxed::Box> { + self.list_members().await?; + + Ok(()) + } + + async fn add_history( + &'static self, + conn: &diesel::PgConnection, + item: String, + start_at: i64, + code: i64, + message: Option, + ) -> Result<(), Box> { + let complete_at = (chrono::Utc::now()).timestamp(); + + self + .synchronization_history_repository + .insert( + conn, + &repositories::synchronization_history::models::NewSynchronizationHistory { + item, + start_at, + complete_at, + code, + message, + }, + ) + .expect("synchronization_history insert"); + + Ok(()) + } + + async fn list_members(&'static self) -> Result<(), Box> { + let j_synchronization = Job::new_async("0 0 0/1 * * *", move |_uuid, _l| { + Box::pin(async move { + let start_at = (chrono::Utc::now()).timestamp(); + let conn = self.pool.get().expect("conn"); + + let req = api::member::models::ListMembersRequest { group_key: None }; + let res = match self.member_api.list_members(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_MEMBERS.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("list_members"); + + for u in res.users { + let modify_member = repositories::member::models::ModifyMember { + balance: u.cash, + balance_bota: u.cash_bota, + oriental_play: u.oriental_play, + }; + + self + .member_repository + .update(&conn, u.id, &modify_member) + .expect("member update"); + } + + self.add_history( + &conn, + repositories::synchronization::models::ITEM_MEMBERS.to_string(), + start_at, + 0, + None, + ); + }) + })?; + + self.sched.add(j_synchronization).await; + + Ok(()) } } diff --git a/src/schedulers/vendor/scheduler.rs b/src/schedulers/vendor/scheduler.rs index 929ae0f..68452cb 100644 --- a/src/schedulers/vendor/scheduler.rs +++ b/src/schedulers/vendor/scheduler.rs @@ -1,17 +1,24 @@ -use std::time::Duration; - +use crate::api; +use crate::core; use crate::repositories; use diesel::{ r2d2::{ConnectionManager, Pool}, PgConnection, }; +use once_cell::sync::OnceCell; +use std::sync::Arc; use tokio_cron_scheduler::{Job, JobScheduler}; +static G_INSTANCE: OnceCell> = OnceCell::new(); + /// pub struct Scheduler { pool: Pool>, sched: JobScheduler, + api_config: core::config::ApiConfig, + synchronization_history_repository: repositories::synchronization_history::repository::Repository, vendor_repository: repositories::vendor::repository::Repository, + vendor_api: api::vendor::api::Api, } impl std::fmt::Debug for Scheduler { @@ -22,65 +29,119 @@ impl std::fmt::Debug for Scheduler { impl Scheduler { /// - pub fn new(pool: Pool>, sched: JobScheduler) -> Scheduler { - Scheduler { - pool, - sched, - vendor_repository: repositories::vendor::repository::Repository::new(), - } + pub fn get_instance( + pool: Pool>, + sched: JobScheduler, + api_config: core::config::ApiConfig, + ) -> Result<&'static Arc, Box> { + let instance = G_INSTANCE + .get_or_try_init(|| -> Result, Box> { + let s = Scheduler { + pool, + sched, + api_config: api_config.clone(), + synchronization_history_repository: + repositories::synchronization_history::repository::Repository::new(), + vendor_repository: repositories::vendor::repository::Repository::new(), + vendor_api: api::vendor::api::Api::new(api_config.clone()), + }; + + Ok(Arc::new(s)) + }) + .expect(""); + + Ok(instance) } - pub async fn queue(&self) -> Result<(), std::boxed::Box> { - self.list_members().await?; + pub async fn queue(&'static self) -> Result<(), std::boxed::Box> { + self.list_vendors().await?; Ok(()) } - async fn list_members(&self) -> Result<(), Box> { - let mut jj = Job::new_repeated(Duration::from_secs(60), |_uuid, _l| { - println!("{:?} I'm repeated every 60 seconds", chrono::Utc::now()); - }) - .unwrap(); + async fn add_history( + &'static self, + conn: &diesel::PgConnection, + item: String, + start_at: i64, + code: i64, + message: Option, + ) -> Result<(), Box> { + let complete_at = (chrono::Utc::now()).timestamp(); - jj.on_start_notification_add( - &self.sched, - Box::new(|job_id, notification_id, type_of_notification| { - Box::pin(async move { - println!( - "Job {:?} was started, notification {:?} ran ({:?})", - job_id, notification_id, type_of_notification - ); - }) - }), - ) - .await; + self + .synchronization_history_repository + .insert( + conn, + &repositories::synchronization_history::models::NewSynchronizationHistory { + item, + start_at, + complete_at, + code, + message, + }, + ) + .expect("synchronization_history insert"); - jj.on_stop_notification_add( - &self.sched, - Box::new(|job_id, notification_id, type_of_notification| { - Box::pin(async move { - println!( - "Job {:?} was completed, notification {:?} ran ({:?})", - job_id, notification_id, type_of_notification - ); - }) - }), - ) - .await; + Ok(()) + } - jj.on_removed_notification_add( - &self.sched, - Box::new(|job_id, notification_id, type_of_notification| { - Box::pin(async move { - println!( - "Job {:?} was removed, notification {:?} ran ({:?})", - job_id, notification_id, type_of_notification - ); - }) - }), - ) - .await; - self.sched.add(jj).await; + async fn list_vendors(&'static self) -> Result<(), Box> { + let j_synchronization = Job::new_async("0 0 0/1 * * *", move |_uuid, _l| { + Box::pin(async move { + let start_at = (chrono::Utc::now()).timestamp(); + let conn = self.pool.get().expect("conn"); + + let req = api::vendor::models::ListVendorsRequest {}; + let res = match self.vendor_api.list_vendors(req).await { + Ok(r) => Ok(r), + Err(e) => { + self.add_history( + &conn, + repositories::synchronization::models::ITEM_VENDORS.to_string(), + start_at, + e.code, + e.msg.clone(), + ); + + Err(e) + } + } + .expect("list_vendors"); + + let upsert_vendors: Vec = res + .vendors + .iter() + .map(|d| repositories::vendor::models::UpsertVendor { + id: d.id, + company_id: d.company_id, + vendor_id: d.vendor_id, + key: d.key.clone(), + name: d.name.clone(), + category: d.category.clone(), + max_bet_casino: d.max_bet_casino, + max_bet_slot: d.max_bet_slot, + is_enable: d.is_enable.clone(), + bet_count: d.bet_count, + }) + .collect(); + + let affected = self + .vendor_repository + .upserts(&conn, upsert_vendors) + .expect("vendor upsert"); + + self.add_history( + &conn, + repositories::synchronization::models::ITEM_VENDORS.to_string(), + start_at, + 0, + None, + ); + }) + })?; + + self.sched.add(j_synchronization).await; Ok(()) } diff --git a/src/services/betting/service.rs b/src/services/betting/service.rs index ba4fce6..a3f7696 100644 --- a/src/services/betting/service.rs +++ b/src/services/betting/service.rs @@ -2,8 +2,6 @@ pub struct Service { connection_broker: nats::asynk::Connection, queue_broker: String, - k_secret: String, - k_username: String, } impl std::fmt::Debug for Service { @@ -14,27 +12,34 @@ impl std::fmt::Debug for Service { impl Service { /// - pub fn new( - connection_broker: nats::asynk::Connection, - queue_broker: String, - k_secret: String, - k_username: String, - ) -> Service { + pub fn new(connection_broker: nats::asynk::Connection, queue_broker: String) -> Service { Service { connection_broker, queue_broker, - k_secret, - k_username, } } pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box> { - futures::try_join!(self.create_member(), self.list_members(), self.get_member(),).map(|_| ()) + futures::try_join!( + self.list_history(), + self.list_history_for_pragmatic(), + self.list_history_for_evolution(), + self.statistics(), + ) + .map(|_| ()) } - async fn list_history(&self) -> Result<(), Box> {} - async fn list_history_for_pragmatic(&self) -> Result<(), Box> {} - async fn list_history_for_evolution(&self) -> Result<(), Box> {} + async fn list_history(&self) -> Result<(), Box> { + Ok(()) + } + async fn list_history_for_pragmatic(&self) -> Result<(), Box> { + Ok(()) + } + async fn list_history_for_evolution(&self) -> Result<(), Box> { + Ok(()) + } - async fn statistics(&self) -> Result<(), Box> {} + async fn statistics(&self) -> Result<(), Box> { + Ok(()) + } } diff --git a/src/services/game/service.rs b/src/services/game/service.rs index 3178e3c..aa5dbfe 100644 --- a/src/services/game/service.rs +++ b/src/services/game/service.rs @@ -2,8 +2,6 @@ pub struct Service { connection_broker: nats::asynk::Connection, queue_broker: String, - k_secret: String, - k_username: String, } impl std::fmt::Debug for Service { @@ -14,26 +12,25 @@ impl std::fmt::Debug for Service { impl Service { /// - pub fn new( - connection_broker: nats::asynk::Connection, - queue_broker: String, - k_secret: String, - k_username: String, - ) -> Service { + pub fn new(connection_broker: nats::asynk::Connection, queue_broker: String) -> Service { Service { connection_broker, queue_broker, - k_secret, - k_username, } } pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box> { - futures::try_join!(self.create_member(), self.list_members(), self.get_member(),).map(|_| ()) + futures::try_join!(self.list_vendors(), self.list_games(), self.execute_game(),).map(|_| ()) } - async fn list_vendors(&self) -> Result<(), Box> {} - async fn list_games(&self) -> Result<(), Box> {} + async fn list_vendors(&self) -> Result<(), Box> { + Ok(()) + } + async fn list_games(&self) -> Result<(), Box> { + Ok(()) + } - async fn execute_game(&self) -> Result<(), Box> {} + async fn execute_game(&self) -> Result<(), Box> { + Ok(()) + } } diff --git a/src/services/member/service.rs b/src/services/member/service.rs index ff9f7c4..dd5d10a 100644 --- a/src/services/member/service.rs +++ b/src/services/member/service.rs @@ -2,8 +2,6 @@ pub struct Service { connection_broker: nats::asynk::Connection, queue_broker: String, - k_secret: String, - k_username: String, } impl std::fmt::Debug for Service { @@ -14,17 +12,10 @@ impl std::fmt::Debug for Service { impl Service { /// - pub fn new( - connection_broker: nats::asynk::Connection, - queue_broker: String, - k_secret: String, - k_username: String, - ) -> Service { + pub fn new(connection_broker: nats::asynk::Connection, queue_broker: String) -> Service { Service { connection_broker, queue_broker, - k_secret, - k_username, } } @@ -32,9 +23,15 @@ impl Service { futures::try_join!(self.create_member(), self.list_members(), self.get_member(),).map(|_| ()) } - async fn create_member(&self) -> Result<(), Box> {} + async fn create_member(&self) -> Result<(), Box> { + Ok(()) + } - async fn list_members(&self) -> Result<(), Box> {} + async fn list_members(&self) -> Result<(), Box> { + Ok(()) + } - async fn get_member(&self) -> Result<(), Box> {} + async fn get_member(&self) -> Result<(), Box> { + Ok(()) + } } diff --git a/src/services/member_account/service.rs b/src/services/member_account/service.rs index 3ab0f0c..9e37433 100644 --- a/src/services/member_account/service.rs +++ b/src/services/member_account/service.rs @@ -2,8 +2,6 @@ pub struct Service { connection_broker: nats::asynk::Connection, queue_broker: String, - k_secret: String, - k_username: String, } impl std::fmt::Debug for Service { @@ -14,28 +12,34 @@ impl std::fmt::Debug for Service { impl Service { /// - pub fn new( - connection_broker: nats::asynk::Connection, - queue_broker: String, - k_secret: String, - k_username: String, - ) -> Service { + pub fn new(connection_broker: nats::asynk::Connection, queue_broker: String) -> Service { Service { connection_broker, queue_broker, - k_secret, - k_username, } } - pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box> { - futures::try_join!(self.create_member(), self.list_members(), self.get_member(),).map(|_| ()) + futures::try_join!( + self.create_deposit(), + self.create_withdraw(), + self.list_partner_balnace(), + self.list_user_balnace(), + ) + .map(|_| ()) } - async fn create_deposit(&self) -> Result<(), Box> {} - async fn create_withdraw(&self) -> Result<(), Box> {} + async fn create_deposit(&self) -> Result<(), Box> { + Ok(()) + } + async fn create_withdraw(&self) -> Result<(), Box> { + Ok(()) + } - async fn list_partner_balnace(&self) -> Result<(), Box> {} - async fn list_user_balnace(&self) -> Result<(), Box> {} + async fn list_partner_balnace(&self) -> Result<(), Box> { + Ok(()) + } + async fn list_user_balnace(&self) -> Result<(), Box> { + Ok(()) + } }