Skip to content

Commit a9a2453

Browse files
authored
perf(server): reuse SuiClient across requests (#764)
reuse sui client across requests
1 parent 885178b commit a9a2453

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

crates/server/src/server.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::{collections::HashMap, net::SocketAddr};
2929
use sui_pg_db::DbArgs;
3030
use tokio::net::TcpListener;
3131
use tokio::sync::oneshot;
32+
use tokio::sync::OnceCell;
3233
use tower_http::cors::{AllowMethods, Any, CorsLayer};
3334
use url::Url;
3435

@@ -107,6 +108,8 @@ pub const DEPOSITED_ASSETS_PATH: &str = "/deposited_assets/:balance_manager_ids"
107108
pub struct AppState {
108109
reader: Reader,
109110
metrics: Arc<RpcMetrics>,
111+
rpc_url: Url,
112+
sui_client: Arc<OnceCell<sui_sdk::SuiClient>>,
110113
deepbook_package_id: String,
111114
deep_token_package_id: String,
112115
deep_treasury_id: String,
@@ -117,6 +120,7 @@ impl AppState {
117120
database_url: Url,
118121
args: DbArgs,
119122
registry: &Registry,
123+
rpc_url: Url,
120124
deepbook_package_id: String,
121125
deep_token_package_id: String,
122126
deep_treasury_id: String,
@@ -126,11 +130,27 @@ impl AppState {
126130
Ok(Self {
127131
reader,
128132
metrics,
133+
rpc_url,
134+
sui_client: Arc::new(OnceCell::new()),
129135
deepbook_package_id,
130136
deep_token_package_id,
131137
deep_treasury_id,
132138
})
133139
}
140+
141+
/// Returns a reference to the shared SuiClient instance.
142+
/// Lazily initializes the client on first access and caches it for subsequent calls
143+
pub async fn sui_client(&self) -> Result<&sui_sdk::SuiClient, DeepBookError> {
144+
self.sui_client
145+
.get_or_try_init(|| async {
146+
SuiClientBuilder::default()
147+
.build(self.rpc_url.as_str())
148+
.await
149+
})
150+
.await
151+
.map_err(DeepBookError::from)
152+
}
153+
134154
pub(crate) fn metrics(&self) -> &RpcMetrics {
135155
&self.metrics
136156
}
@@ -176,6 +196,7 @@ pub async fn run_server(
176196
database_url.clone(),
177197
db_arg.clone(),
178198
metrics.registry(),
199+
rpc_url.clone(),
179200
deepbook_package_id,
180201
deep_token_package_id,
181202
deep_treasury_id,
@@ -221,7 +242,7 @@ pub async fn run_server(
221242
let _ = stx.send(());
222243
})
223244
.spawn(async move {
224-
axum::serve(listener, make_router(Arc::new(state), rpc_url))
245+
axum::serve(listener, make_router(Arc::new(state)))
225246
.with_graceful_shutdown(async move {
226247
let _ = srx.await;
227248
})
@@ -234,7 +255,7 @@ pub async fn run_server(
234255

235256
Ok(())
236257
}
237-
pub(crate) fn make_router(state: Arc<AppState>, rpc_url: Url) -> Router {
258+
pub(crate) fn make_router(state: Arc<AppState>) -> Router {
238259
let cors = CorsLayer::new()
239260
.allow_methods(AllowMethods::list(vec![Method::GET, Method::OPTIONS]))
240261
.allow_headers(Any)
@@ -305,7 +326,7 @@ pub(crate) fn make_router(state: Arc<AppState>, rpc_url: Url) -> Router {
305326
.route(DEEP_SUPPLY_PATH, get(deep_supply))
306327
.route(SUMMARY_PATH, get(summary))
307328
.route(STATUS_PATH, get(status))
308-
.with_state((state.clone(), rpc_url));
329+
.with_state(state.clone());
309330

310331
db_routes
311332
.merge(rpc_routes)
@@ -320,13 +341,13 @@ async fn health_check() -> StatusCode {
320341
/// Get indexer status including checkpoint lag
321342
async fn status(
322343
Query(params): Query<StatusQueryParams>,
323-
State((state, rpc_url)): State<(Arc<AppState>, Url)>,
344+
State(state): State<Arc<AppState>>,
324345
) -> Result<Json<serde_json::Value>, DeepBookError> {
325346
// Get watermarks from the database
326347
let watermarks = state.reader.get_watermarks().await?;
327348

328349
// Get the latest checkpoint from Sui RPC
329-
let sui_client = SuiClientBuilder::default().build(rpc_url.as_str()).await?;
350+
let sui_client = state.sui_client().await?;
330351
let latest_checkpoint = sui_client
331352
.read_api()
332353
.get_latest_checkpoint_sequence_number()
@@ -714,7 +735,7 @@ async fn fetch_historical_volume(
714735

715736
#[allow(clippy::get_first)]
716737
async fn summary(
717-
State((state, rpc_url)): State<(Arc<AppState>, Url)>,
738+
State(state): State<Arc<AppState>>,
718739
) -> Result<Json<Vec<HashMap<String, Value>>>, DeepBookError> {
719740
// Fetch pools metadata first since it's required for other functions
720741
let pools = state.reader.get_pools().await?;
@@ -756,7 +777,7 @@ async fn summary(
756777
orderbook(
757778
Path(pool_name_clone),
758779
Query(HashMap::from([("level".to_string(), "1".to_string())])),
759-
State((state.clone(), rpc_url.clone())),
780+
State(state.clone()),
760781
)
761782
})
762783
.collect();
@@ -1321,7 +1342,7 @@ pub async fn assets(
13211342
async fn orderbook(
13221343
Path(pool_name): Path<String>,
13231344
Query(params): Query<HashMap<String, String>>,
1324-
State((state, rpc_url)): State<(Arc<AppState>, Url)>,
1345+
State(state): State<Arc<AppState>>,
13251346
) -> Result<Json<HashMap<String, Value>>, DeepBookError> {
13261347
let depth = params
13271348
.get("depth")
@@ -1375,7 +1396,7 @@ async fn orderbook(
13751396

13761397
let pool_address = ObjectID::from_hex_literal(&pool_id)?;
13771398

1378-
let sui_client = SuiClientBuilder::default().build(rpc_url.as_str()).await?;
1399+
let sui_client = state.sui_client().await?;
13791400
let mut ptb = ProgrammableTransactionBuilder::new();
13801401

13811402
let pool_object: SuiObjectResponse = sui_client
@@ -1531,10 +1552,8 @@ async fn orderbook(
15311552
}
15321553

15331554
/// DEEP total supply
1534-
async fn deep_supply(
1535-
State((state, rpc_url)): State<(Arc<AppState>, Url)>,
1536-
) -> Result<Json<u64>, DeepBookError> {
1537-
let sui_client = SuiClientBuilder::default().build(rpc_url.as_str()).await?;
1555+
async fn deep_supply(State(state): State<Arc<AppState>>) -> Result<Json<u64>, DeepBookError> {
1556+
let sui_client = state.sui_client().await?;
15381557
let mut ptb = ProgrammableTransactionBuilder::new();
15391558

15401559
let deep_treasury_object_id = ObjectID::from_hex_literal(&state.deep_treasury_id)?;

0 commit comments

Comments
 (0)