Skip to content
Draft
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,6 @@ s3

sequencer_venv/
sequencer_requirements.txt

# Documentations of AI code gen chats
AI_docs
1 change: 1 addition & 0 deletions .markdownlintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
node_modules/**/*.md
**/target/**/*.md
docs/**/*.md
AI_docs/*.md
13 changes: 13 additions & 0 deletions madara/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions madara/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ members = [
"crates/primitives/gateway",
"crates/primitives/rpc",
"crates/primitives/receipt",
"crates/primitives/resilience",
"crates/primitives/state_update",
"crates/primitives/chain_config",
"crates/primitives/utils",
Expand Down Expand Up @@ -94,6 +95,7 @@ mp-state-update = { path = "crates/primitives/state_update", default-features =
mp-utils = { path = "crates/primitives/utils", default-features = false }
mp-chain-config = { path = "crates/primitives/chain_config", default-features = false }
mp-oracle = { path = "crates/primitives/oracle", default-features = false }
mp-resilience = { path = "crates/primitives/resilience", default-features = false }

# Madara client
mc-analytics = { path = "crates/client/analytics" }
Expand Down
2 changes: 2 additions & 0 deletions madara/crates/client/gateway/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mc-submit-tx.workspace = true
mp-block.workspace = true
mp-class.workspace = true
mp-gateway.workspace = true
mp-resilience.workspace = true
mp-rpc.workspace = true
mp-transactions.workspace = true

Expand Down Expand Up @@ -55,3 +56,4 @@ url.workspace = true
rstest.workspace = true
flate2.workspace = true
reqwest = { workspace = true, features = ["json"] }
httpmock.workspace = true
27 changes: 25 additions & 2 deletions madara/crates/client/gateway/client/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,24 @@ type BodyTy = Full<Bytes>;
type HttpsClient = Client<HttpsConnector<HttpConnector>, BodyTy>;
type TimeoutRetryClient = Retry<RetryPolicy, Timeout<HttpsClient>>;
pub type PausedClient = PauseLayerMiddleware<TimeoutRetryClient>;
#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct GatewayProvider {
pub(crate) client: PausedClient,
pub(crate) headers: HeaderMap,
pub(crate) gateway_url: Url,
pub(crate) feeder_gateway_url: Url,
pub(crate) madara_specific_url: Option<Url>,
pub(crate) health: Arc<RwLock<crate::health::GatewayHealth>>,
}

impl std::fmt::Debug for GatewayProvider {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GatewayProvider")
.field("gateway_url", &self.gateway_url)
.field("feeder_gateway_url", &self.feeder_gateway_url)
.field("madara_specific_url", &self.madara_specific_url)
.finish()
}
}

impl GatewayProvider {
Expand Down Expand Up @@ -64,7 +75,19 @@ impl GatewayProvider {
let retry_layer = Retry::new(retry_policy, timeout_layer);
let client = PauseLayerMiddleware::new(retry_layer, Arc::clone(&pause_until));

Self { client, gateway_url, feeder_gateway_url, madara_specific_url: None, headers: HeaderMap::new() }
Self {
client,
gateway_url,
feeder_gateway_url,
madara_specific_url: None,
headers: HeaderMap::new(),
health: Arc::new(RwLock::new(crate::health::GatewayHealth::new("Gateway"))),
}
}

/// Get a reference to the health tracker for this gateway
pub fn health(&self) -> Arc<RwLock<crate::health::GatewayHealth>> {
Arc::clone(&self.health)
}

pub fn with_header(mut self, name: HeaderName, value: HeaderValue) -> Self {
Expand Down
36 changes: 36 additions & 0 deletions madara/crates/client/gateway/client/src/health.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/// Gateway Health Tracking
///
/// This module provides gateway-specific health monitoring by wrapping the generic
/// mp-resilience ConnectionHealth with gateway-specific context.
use mp_resilience::ConnectionHealth;
use std::sync::Arc;
use tokio::sync::RwLock;

/// Gateway health tracker (wraps generic ConnectionHealth)
pub type GatewayHealth = ConnectionHealth;

/// Start the background health monitor task for the gateway
///
/// This spawns a tokio task that periodically logs gateway health status.
/// The task will run until the health Arc is dropped or the program exits.
///
/// # Arguments
/// * `health` - Arc to the GatewayHealth instance to monitor
pub fn start_gateway_health_monitor(health: Arc<RwLock<GatewayHealth>>) {
mp_resilience::start_health_monitor(health);
}

// Re-export HealthState for convenience
pub use mp_resilience::HealthState;

#[cfg(test)]
mod tests {
use super::*;
use mp_resilience::HealthState;

#[test]
fn test_gateway_health_creation() {
let health = GatewayHealth::new("Gateway");
assert!(matches!(health.state(), HealthState::Healthy));
}
}
7 changes: 7 additions & 0 deletions madara/crates/client/gateway/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,17 @@
//! [invoke transactions]: mp_gateway::user_transaction::UserTransaction::InvokeFunction

mod builder;
mod health;
mod methods;
mod request_builder;
mod retry;
mod submit_tx;

#[cfg(test)]
mod tests;

pub use mp_rpc::v0_7_1::{BlockId, BlockTag};

pub use builder::GatewayProvider;
pub use health::{start_gateway_health_monitor, GatewayHealth, HealthState};
pub use retry::{RetryConfig, RetryPhase, RetryState};
Loading