Skip to content

Commit c5a717e

Browse files
authored
refactor(agent): convert local store to an Api (#123)
1 parent 2d074fb commit c5a717e

File tree

10 files changed

+171
-256
lines changed

10 files changed

+171
-256
lines changed

src/agent.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,26 +118,18 @@ impl Agent {
118118
// Create the channels
119119
// TODO: make all components listen to shutdown signal
120120
let (shutdown_tx, _) = broadcast::channel(self.config.channel_capacities.shutdown);
121-
let (local_store_tx, local_store_rx) =
122-
mpsc::channel(self.config.channel_capacities.local_store);
123121
let (primary_keypair_loader_tx, primary_keypair_loader_rx) = mpsc::channel(10);
124122
let (secondary_keypair_loader_tx, secondary_keypair_loader_rx) = mpsc::channel(10);
125123

126124
// Create the Pythd Adapter.
127125
let adapter = Arc::new(
128-
pythd::adapter::Adapter::new(
129-
self.config.pythd_adapter.clone(),
130-
local_store_tx.clone(),
131-
logger.clone(),
132-
)
133-
.await,
126+
pythd::adapter::Adapter::new(self.config.pythd_adapter.clone(), logger.clone()).await,
134127
);
135128

136129
// Spawn the primary network
137130
jhs.extend(network::spawn_network(
138131
self.config.primary_network.clone(),
139132
network::Network::Primary,
140-
local_store_tx.clone(),
141133
primary_keypair_loader_tx,
142134
logger.new(o!("primary" => true)),
143135
adapter.clone(),
@@ -148,7 +140,6 @@ impl Agent {
148140
jhs.extend(network::spawn_network(
149141
config.clone(),
150142
network::Network::Secondary,
151-
local_store_tx.clone(),
152143
secondary_keypair_loader_tx,
153144
logger.new(o!("primary" => false)),
154145
adapter.clone(),
@@ -161,9 +152,6 @@ impl Agent {
161152
shutdown_tx.subscribe(),
162153
)));
163154

164-
// Spawn the Local Store
165-
jhs.push(store::local::spawn_store(local_store_rx, logger.clone()));
166-
167155
// Spawn the Pythd API Server
168156
jhs.push(tokio::spawn(rpc::run(
169157
self.config.pythd_api_server.clone(),
@@ -175,7 +163,6 @@ impl Agent {
175163
// Spawn the metrics server
176164
jhs.push(tokio::spawn(metrics::MetricsServer::spawn(
177165
self.config.metrics_server.bind_address,
178-
local_store_tx,
179166
logger.clone(),
180167
adapter,
181168
)));

src/agent/dashboard.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
use {
22
super::{
3-
pythd::adapter::global::GlobalStore,
3+
pythd::adapter::{
4+
global::GlobalStore,
5+
local::{
6+
LocalStore,
7+
PriceInfo,
8+
},
9+
},
410
solana::{
511
network::Network,
612
oracle::PriceEntry,
713
},
8-
store::local::{
9-
Message,
10-
PriceInfo,
11-
},
1214
},
1315
crate::agent::{
1416
metrics::MetricsServer,
@@ -34,7 +36,6 @@ use {
3436
},
3537
time::Duration,
3638
},
37-
tokio::sync::oneshot,
3839
typed_html::{
3940
dom::DOMTree,
4041
html,
@@ -45,22 +46,11 @@ use {
4546
impl MetricsServer {
4647
/// Create an HTML view of store data
4748
pub async fn render_dashboard(&self) -> Result<String, Box<dyn std::error::Error>> {
48-
// Prepare response channel for requests
49-
let (local_tx, local_rx) = oneshot::channel();
50-
5149
// Request price data from local and global store
52-
self.local_store_tx
53-
.send(Message::LookupAllPriceInfo {
54-
result_tx: local_tx,
55-
})
56-
.await?;
57-
50+
let local_data = LocalStore::get_all_price_infos(&*self.adapter).await;
5851
let global_data = GlobalStore::accounts_data(&*self.adapter, Network::Primary).await?;
5952
let global_metadata = GlobalStore::accounts_metadata(&*self.adapter).await?;
6053

61-
// Await the results
62-
let local_data = local_rx.await?;
63-
6454
let symbol_view =
6555
build_dashboard_data(local_data, global_data, global_metadata, &self.logger);
6656

src/agent/metrics.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
use {
2-
super::{
3-
pythd::adapter::Adapter,
4-
store::local::Message,
2+
super::pythd::adapter::{
3+
local::PriceInfo,
4+
Adapter,
55
},
66
crate::agent::{
77
solana::oracle::PriceEntry,
8-
store::{
9-
local::PriceInfo,
10-
PriceIdentifier,
11-
},
8+
store::PriceIdentifier,
129
},
1310
lazy_static::lazy_static,
1411
prometheus_client::{
@@ -34,10 +31,7 @@ use {
3431
},
3532
time::Instant,
3633
},
37-
tokio::sync::{
38-
mpsc,
39-
Mutex,
40-
},
34+
tokio::sync::Mutex,
4135
warp::{
4236
hyper::StatusCode,
4337
reply,
@@ -73,23 +67,19 @@ lazy_static! {
7367
/// Internal metrics server state, holds state needed for serving
7468
/// dashboard and metrics.
7569
pub struct MetricsServer {
76-
/// Used to pull the state of all symbols in local store
77-
pub local_store_tx: mpsc::Sender<Message>,
78-
pub start_time: Instant,
79-
pub logger: Logger,
80-
pub adapter: Arc<Adapter>,
70+
pub start_time: Instant,
71+
pub logger: Logger,
72+
pub adapter: Arc<Adapter>,
8173
}
8274

8375
impl MetricsServer {
8476
/// Instantiate a metrics API with a dashboard
8577
pub async fn spawn(
8678
addr: impl Into<SocketAddr> + 'static,
87-
local_store_tx: mpsc::Sender<Message>,
8879
logger: Logger,
8980
adapter: Arc<Adapter>,
9081
) {
9182
let server = MetricsServer {
92-
local_store_tx,
9383
start_time: Instant::now(),
9484
logger,
9585
adapter,

src/agent/pythd/adapter.rs

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use {
22
super::{
3-
super::store::{
4-
local,
5-
PriceIdentifier,
6-
},
3+
super::store::PriceIdentifier,
74
api::{
85
NotifyPrice,
96
NotifyPriceSched,
@@ -29,6 +26,7 @@ use {
2926

3027
pub mod api;
3128
pub mod global;
29+
pub mod local;
3230
pub use api::{
3331
notifier,
3432
AdapterApi,
@@ -68,14 +66,14 @@ pub struct Adapter {
6866
/// The fixed interval at which Notify Price Sched notifications are sent
6967
notify_price_sched_interval_duration: Duration,
7068

71-
/// Channel on which to communicate with the local store
72-
local_store_tx: mpsc::Sender<local::Message>,
73-
7469
/// The logger
7570
logger: Logger,
7671

7772
/// Global store for managing the unified state of Pyth-on-Solana networks.
7873
global_store: global::Store,
74+
75+
/// Local store for managing the unpushed state.
76+
local_store: local::Store,
7977
}
8078

8179
/// Represents a single Notify Price Sched subscription
@@ -95,19 +93,15 @@ struct NotifyPriceSubscription {
9593
}
9694

9795
impl Adapter {
98-
pub async fn new(
99-
config: Config,
100-
local_store_tx: mpsc::Sender<local::Message>,
101-
logger: Logger,
102-
) -> Self {
96+
pub async fn new(config: Config, logger: Logger) -> Self {
10397
let registry = &mut *PROMETHEUS_REGISTRY.lock().await;
10498
Adapter {
10599
global_store: global::Store::new(logger.clone(), registry),
100+
local_store: local::Store::new(logger.clone(), registry),
106101
subscription_id_seq: 1.into(),
107102
notify_price_sched_subscriptions: RwLock::new(HashMap::new()),
108103
notify_price_subscriptions: RwLock::new(HashMap::new()),
109104
notify_price_sched_interval_duration: config.notify_price_sched_interval_duration,
110-
local_store_tx,
111105
logger,
112106
}
113107
}
@@ -128,8 +122,9 @@ mod tests {
128122
},
129123
crate::agent::{
130124
pythd::{
131-
api,
125+
adapter::local::LocalStore,
132126
api::{
127+
self,
133128
NotifyPrice,
134129
NotifyPriceSched,
135130
PriceAccountMetadata,
@@ -140,7 +135,6 @@ mod tests {
140135
},
141136
},
142137
solana,
143-
store::local,
144138
},
145139
iobuffer::IoBuffer,
146140
pyth_sdk::Identifier,
@@ -172,29 +166,26 @@ mod tests {
172166
};
173167

174168
struct TestAdapter {
175-
adapter: Arc<Adapter>,
176-
local_store_rx: mpsc::Receiver<local::Message>,
177-
shutdown_tx: broadcast::Sender<()>,
178-
jh: JoinHandle<()>,
169+
adapter: Arc<Adapter>,
170+
shutdown_tx: broadcast::Sender<()>,
171+
jh: JoinHandle<()>,
179172
}
180173

181174
async fn setup() -> TestAdapter {
182175
// Create and spawn an adapter
183-
let (local_store_tx, local_store_rx) = mpsc::channel(1000);
184176
let notify_price_sched_interval_duration = Duration::from_nanos(10);
185177
let logger = slog_test::new_test_logger(IoBuffer::new());
186178
let config = Config {
187179
notify_price_sched_interval_duration,
188180
};
189-
let adapter = Arc::new(Adapter::new(config, local_store_tx, logger).await);
181+
let adapter = Arc::new(Adapter::new(config, logger).await);
190182
let (shutdown_tx, _) = broadcast::channel(1);
191183

192184
// Spawn Price Notifier
193185
let jh = tokio::spawn(notifier(adapter.clone(), shutdown_tx.subscribe()));
194186

195187
TestAdapter {
196188
adapter,
197-
local_store_rx,
198189
shutdown_tx,
199190
jh,
200191
}
@@ -1379,7 +1370,7 @@ mod tests {
13791370
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
13801371
async fn test_update_price() {
13811372
// Start the test adapter
1382-
let mut test_adapter = setup().await;
1373+
let test_adapter = setup().await;
13831374

13841375
// Send an Update Price message
13851376
let account = "CkMrDWtmFJZcmAUC11qNaWymbXQKvnRx4cq1QudLav7t"
@@ -1394,18 +1385,14 @@ mod tests {
13941385
.unwrap();
13951386

13961387
// Check that the local store indeed received the correct update
1397-
match test_adapter.local_store_rx.recv().await.unwrap() {
1398-
local::Message::Update {
1399-
price_identifier,
1400-
price_info,
1401-
} => {
1402-
assert_eq!(price_identifier, Identifier::new(account.to_bytes()));
1403-
assert_eq!(price_info.price, price);
1404-
assert_eq!(price_info.conf, conf);
1405-
assert_eq!(price_info.status, PriceStatus::Trading);
1406-
}
1407-
_ => panic!("Uexpected message received by local store from adapter"),
1408-
};
1388+
let price_infos = LocalStore::get_all_price_infos(&*test_adapter.adapter).await;
1389+
let price_info = price_infos
1390+
.get(&Identifier::new(account.to_bytes()))
1391+
.unwrap();
1392+
1393+
assert_eq!(price_info.price, price);
1394+
assert_eq!(price_info.conf, conf);
1395+
assert_eq!(price_info.status, PriceStatus::Trading);
14091396

14101397
let _ = test_adapter.shutdown_tx.send(());
14111398
test_adapter.jh.abort();

src/agent/pythd/adapter/api.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ use {
55
AllAccountsMetadata,
66
GlobalStore,
77
},
8+
local::{
9+
self,
10+
LocalStore,
11+
},
812
Adapter,
913
NotifyPriceSchedSubscription,
1014
NotifyPriceSubscription,
@@ -28,10 +32,7 @@ use {
2832
network::Network,
2933
oracle::PriceEntry,
3034
},
31-
store::{
32-
local,
33-
PriceIdentifier,
34-
},
35+
store::PriceIdentifier,
3536
},
3637
anyhow::{
3738
anyhow,
@@ -357,18 +358,18 @@ impl AdapterApi for Adapter {
357358
conf: Conf,
358359
status: String,
359360
) -> Result<()> {
360-
self.local_store_tx
361-
.send(local::Message::Update {
362-
price_identifier: pyth_sdk::Identifier::new(account.to_bytes()),
363-
price_info: local::PriceInfo {
364-
status: Adapter::map_status(&status)?,
365-
price,
366-
conf,
367-
timestamp: Utc::now().naive_utc(),
368-
},
369-
})
370-
.await
371-
.map_err(|_| anyhow!("failed to send update to local store"))
361+
LocalStore::update(
362+
self,
363+
pyth_sdk::Identifier::new(account.to_bytes()),
364+
local::PriceInfo {
365+
status: Adapter::map_status(&status)?,
366+
price,
367+
conf,
368+
timestamp: Utc::now().naive_utc(),
369+
},
370+
)
371+
.await
372+
.map_err(|_| anyhow!("failed to send update to local store"))
372373
}
373374

374375
// TODO: implement FromStr method on PriceStatus

0 commit comments

Comments
 (0)