pub mod higher_order_candles; pub mod minute_candles; use chrono::Duration; use deadpool_postgres::Pool; use log::{error, warn}; use strum::IntoEnumIterator; use tokio::time::sleep; use crate::{ database::insert::build_candles_upsert_statement, structs::{candle::Candle, markets::MarketInfo, resolution::Resolution}, utils::AnyhowWrap, worker::candle_batching::minute_candles::batch_1m_candles, }; use self::higher_order_candles::batch_higher_order_candles; use super::metrics::METRIC_CANDLES_TOTAL; pub async fn batch_for_market(pool: &Pool, market: &MarketInfo) -> anyhow::Result<()> { loop { let market_clone = market.clone(); loop { sleep(Duration::milliseconds(2000).to_std()?).await; match batch_inner(pool, &market_clone).await { Ok(_) => {} Err(e) => { error!( "Batching thread failed for {:?} with error: {:?}", market_clone.name.clone(), e ); break; } }; } warn!("Restarting {:?} batching thread", market.name); } } async fn batch_inner(pool: &Pool, market: &MarketInfo) -> anyhow::Result<()> { let market_name = &market.name.clone(); let candles = batch_1m_candles(pool, market).await?; METRIC_CANDLES_TOTAL .with_label_values(&[market.name.as_str()]) .inc_by(candles.clone().len() as u64); save_candles(pool, candles).await?; for resolution in Resolution::iter() { if resolution == Resolution::R1m { continue; } let candles = batch_higher_order_candles(pool, market_name, resolution).await?; METRIC_CANDLES_TOTAL .with_label_values(&[market.name.as_str()]) .inc_by(candles.clone().len() as u64); save_candles(pool, candles).await?; } Ok(()) } async fn save_candles(pool: &Pool, candles: Vec) -> anyhow::Result<()> { if candles.len() == 0 { return Ok(()); } let upsert_statement = build_candles_upsert_statement(&candles); let client = pool.get().await.unwrap(); client .execute(&upsert_statement, &[]) .await .map_err_anyhow()?; Ok(()) }