|
|
@@ -1,8 +1,12 @@
|
|
|
+pub mod traits;
|
|
|
+
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
use std::sync::{Arc, RwLock, Mutex};
|
|
|
+use anyhow::Result;
|
|
|
use tokio::sync::watch;
|
|
|
|
|
|
use crate::adapters::types::{Price, PriceId, SubscriptionId};
|
|
|
+use self::traits::*;
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
pub struct SubscriptionParams {
|
|
|
@@ -14,9 +18,9 @@ pub struct SubscriptionParams {
|
|
|
#[derive(Clone)]
|
|
|
pub struct ArgusState {
|
|
|
pub chain_id: String,
|
|
|
- pub subscription_state: Arc<SubscriptionState>,
|
|
|
- pub pyth_price_state: Arc<PythPriceState>,
|
|
|
- pub chain_price_state: Arc<ChainPriceState>,
|
|
|
+ subscription_state: Arc<SubscriptionState>,
|
|
|
+ pyth_price_state: Arc<PythPriceState>,
|
|
|
+ chain_price_state: Arc<ChainPriceState>,
|
|
|
pub stop_sender: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
|
|
}
|
|
|
|
|
|
@@ -30,6 +34,44 @@ impl ArgusState {
|
|
|
stop_sender: Arc::new(Mutex::new(None)),
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ pub fn subscription_reader(&self) -> Arc<dyn ReadSubscriptionState> {
|
|
|
+ self.subscription_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn subscription_writer(&self) -> Arc<dyn WriteSubscriptionState> {
|
|
|
+ self.subscription_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn pyth_price_reader(&self) -> Arc<dyn ReadPythPriceState> {
|
|
|
+ self.pyth_price_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn pyth_price_writer(&self) -> Arc<dyn WritePythPriceState> {
|
|
|
+ self.pyth_price_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn chain_price_reader(&self) -> Arc<dyn ReadChainPriceState> {
|
|
|
+ self.chain_price_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn chain_price_writer(&self) -> Arc<dyn WriteChainPriceState> {
|
|
|
+ self.chain_price_state.clone()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn system_control(&self) -> Arc<dyn SystemControl> {
|
|
|
+ Arc::new(SystemController {
|
|
|
+ stop_sender: self.stop_sender.clone(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn setup_stop_channel(&self) -> watch::Receiver<bool> {
|
|
|
+ let (tx, rx) = watch::channel(false);
|
|
|
+ let mut stop_sender = self.stop_sender.lock().expect("Mutex poisoned");
|
|
|
+ *stop_sender = Some(tx);
|
|
|
+ rx
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
pub struct SubscriptionState {
|
|
|
@@ -42,12 +84,14 @@ impl SubscriptionState {
|
|
|
subscriptions: RwLock::new(HashMap::new()),
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pub fn get_subscriptions(&self) -> HashMap<SubscriptionId, SubscriptionParams> {
|
|
|
+impl ReadSubscriptionState for SubscriptionState {
|
|
|
+ fn get_subscriptions(&self) -> HashMap<SubscriptionId, SubscriptionParams> {
|
|
|
self.subscriptions.read().expect("RwLock poisoned").clone()
|
|
|
}
|
|
|
|
|
|
- pub fn get_subscription(&self, id: &SubscriptionId) -> Option<SubscriptionParams> {
|
|
|
+ fn get_subscription(&self, id: &SubscriptionId) -> Option<SubscriptionParams> {
|
|
|
self.subscriptions
|
|
|
.read()
|
|
|
.expect("RwLock poisoned")
|
|
|
@@ -55,15 +99,7 @@ impl SubscriptionState {
|
|
|
.cloned()
|
|
|
}
|
|
|
|
|
|
- pub fn update_subscriptions(
|
|
|
- &self,
|
|
|
- subscriptions: HashMap<SubscriptionId, SubscriptionParams>,
|
|
|
- ) {
|
|
|
- let mut lock = self.subscriptions.write().expect("RwLock poisoned");
|
|
|
- *lock = subscriptions;
|
|
|
- }
|
|
|
-
|
|
|
- pub fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
+ fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
let subscriptions = self.subscriptions.read().expect("RwLock poisoned");
|
|
|
let mut feed_ids = HashSet::new();
|
|
|
|
|
|
@@ -77,6 +113,16 @@ impl SubscriptionState {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl WriteSubscriptionState for SubscriptionState {
|
|
|
+ fn update_subscriptions(
|
|
|
+ &self,
|
|
|
+ subscriptions: HashMap<SubscriptionId, SubscriptionParams>,
|
|
|
+ ) {
|
|
|
+ let mut lock = self.subscriptions.write().expect("RwLock poisoned");
|
|
|
+ *lock = subscriptions;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
pub struct PythPriceState {
|
|
|
prices: RwLock<HashMap<PriceId, Price>>,
|
|
|
feed_ids: RwLock<HashSet<PriceId>>,
|
|
|
@@ -89,8 +135,10 @@ impl PythPriceState {
|
|
|
feed_ids: RwLock::new(HashSet::new()),
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pub fn get_price(&self, feed_id: &PriceId) -> Option<Price> {
|
|
|
+impl ReadPythPriceState for PythPriceState {
|
|
|
+ fn get_price(&self, feed_id: &PriceId) -> Option<Price> {
|
|
|
self.prices
|
|
|
.read()
|
|
|
.expect("RwLock poisoned")
|
|
|
@@ -98,24 +146,26 @@ impl PythPriceState {
|
|
|
.cloned()
|
|
|
}
|
|
|
|
|
|
- pub fn update_price(&self, feed_id: PriceId, price: Price) {
|
|
|
+ fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
+ self.feed_ids.read().expect("RwLock poisoned").clone()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl WritePythPriceState for PythPriceState {
|
|
|
+ fn update_price(&self, feed_id: PriceId, price: Price) {
|
|
|
let mut prices = self.prices.write().expect("RwLock poisoned");
|
|
|
prices.insert(feed_id, price);
|
|
|
}
|
|
|
|
|
|
- pub fn update_prices(&self, prices: HashMap<PriceId, Price>) {
|
|
|
+ fn update_prices(&self, prices: HashMap<PriceId, Price>) {
|
|
|
let mut lock = self.prices.write().expect("RwLock poisoned");
|
|
|
lock.extend(prices);
|
|
|
}
|
|
|
|
|
|
- pub fn update_feed_ids(&self, feed_ids: HashSet<PriceId>) {
|
|
|
+ fn update_feed_ids(&self, feed_ids: HashSet<PriceId>) {
|
|
|
let mut lock = self.feed_ids.write().expect("RwLock poisoned");
|
|
|
*lock = feed_ids;
|
|
|
}
|
|
|
-
|
|
|
- pub fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
- self.feed_ids.read().expect("RwLock poisoned").clone()
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
pub struct ChainPriceState {
|
|
|
@@ -130,8 +180,10 @@ impl ChainPriceState {
|
|
|
feed_ids: RwLock::new(HashSet::new()),
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pub fn get_price(&self, feed_id: &PriceId) -> Option<Price> {
|
|
|
+impl ReadChainPriceState for ChainPriceState {
|
|
|
+ fn get_price(&self, feed_id: &PriceId) -> Option<Price> {
|
|
|
self.prices
|
|
|
.read()
|
|
|
.expect("RwLock poisoned")
|
|
|
@@ -139,22 +191,40 @@ impl ChainPriceState {
|
|
|
.cloned()
|
|
|
}
|
|
|
|
|
|
- pub fn update_price(&self, feed_id: PriceId, price: Price) {
|
|
|
+ fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
+ self.feed_ids.read().expect("RwLock poisoned").clone()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl WriteChainPriceState for ChainPriceState {
|
|
|
+ fn update_price(&self, feed_id: PriceId, price: Price) {
|
|
|
let mut prices = self.prices.write().expect("RwLock poisoned");
|
|
|
prices.insert(feed_id, price);
|
|
|
}
|
|
|
|
|
|
- pub fn update_prices(&self, prices: HashMap<PriceId, Price>) {
|
|
|
+ fn update_prices(&self, prices: HashMap<PriceId, Price>) {
|
|
|
let mut lock = self.prices.write().expect("RwLock poisoned");
|
|
|
lock.extend(prices);
|
|
|
}
|
|
|
|
|
|
- pub fn update_feed_ids(&self, feed_ids: HashSet<PriceId>) {
|
|
|
+ fn update_feed_ids(&self, feed_ids: HashSet<PriceId>) {
|
|
|
let mut lock = self.feed_ids.write().expect("RwLock poisoned");
|
|
|
*lock = feed_ids;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- pub fn get_feed_ids(&self) -> HashSet<PriceId> {
|
|
|
- self.feed_ids.read().expect("RwLock poisoned").clone()
|
|
|
+struct SystemController {
|
|
|
+ pub stop_sender: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
|
|
+}
|
|
|
+
|
|
|
+impl SystemControl for SystemController {
|
|
|
+ fn signal_shutdown(&self) -> Result<()> {
|
|
|
+ let sender = self.stop_sender.lock().expect("Mutex poisoned");
|
|
|
+ if let Some(sender) = &*sender {
|
|
|
+ sender.send(true)?;
|
|
|
+ Ok(())
|
|
|
+ } else {
|
|
|
+ Err(anyhow::anyhow!("Stop sender not initialized"))
|
|
|
+ }
|
|
|
}
|
|
|
}
|