Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add max_queued_txs column + minor client improvement #25

Merged
merged 8 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions db/migrations/003_relayers_tx_limits.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE relayers
ADD COLUMN max_queued_txs BIGINT NOT NULL DEFAULT 20,
ADD CONSTRAINT check_max_queued_txs CHECK (max_queued_txs > max_inflight_txs);

UPDATE relayers
SET max_queued_txs = GREATEST(max_inflight_txs, 20);
68 changes: 54 additions & 14 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use reqwest::Response;
use thiserror::Error;

use crate::api_key::ApiKey;
use crate::server::routes::network::NewNetworkInfo;
Expand All @@ -8,12 +9,29 @@ use crate::server::routes::relayer::{
use crate::server::routes::transaction::{
GetTxResponse, SendTxRequest, SendTxResponse,
};
use crate::server::ApiError;
use crate::types::RelayerUpdate;

pub struct TxSitterClient {
client: reqwest::Client,
url: String,
}

#[derive(Debug, Error)]
pub enum ClientError {
#[error("Reqwest error: {0}")]
Reqwest(#[from] reqwest::Error),

#[error("Serialization error: {0}")]
Serde(#[from] serde_json::Error),

#[error("API error: {0}")]
TxSitter(#[from] ApiError),

#[error("Invalid API key: {0}")]
InvalidApiKey(eyre::Error),
}

impl TxSitterClient {
pub fn new(url: impl ToString) -> Self {
Self {
Expand All @@ -22,7 +40,7 @@ impl TxSitterClient {
}
}

async fn post<R>(&self, url: &str) -> eyre::Result<R>
async fn post<R>(&self, url: &str) -> Result<R, ClientError>
where
R: serde::de::DeserializeOwned,
{
Expand All @@ -33,7 +51,11 @@ impl TxSitterClient {
Ok(response.json().await?)
}

async fn json_post<T, R>(&self, url: &str, body: T) -> eyre::Result<R>
async fn json_post<T, R>(
&self,
url: &str,
body: T,
) -> Result<R, ClientError>
where
T: serde::Serialize,
R: serde::de::DeserializeOwned,
Expand All @@ -45,7 +67,7 @@ impl TxSitterClient {
Ok(response.json().await?)
}

async fn json_get<R>(&self, url: &str) -> eyre::Result<R>
async fn json_get<R>(&self, url: &str) -> Result<R, ClientError>
where
R: serde::de::DeserializeOwned,
{
Expand All @@ -56,38 +78,56 @@ impl TxSitterClient {
Ok(response.json().await?)
}

async fn validate_response(response: Response) -> eyre::Result<Response> {
async fn validate_response(
response: Response,
) -> Result<Response, ClientError> {
if !response.status().is_success() {
let body = response.text().await?;

return Err(eyre::eyre!("{body}"));
let body: ApiError = response.json().await?;
return Err(ClientError::TxSitter(body));
}

Ok(response)
}

pub async fn create_relayer(
&self,
req: &CreateRelayerRequest,
) -> eyre::Result<CreateRelayerResponse> {
) -> Result<CreateRelayerResponse, ClientError> {
self.json_post(&format!("{}/1/admin/relayer", self.url), req)
.await
}

pub async fn create_relayer_api_key(
&self,
relayer_id: &str,
) -> eyre::Result<CreateApiKeyResponse> {
) -> Result<CreateApiKeyResponse, ClientError> {
self.post(&format!("{}/1/admin/relayer/{relayer_id}/key", self.url,))
.await
}

pub async fn update_relayer(
&self,
relayer_id: &str,
relayer_update: RelayerUpdate,
) -> Result<(), ClientError> {
self.json_post(
&format!("{}/1/admin/relayer/{relayer_id}", self.url),
relayer_update,
)
.await
}

pub async fn send_tx(
&self,
api_key: &ApiKey,
req: &SendTxRequest,
) -> eyre::Result<SendTxResponse> {
) -> Result<SendTxResponse, ClientError> {
self.json_post(
&format!("{}/1/api/{}/tx", self.url, api_key.reveal()?),
&format!(
"{}/1/api/{}/tx",
self.url,
api_key.reveal().map_err(ClientError::InvalidApiKey)?
),
req,
)
.await
Expand All @@ -97,11 +137,11 @@ impl TxSitterClient {
&self,
api_key: &ApiKey,
tx_id: &str,
) -> eyre::Result<GetTxResponse> {
) -> Result<GetTxResponse, ClientError> {
self.json_get(&format!(
"{}/1/api/{}/tx/{tx_id}",
self.url,
api_key.reveal()?,
api_key.reveal().map_err(ClientError::InvalidApiKey)?,
tx_id = tx_id
))
.await
Expand All @@ -111,7 +151,7 @@ impl TxSitterClient {
&self,
chain_id: u64,
req: &NewNetworkInfo,
) -> eyre::Result<()> {
) -> Result<(), ClientError> {
let response = self
.client
.post(&format!("{}/1/admin/network/{}", self.url, chain_id))
Expand Down
Loading