mod hloc;
#[cfg(feature = "statistics")]
pub mod interval;
mod ticker;
mod trade;
mod volume;
pub use hloc::*;
pub use ticker::Ticker;
pub use trade::Trade;
pub use volume::Volume;
#[cfg(feature = "statistics")]
pub use inner::*;
#[cfg(feature = "statistics")]
mod inner {
use super::{interval::Interval, trade::TradeHistory, *};
use crate::{
domain::{
market::Market,
offer::{OfferId, OpenOffer},
CommandResult, FutureCommandResult,
},
prelude::*,
};
use std::{collections::HashSet, sync::Arc};
pub struct StatsCacheInner {
trades: TradeHistory,
ids: HashSet<OfferId>,
}
impl StatsCacheInner {
fn insert(&mut self, trade: Trade) -> CommandResult {
if self.ids.insert(trade.offer_id.clone()) {
self.trades.insert(trade);
CommandResult::Accepted
} else {
CommandResult::Ignored
}
}
fn bootstrap(&mut self, trades: Vec<Trade>) {
let mut ids = self.ids.clone();
self.trades.insert_all(
trades
.into_iter()
.filter(|t| ids.insert(t.offer_id.clone())),
);
self.ids = ids;
}
pub fn trades(&self) -> impl DoubleEndedIterator<Item = &Trade> {
self.trades.iter()
}
pub fn hloc(&self, query: HlocQuery) -> Vec<Hloc> {
Hloc::from_trades(&self.trades, query)
}
pub fn ticker<'a>(
&self,
market: Option<&'static Market>,
offers: impl Iterator<Item = &'a OpenOffer>,
) -> Vec<Ticker> {
Ticker::from_trades(&self.trades, market, offers)
}
pub fn volumes(
&self,
market: Option<&'static Market>,
interval: Option<Interval>,
) -> Vec<Volume> {
Volume::from_trades(&self.trades, market, interval)
}
}
#[derive(Clone)]
pub struct StatsCache {
inner: Arc<locks::RwLock<StatsCacheInner>>,
}
impl StatsCache {
pub fn new() -> Option<Self> {
Some(Self {
inner: Arc::new(locks::RwLock::new(StatsCacheInner {
trades: TradeHistory::new(),
ids: HashSet::new(),
})),
})
}
pub fn add(&self, trade: Trade) -> impl FutureCommandResult {
self.inner
.write()
.map(move |mut inner| inner.insert(trade))
.map_err(|_| MailboxError::Closed)
}
pub fn bootstrap(&self, trades: Vec<Trade>) -> impl Future<Item = (), Error = ()> {
self.inner
.write()
.map(move |mut inner| {
inner.bootstrap(trades);
})
.then(|_| Ok(()))
}
pub fn inner(
&self,
) -> impl Future<Item = locks::RwLockReadGuard<StatsCacheInner>, Error = ()> {
self.inner.read()
}
}
}
#[cfg(not(feature = "statistics"))]
pub use empty::*;
#[cfg(not(feature = "statistics"))]
mod empty {
#[derive(Clone)]
pub struct StatsCache;
impl StatsCache {
pub fn new() -> Option<Self> {
None
}
}
}