diff --git a/.github/img/rustler.svg b/.github/img/rustler.svg
index fe6126a..3e148fd 100644
--- a/.github/img/rustler.svg
+++ b/.github/img/rustler.svg
@@ -6,10 +6,6 @@
}
-
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 00de050..18edc72 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,7 +1,7 @@
{
"files.exclude": {
// 🧩 modules
- "migration": true,
+ // "migration": true,
// "entities": true,
// ⚙️
@@ -24,12 +24,12 @@
// 🗑️
"check_size.py": true,
"*.code-workspace": true,
- // ".gitignore": true,
+ ".gitignore": true,
".vscode": true,
".git": true,
// 🗄️ database
- "rustler.db": true,
+ // "rustler.db": true,
"rustler.db-shm": true,
"rustler.db-wal": true,
"rustler.db.bkp": true,
diff --git a/Cargo.lock b/Cargo.lock
index 67b1f78..955ae61 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -317,9 +317,9 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
[[package]]
name = "async-trait"
-version = "0.1.78"
+version = "0.1.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85"
+checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
dependencies = [
"proc-macro2",
"quote",
@@ -358,7 +358,7 @@ dependencies = [
"bitflags 1.3.2",
"bytes",
"futures-util",
- "http",
+ "http 0.2.12",
"http-body",
"hyper",
"itoa",
@@ -384,7 +384,7 @@ dependencies = [
"async-trait",
"bytes",
"futures-util",
- "http",
+ "http 0.2.12",
"http-body",
"mime",
"rustversion",
@@ -566,14 +566,16 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
-version = "0.4.35"
+version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
+checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
dependencies = [
"android-tzdata",
"iana-time-zone",
+ "js-sys",
"num-traits",
"serde",
+ "wasm-bindgen",
"windows-targets 0.52.4",
]
@@ -703,6 +705,12 @@ dependencies = [
"typenum",
]
+[[package]]
+name = "data-encoding"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
+
[[package]]
name = "der"
version = "0.7.8"
@@ -1066,6 +1074,18 @@ dependencies = [
"wasi",
]
+[[package]]
+name = "getset"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "gimli"
version = "0.28.1"
@@ -1113,7 +1133,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
- "http",
+ "http 0.2.12",
"indexmap 2.2.6",
"slab",
"tokio",
@@ -1214,6 +1234,17 @@ dependencies = [
"itoa",
]
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http-body"
version = "0.4.6"
@@ -1221,7 +1252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
- "http",
+ "http 0.2.12",
"pin-project-lite",
]
@@ -1248,13 +1279,13 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
- "http",
+ "http 0.2.12",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
- "socket2 0.5.6",
+ "socket2 0.4.10",
"tokio",
"tower-service",
"tracing",
@@ -1470,13 +1501,17 @@ dependencies = [
[[package]]
name = "lool"
-version = "0.0.5"
+version = "0.1.4"
source = "sparse+http://lugit.local/api/packages/lucodear/cargo/"
-checksum = "c727e0c375380178e0b15f8f54f249e5e2a9e72c20475e8a7807f4c72d253106"
+checksum = "4320ce16557a892f40c0a776371ac0c3cda2c9312c83065a4ab2a1facf571539"
dependencies = [
"bitflags 2.5.0",
+ "chrono",
"eyre",
"log",
+ "num-traits",
+ "tokio",
+ "tokio_schedule",
]
[[package]]
@@ -2258,14 +2293,30 @@ dependencies = [
name = "rustler"
version = "0.0.0-alpha.0"
dependencies = [
+ "chrono",
"dotenvy",
"entities",
"eyre",
"grpc",
"lool",
+ "rustlers",
"tokio",
]
+[[package]]
+name = "rustlers"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "chrono",
+ "entities",
+ "eyre",
+ "getset",
+ "lool",
+ "tokio-tungstenite",
+ "tonic-build",
+]
+
[[package]]
name = "rustversion"
version = "1.0.14"
@@ -3015,9 +3066,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.36.0"
+version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
+checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [
"backtrace",
"bytes",
@@ -3062,6 +3113,18 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-tungstenite"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38"
+dependencies = [
+ "futures-util",
+ "log",
+ "tokio",
+ "tungstenite",
+]
+
[[package]]
name = "tokio-util"
version = "0.7.10"
@@ -3076,6 +3139,16 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "tokio_schedule"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b4a14ab1658c39d137ebcc5fbaab364c9922a6cc04ab48b364546c2e6022256"
+dependencies = [
+ "chrono",
+ "tokio",
+]
+
[[package]]
name = "toml_datetime"
version = "0.6.5"
@@ -3105,7 +3178,7 @@ dependencies = [
"base64",
"bytes",
"h2",
- "http",
+ "http 0.2.12",
"http-body",
"hyper",
"hyper-timeout",
@@ -3218,6 +3291,25 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+[[package]]
+name = "tungstenite"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1"
+dependencies = [
+ "byteorder",
+ "bytes",
+ "data-encoding",
+ "http 1.1.0",
+ "httparse",
+ "log",
+ "rand",
+ "sha1",
+ "thiserror",
+ "url",
+ "utf-8",
+]
+
[[package]]
name = "typenum"
version = "1.17.0"
@@ -3274,6 +3366,12 @@ version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
[[package]]
name = "utf8parse"
version = "0.2.1"
diff --git a/Cargo.toml b/Cargo.toml
index 1272264..8d41e8b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,21 +22,26 @@ name = "rustler"
path = "app/main.rs"
[workspace]
-members = [".", "migration", "entities", "grpc"]
+members = [".", "migration", "entities", "grpc", "rustlers"]
[workspace.dependencies]
-lool = { version = "0.0.5", registry = "lugit" } # crates: disable-check
+lool = { version = "0.1.4", registry = "lugit" } # crates: disable-check
eyre = { version = "0.6.12", default-features = false }
+tokio-tungstenite = { version = "0.21.0" }
[dependencies]
# internal
entities = { path = "entities" }
grpc = { path = "grpc" }
+rustlers = { path = "rustlers" }
# workspace
-eyre = { workspace = true, default-features = false, features = ["auto-install"] }
-lool = { workspace = true, features = ["logger", "macros", "cli-stylize"] }
+eyre = { workspace = true, default-features = false, features = [
+ "auto-install",
+] }
+lool = { workspace = true }
# external
-tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }
+tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] }
dotenvy = "0.15.7"
+chrono = "0.4.37"
diff --git a/Taskfile.yaml b/Taskfile.yaml
index 8d3c82c..4cec3b4 100644
--- a/Taskfile.yaml
+++ b/Taskfile.yaml
@@ -34,6 +34,11 @@ tasks:
cmds:
- cargo +nightly fmt --all
+ test:
+ desc: 🧪 test lool
+ cmds:
+ - cargo nextest run --all-features --workspace
+
lint:
desc: 🧶 lint rustler
cmds:
diff --git a/app/main.rs b/app/main.rs
index 7997f22..4507978 100644
--- a/app/main.rs
+++ b/app/main.rs
@@ -1,7 +1,7 @@
use {
dotenvy::dotenv,
eyre::Result,
- lool::logger::{info, ConsoleLogger, Level},
+ lool::logger::{info, ConsoleLogger, Level}, tokio::{join, select},
};
// TODO: here we will trigger the start of both the grpc server and the websocket gateway
@@ -13,8 +13,12 @@ async fn main() -> Result<()> {
dotenv()?;
let conn = entities::db::get_connection().await?;
+ let mut rustler = rustlers::svc::RustlersSvc::new(conn.clone()).await;
- grpc::server::start(conn.clone()).await?;
+ let (grpc_res, rustlers_res) = join! {
+ grpc::server::start(conn.clone()),
+ rustler.start(),
+ };
info!("Shutting down");
Ok(())
diff --git a/entities/Cargo.toml b/entities/Cargo.toml
index 037a431..a3ed977 100644
--- a/entities/Cargo.toml
+++ b/entities/Cargo.toml
@@ -11,7 +11,7 @@ path = "src/lib.rs"
[dependencies]
# common
eyre = { workspace = true, default-features = false }
-lool = { workspace = true }
+lool = { workspace = true, features = [ "cli", "cli.stylize", "macros", "logger" ] }
# external
sea-orm = { version = "0.12.15", features = [
diff --git a/entities/src/lib.rs b/entities/src/lib.rs
index ad52a1e..1d9a0a1 100644
--- a/entities/src/lib.rs
+++ b/entities/src/lib.rs
@@ -1,8 +1,28 @@
-pub mod market;
-pub mod ticker;
-
pub use sea_orm;
+mod orm {
+ #[path = "market.rs"] pub mod market;
+ #[path = "ticker.rs"] pub mod ticker;
+}
+
+mod services {
+ #[path = "market.rs"] pub mod market;
+ #[path = "ticker.rs"] pub mod ticker;
+}
+
+/// market entities and services
+pub mod market {
+ pub use super::orm::market::*;
+ pub use super::services::market::*;
+}
+
+/// ticker entities and services
+pub mod ticker {
+ pub use super::orm::ticker::*;
+ pub use super::services::ticker::*;
+}
+
+/// database connection stuff
pub mod db {
use {
eyre::Result,
@@ -25,14 +45,14 @@ pub mod db {
conn_str
}
- pub async fn get_connection() -> Result> {
+ pub async fn get_connection() -> Result {
let db_conn_str =
std::env::var(RUSTLER_DATABASE).unwrap_or_else(|_| get_default_conn_str());
let mut conn_opts = ConnectOptions::new(db_conn_str.to_owned());
conn_opts.sqlx_logging(false);
- let conn = Arc::new(Database::connect(conn_opts).await?);
+ let conn = Database::connect(conn_opts).await?;
conn.query_one(Statement::from_string(
DbBackend::Sqlite,
diff --git a/entities/src/market/svc.rs b/entities/src/market/svc.rs
deleted file mode 100644
index ba63b10..0000000
--- a/entities/src/market/svc.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use {
- super::{Entity as MarketEntity, Model as MarketModel},
- eyre::Result,
- sea_orm::{DatabaseConnection, EntityTrait, IntoActiveModel},
- std::{sync::Arc, time::Instant},
-};
-
-pub struct Service {
- conn: Arc,
-}
-
-impl Service {
- pub async fn new(conn: Arc) -> Self {
- Self { conn }
- }
-
- pub async fn get_all(&self) -> Result> {
- // let conn = self.conn.unwrap();
- let markets = MarketEntity::find().all(&*self.conn).await?;
- Ok(markets)
- }
-
- pub async fn create(&self, market: MarketModel) -> Result {
- let start = Instant::now();
- MarketEntity::insert(market.clone().into_active_model()).exec(&*self.conn).await?;
- println!("insert market model took {:?}", start.elapsed());
- Ok(market)
- }
-}
diff --git a/entities/src/market/mod.rs b/entities/src/orm/market.rs
similarity index 70%
rename from entities/src/market/mod.rs
rename to entities/src/orm/market.rs
index 3a277f5..402f366 100644
--- a/entities/src/market/mod.rs
+++ b/entities/src/orm/market.rs
@@ -1,7 +1,6 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15
-mod svc;
+
use sea_orm::entity::prelude::*;
-pub use svc::Service;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "market")]
@@ -10,13 +9,13 @@ pub struct Model {
pub id: String,
pub short_name: String,
pub full_name: String,
- pub opens_from: i32,
- pub opens_till: i32,
- pub open_time: String,
- pub close_time: String,
- pub pre_market_offset: i32,
- pub post_market_offset: i32,
- pub time_zone_offset: i32,
+ pub opens_from: Option,
+ pub opens_till: Option,
+ pub open_time: Option,
+ pub close_time: Option,
+ pub pre_market_offset: Option,
+ pub post_market_offset: Option,
+ pub time_zone_offset: Option,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
diff --git a/entities/src/ticker.rs b/entities/src/orm/ticker.rs
similarity index 94%
rename from entities/src/ticker.rs
rename to entities/src/orm/ticker.rs
index 2e3e94c..676ad4e 100644
--- a/entities/src/ticker.rs
+++ b/entities/src/orm/ticker.rs
@@ -29,4 +29,4 @@ impl Related for Entity {
}
}
-impl ActiveModelBehavior for ActiveModel {}
+impl ActiveModelBehavior for ActiveModel {}
\ No newline at end of file
diff --git a/entities/src/services/market.rs b/entities/src/services/market.rs
new file mode 100644
index 0000000..a04a8d3
--- /dev/null
+++ b/entities/src/services/market.rs
@@ -0,0 +1,37 @@
+use {
+ crate::{
+ market::{Entity as Market, Model as MarketModel},
+ ticker::{Entity as Ticker, Model as TickerModel},
+ },
+ eyre::Result,
+ sea_orm::{DatabaseConnection, DbErr, EntityTrait, IntoActiveModel}
+};
+
+pub struct Service {
+ conn: DatabaseConnection,
+}
+
+impl Service {
+ pub async fn new(conn: DatabaseConnection) -> Self {
+ Self { conn }
+ }
+
+ pub async fn get_all(&self) -> Result, DbErr> {
+ let markets = Market::find().all(&self.conn).await?;
+ Ok(markets)
+ }
+
+ pub async fn create(&self, market: MarketModel) -> Result {
+ Market::insert(market.clone().into_active_model()).exec(&self.conn).await?;
+ Ok(market)
+ }
+
+ pub async fn get_all_with_tickers(
+ &self,
+ ) -> Result)>, DbErr> {
+ let markets_with_tickers: Vec<(MarketModel, Vec)> =
+ Market::find().find_with_related(Ticker).all(&self.conn).await?;
+
+ Ok(markets_with_tickers)
+ }
+}
diff --git a/entities/src/services/ticker.rs b/entities/src/services/ticker.rs
new file mode 100644
index 0000000..bdf41d7
--- /dev/null
+++ b/entities/src/services/ticker.rs
@@ -0,0 +1,40 @@
+use {
+ crate::{
+ orm::ticker,
+ ticker::{Entity as Ticker, Model as TickerModel},
+ },
+ eyre::Result,
+ sea_orm::{ColumnTrait, DatabaseConnection, DbErr, EntityTrait, IntoActiveModel, QueryFilter}
+};
+
+pub struct Service {
+ conn: DatabaseConnection,
+}
+
+impl Service {
+ pub async fn new(conn: DatabaseConnection) -> Self {
+ Self { conn }
+ }
+
+ pub async fn get_all(&self) -> Result, DbErr> {
+ let tickers = Ticker::find().all(&self.conn).await?;
+ Ok(tickers)
+ }
+
+ pub async fn get(&self, id: String) -> Result