Add RabbitMQ messaging

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-08-28 13:45:51 +03:00
parent fa509934ae
commit 9d3d51f23c
22 changed files with 1232 additions and 151 deletions

View File

@@ -1,11 +1,21 @@
[package]
name = "common"
name = "common"
version = "0.1.0"
edition = "2021"
[dependencies]
lapin = "2.3.1"
apca = "0.27.2"
deadpool = "0.9.5"
serde = { version = "1.0.188", features = ["derive"] }
sqlx = { version = "0.7.1", features = ["uuid", "time", "postgres"] }
time = { version = "0.3.27", features = ["serde"] }
deadpool-lapin = "0.10.0"
serde = { version = "1.0.188", features = [
"derive",
] }
sqlx = { version = "0.7.1", features = [
"uuid",
"time",
"postgres",
] }
time = { version = "0.3.27", features = [
"serde",
] }

View File

@@ -1,23 +0,0 @@
use apca::{ApiInfo, Client};
use deadpool::unmanaged::Pool;
use std::error::Error;
pub type AlpacaPool = Pool<Client>;
pub fn create_alpaca_pool(
apca_api_base_url: &str,
apca_api_key_id: &str,
apca_api_secret_key: &str,
num_clients: usize,
) -> Result<Pool<Client>, Box<dyn Error + Send + Sync>> {
let mut alpaca_clients = Vec::new();
for _ in 0..num_clients {
let client = Client::new(ApiInfo::from_parts(
apca_api_base_url,
apca_api_key_id,
apca_api_secret_key,
)?);
alpaca_clients.push(client);
}
Ok(Pool::from(alpaca_clients))
}

View File

@@ -1,11 +1,11 @@
use serde::{Deserialize, Serialize};
use sqlx::{error::BoxDynError, types::Uuid, Decode, Encode, FromRow, Postgres, Type};
use std::ops::Deref;
use time::PrimitiveDateTime;
use time::OffsetDateTime;
macro_rules! impl_apca_sqlx_traits {
($outer_type:ident, $inner_type:path, $fallback:expr) => {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Copy, PartialEq, Serialize, Deserialize)]
pub struct $outer_type($inner_type);
impl Deref for $outer_type {
@@ -43,7 +43,7 @@ macro_rules! impl_apca_sqlx_traits {
&self,
buf: &mut <Postgres as sqlx::database::HasArguments<'_>>::ArgumentBuffer,
) -> sqlx::encode::IsNull {
<String as Encode<Postgres>>::encode_by_ref(&self.0.as_ref().to_owned(), buf)
<String as Encode<Postgres>>::encode_by_ref(&self.0.as_ref().into(), buf)
}
}
@@ -74,13 +74,13 @@ pub struct Asset {
pub class: Class,
pub exchange: Exchange,
pub trading: bool,
pub date_added: PrimitiveDateTime,
pub date_added: OffsetDateTime,
}
#[derive(Clone, Debug, PartialEq, FromRow, Serialize, Deserialize)]
pub struct Bar {
pub timestamp: PrimitiveDateTime,
pub symbol_id: Uuid,
pub timestamp: OffsetDateTime,
pub asset_id: Uuid,
pub open: f64,
pub high: f64,
pub low: f64,

View File

@@ -1,2 +1,2 @@
pub mod alpaca;
pub mod pool;
pub mod database;

View File

@@ -0,0 +1,79 @@
use apca::{ApiInfo, Client};
use deadpool::{unmanaged::Pool, Runtime};
use deadpool_lapin::Hook;
use sqlx::postgres::PgPoolOptions;
use std::{env, error::Error};
pub type AlpacaPool = Pool<Client>;
pub async fn create_alpaca_pool(
apca_api_base_url: &str,
apca_api_key_id: &str,
apca_api_secret_key: &str,
num_clients: usize,
) -> Result<Pool<Client>, Box<dyn Error + Send + Sync>> {
let mut alpaca_clients = Vec::new();
for _ in 0..num_clients {
let client = Client::new(ApiInfo::from_parts(
apca_api_base_url,
apca_api_key_id,
apca_api_secret_key,
)?);
alpaca_clients.push(client);
}
Ok(Pool::from(alpaca_clients))
}
pub async fn create_alpaca_pool_from_env(
num_clients: usize,
) -> Result<Pool<Client>, Box<dyn Error + Send + Sync>> {
create_alpaca_pool(
&env::var("APCA_API_BASE_URL")?,
&env::var("APCA_API_KEY_ID")?,
&env::var("APCA_API_SECRET_KEY")?,
num_clients,
)
.await
}
pub async fn create_database_pool(
database_url: &str,
num_clients: usize,
) -> Result<sqlx::PgPool, Box<dyn Error + Send + Sync>> {
PgPoolOptions::new()
.max_connections(num_clients as u32)
.connect(database_url)
.await
.map_err(|e| e.into())
}
pub async fn create_database_pool_from_env(
num_clients: usize,
) -> Result<sqlx::PgPool, Box<dyn Error + Send + Sync>> {
create_database_pool(&env::var("DATABASE_URL")?, num_clients).await
}
pub type RabbitmqPool = deadpool_lapin::Pool;
pub async fn create_rabbitmq_pool(
rabbitmq_url: &str,
num_clients: usize,
post_create: impl Into<Hook>,
) -> Result<RabbitmqPool, Box<dyn Error + Send + Sync>> {
deadpool_lapin::Config {
url: Some(rabbitmq_url.into()),
..Default::default()
}
.builder(Some(Runtime::Tokio1))
.max_size(num_clients)
.post_create(post_create)
.build()
.map_err(|e| e.into())
}
pub async fn create_rabbitmq_pool_from_env(
num_clients: usize,
post_create: impl Into<Hook>,
) -> Result<deadpool_lapin::Pool, Box<dyn Error + Send + Sync>> {
create_rabbitmq_pool(&env::var("RABBITMQ_URL")?, num_clients, post_create).await
}