fix archive node detection when nodes used to be archive but than changed flags

This commit is contained in:
Bryan Stitt 2022-11-25 00:45:13 +00:00
parent 43d550190b
commit 4dfb7a5451
10 changed files with 292 additions and 89 deletions

175
Cargo.lock generated

@ -272,7 +272,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi",
]
@ -1356,17 +1356,38 @@ dependencies = [
[[package]]
name = "env_logger"
version = "0.9.3"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"atty",
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "error-chain"
version = "0.12.4"
@ -1737,7 +1758,7 @@ dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@ -2170,6 +2191,15 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
@ -2419,6 +2449,16 @@ dependencies = [
"web-sys",
]
[[package]]
name = "io-lifetimes"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87"
dependencies = [
"libc",
"windows-sys 0.42.0",
]
[[package]]
name = "ipnet"
version = "2.5.1"
@ -2435,6 +2475,18 @@ dependencies = [
"serde",
]
[[package]]
name = "is-terminal"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae5bc6e2eb41c9def29a3e0f1306382807764b9b53112030eff57435667352d"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys 0.42.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -2556,9 +2608,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.126"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "libm"
@ -2566,6 +2618,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db"
[[package]]
name = "linux-raw-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
[[package]]
name = "lock_api"
version = "0.4.8"
@ -2698,7 +2756,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@ -2885,7 +2943,7 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
]
@ -3074,7 +3132,7 @@ dependencies = [
"redox_syscall",
"smallvec",
"thread-id",
"windows-sys",
"windows-sys 0.36.1",
]
[[package]]
@ -3770,6 +3828,20 @@ dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.36.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.42.0",
]
[[package]]
name = "rustls"
version = "0.20.6"
@ -3884,9 +3956,9 @@ dependencies = [
[[package]]
name = "sea-orm"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8744afc95ca462de12c2cea5a56d7e406f3be2b2683d3b05066e1afdba898bc5"
checksum = "3120bc435b8640963ffda698f877610e07e077157e216eb99408d819c344034d"
dependencies = [
"async-stream",
"async-trait",
@ -3912,9 +3984,9 @@ dependencies = [
[[package]]
name = "sea-orm-cli"
version = "0.10.3"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "531871fd7d043270d6c26071d48bbdc2e04058e570adf7a8a75d9063c96771e9"
checksum = "d037d297869f0960e56f49b6e8c427660f9cc9c3f867132f4d1014676525dbe7"
dependencies = [
"chrono",
"clap",
@ -3928,9 +4000,9 @@ dependencies = [
[[package]]
name = "sea-orm-macros"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca4d01381fdcabc3818b6d39c5f1f0c885900af90da638e4001406907462784"
checksum = "c54bacfeb842813c16821e21f9456c358861a448294075184ea1d6307e386d08"
dependencies = [
"bae",
"heck 0.3.3",
@ -3941,9 +4013,9 @@ dependencies = [
[[package]]
name = "sea-orm-migration"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e73a6b3823f2d02b09e16060a2d547c781557f756755b80f413679bdb2a149e"
checksum = "8b0c22c789077e49c8ff6b1560e6b7a1e5f2a8f91aeebfb9b9e874fa1bc1aa29"
dependencies = [
"async-trait",
"clap",
@ -5549,43 +5621,100 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "winreg"
version = "0.10.1"

@ -10,6 +10,6 @@ path = "src/mod.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sea-orm = "0.10.3"
sea-orm = "0.10.4"
serde = "1.0.147"
uuid = "1.2.2"

@ -12,7 +12,7 @@ path = "src/lib.rs"
tokio = { version = "1.22.0", features = ["full", "tracing"] }
[dependencies.sea-orm-migration]
version = "0.10.3"
version = "0.10.4"
features = [
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.

@ -31,7 +31,7 @@ counter = "0.5.7"
derive_more = "0.99.17"
dotenv = "0.15.0"
ethers = { version = "1.0.1", default-features = false, features = ["rustls", "ws"] }
env_logger = "0.9.3"
env_logger = "0.10.0"
fdlimit = "0.2.1"
flume = "0.10.14"
futures = { version = "0.3.25", features = ["thread-pool"] }

@ -294,27 +294,29 @@ mod tests {
balanced_rpcs: HashMap::from([
(
"anvil".to_string(),
Web3ConnectionConfig::new(
false,
None,
anvil.endpoint(),
100,
None,
1,
Some(false),
),
Web3ConnectionConfig {
disabled: false,
display_name: None,
url: anvil.endpoint(),
block_data_limit: None,
soft_limit: 100,
hard_limit: None,
weight: 1,
subscribe_txs: Some(false),
},
),
(
"anvil_ws".to_string(),
Web3ConnectionConfig::new(
false,
None,
anvil.ws_endpoint(),
100,
None,
0,
Some(true),
),
Web3ConnectionConfig {
disabled: false,
display_name: None,
url: anvil.ws_endpoint(),
block_data_limit: None,
soft_limit: 100,
hard_limit: None,
weight: 1,
subscribe_txs: Some(false),
},
),
]),
private_rpcs: None,

@ -3,7 +3,6 @@ use crate::rpcs::connection::Web3Connection;
use crate::rpcs::request::OpenRequestHandleMetrics;
use crate::{app::AnyhowJoinHandle, rpcs::blockchain::ArcBlock};
use argh::FromArgs;
use derive_more::Constructor;
use ethers::prelude::TxHash;
use hashbrown::HashMap;
use migration::sea_orm::DatabaseConnection;
@ -176,7 +175,7 @@ fn default_response_cache_max_bytes() -> usize {
}
/// Configuration for a backend web3 RPC server
#[derive(Debug, Deserialize, Constructor)]
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Web3ConnectionConfig {
/// simple way to disable a connection without deleting the row
@ -186,6 +185,8 @@ pub struct Web3ConnectionConfig {
pub display_name: Option<String>,
/// websocket (or http if no websocket)
pub url: String,
/// block data limit. If None, will be queried
pub block_data_limit: Option<u64>,
/// the requests per second at which the server starts slowing down
pub soft_limit: u32,
/// the requests per second at which the server throws errors (rate limit or otherwise)
@ -247,6 +248,7 @@ impl Web3ConnectionConfig {
http_interval_sender,
hard_limit,
self.soft_limit,
self.block_data_limit,
block_map,
block_sender,
tx_id_sender,

@ -45,6 +45,12 @@ pub enum RateLimitResult {
UnknownKey,
}
#[derive(Clone, Debug)]
pub enum AuthorizatioType {
Internal,
Frontend,
}
/// TODO: include the authorization checks in this?
#[derive(Clone, Debug)]
pub struct Authorization {
@ -54,6 +60,7 @@ pub struct Authorization {
pub origin: Option<Origin>,
pub referer: Option<Referer>,
pub user_agent: Option<UserAgent>,
pub authorization_type: AuthorizatioType,
}
#[derive(Debug)]
@ -163,7 +170,7 @@ impl From<RpcSecretKey> for Uuid {
}
impl Authorization {
pub fn local(db_conn: Option<DatabaseConnection>) -> anyhow::Result<Self> {
pub fn internal(db_conn: Option<DatabaseConnection>) -> anyhow::Result<Self> {
let authorization_checks = AuthorizationChecks {
// any error logs on a local (internal) query are likely problems. log them all
log_revert_chance: 1.0,
@ -174,10 +181,18 @@ impl Authorization {
let ip: IpAddr = "127.0.0.1".parse().expect("localhost should always parse");
let user_agent = UserAgent::from_str(APP_USER_AGENT).ok();
Self::try_new(authorization_checks, db_conn, ip, None, None, user_agent)
Self::try_new(
authorization_checks,
db_conn,
ip,
None,
None,
user_agent,
AuthorizatioType::Internal,
)
}
pub fn public(
pub fn external(
allowed_origin_requests_per_period: &HashMap<String, u64>,
db_conn: Option<DatabaseConnection>,
ip: IpAddr,
@ -208,6 +223,7 @@ impl Authorization {
origin,
referer,
user_agent,
AuthorizatioType::Frontend,
)
}
@ -218,6 +234,7 @@ impl Authorization {
origin: Option<Origin>,
referer: Option<Referer>,
user_agent: Option<UserAgent>,
authorization_type: AuthorizatioType,
) -> anyhow::Result<Self> {
// check ip
match &authorization_checks.allowed_ips {
@ -272,6 +289,7 @@ impl Authorization {
origin,
referer,
user_agent,
authorization_type,
})
}
}
@ -444,7 +462,7 @@ impl Web3ProxyApp {
// TODO: dry this up with rate_limit_by_rpc_key?
// we don't care about user agent or origin or referer
let authorization = Authorization::public(
let authorization = Authorization::external(
&self.config.allowed_origin_requests_per_period,
self.db_conn(),
ip,
@ -498,7 +516,7 @@ impl Web3ProxyApp {
) -> anyhow::Result<RateLimitResult> {
// ip rate limits don't check referer or user agent
// the do check
let authorization = Authorization::public(
let authorization = Authorization::external(
allowed_origin_requests_per_period,
self.db_conn.clone(),
ip,
@ -687,6 +705,7 @@ impl Web3ProxyApp {
origin,
referer,
user_agent,
AuthorizatioType::Frontend,
)?;
let user_max_requests_per_period = match authorization.checks.max_requests_per_period {

@ -9,7 +9,7 @@ use anyhow::Context;
use ethers::prelude::{Bytes, Middleware, ProviderError, TxHash, H256, U64};
use futures::future::try_join_all;
use futures::StreamExt;
use log::{debug, error, info, warn, Level};
use log::{debug, error, info, trace, warn, Level};
use migration::sea_orm::DatabaseConnection;
use parking_lot::RwLock;
use redis_rate_limiter::{RedisPool, RedisRateLimitResult, RedisRateLimiter};
@ -37,10 +37,10 @@ pub struct Web3Connection {
pub(super) http_client: Option<reqwest::Client>,
/// keep track of currently open requests. We sort on this
pub(super) active_requests: AtomicU32,
/// keep track of total requests
/// TODO: is this type okay?
/// TODO: replace this with something in metered?
pub(super) total_requests: AtomicU64,
/// keep track of total requests from the frontend
pub(super) frontend_requests: AtomicU64,
/// keep track of total requests from web3-proxy itself
pub(super) internal_requests: AtomicU64,
/// provider is in a RwLock so that we can replace it if re-connecting
/// it is an async lock because we hold it open across awaits
pub(super) provider: AsyncRwLock<Option<Arc<Web3Provider>>>,
@ -75,6 +75,7 @@ impl Web3Connection {
hard_limit: Option<(u64, RedisPool)>,
// TODO: think more about this type
soft_limit: u32,
block_data_limit: Option<u64>,
block_map: BlockHashesCache,
block_sender: Option<flume::Sender<BlockAndRpc>>,
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Self>)>>,
@ -96,17 +97,20 @@ impl Web3Connection {
// turn weight 0 into 100% and weight 100 into 0%
let weight = (100 - weight) as f64 / 100.0;
let block_data_limit = block_data_limit.unwrap_or_default().into();
let new_connection = Self {
name,
display_name,
http_client,
url: url_str,
active_requests: 0.into(),
total_requests: 0.into(),
frontend_requests: 0.into(),
internal_requests: 0.into(),
provider: AsyncRwLock::new(None),
hard_limit,
soft_limit,
block_data_limit: Default::default(),
block_data_limit,
head_block_id: RwLock::new(Default::default()),
weight,
open_request_handle_metrics,
@ -119,7 +123,7 @@ impl Web3Connection {
.retrying_reconnect(block_sender.as_ref(), false)
.await?;
let authorization = Arc::new(Authorization::local(db_conn)?);
let authorization = Arc::new(Authorization::internal(db_conn)?);
// check the server's chain_id here
// TODO: move this outside the `new` function and into a `start` function or something. that way we can do retries from there
@ -153,7 +157,12 @@ impl Web3Connection {
}
}
let will_subscribe_to_blocks = block_sender.is_some();
// TODO: should we do this even if block_sender is None? then we would know limits on private relays
let check_block_limit_needed = (new_connection
.block_data_limit
.load(atomic::Ordering::Acquire)
== 0)
&& block_sender.is_some();
// subscribe to new blocks and new transactions
// TODO: make transaction subscription optional (just pass None for tx_id_sender)
@ -179,7 +188,7 @@ impl Web3Connection {
// TODO: would be great if rpcs exposed this
// TODO: move this to a helper function so we can recheck on errors or as the chain grows
// TODO: move this to a helper function that checks
if will_subscribe_to_blocks {
if check_block_limit_needed {
// TODO: make sure the server isn't still syncing
// TODO: don't sleep. wait for new heads subscription instead
@ -194,32 +203,30 @@ impl Web3Connection {
Ok((new_connection, handle))
}
/// TODO: should check_block_data_limit take authorization?
async fn check_block_data_limit(
self: &Arc<Self>,
authorization: &Arc<Authorization>,
) -> anyhow::Result<Option<u64>> {
let mut limit = None;
for block_data_limit in [u64::MAX, 90_000, 128, 64, 32] {
// TODO: binary search between 90k and max?
// TODO: start at 0 or 1
for block_data_limit in [0, 32, 64, 128, 256, 512, 1024, 90_000, u64::MAX] {
let mut head_block_id = self.head_block_id.read().clone();
// TODO: subscribe to a channel instead of polling. subscribe to http_interval_sender?
while head_block_id.is_none() {
warn!("no head block yet. retrying rpc {}", self);
// TODO: sleep for the block time, or maybe subscribe to a channel instead of this simple pull
sleep(Duration::from_secs(13)).await;
head_block_id = self.head_block_id.read().clone();
}
let head_block_num = head_block_id.expect("is_none was checked above").num;
debug_assert_ne!(head_block_num, U64::zero());
// TODO: subtract 1 from block_data_limit for safety?
let maybe_archive_block = head_block_num
.saturating_sub((block_data_limit).into())
.max(U64::one());
let maybe_archive_block = head_block_num.saturating_sub((block_data_limit).into());
// TODO: wait for the handle BEFORE we check the current block number. it might be delayed too!
// TODO: what should the request be?
@ -233,17 +240,22 @@ impl Web3Connection {
maybe_archive_block,
)),
// error here are expected, so keep the level low
Level::Debug.into(),
Level::Trace.into(),
)
.await;
// // trace!(?archive_result, rpc=%self);
if archive_result.is_ok() {
limit = Some(block_data_limit);
trace!(
"archive_result on {} for {}: {:?}",
block_data_limit,
self.name,
archive_result
);
if archive_result.is_err() {
break;
}
limit = Some(block_data_limit);
}
if let Some(limit) = limit {
@ -251,6 +263,8 @@ impl Web3Connection {
.store(limit, atomic::Ordering::Release);
}
debug!("block data limit on {}: {:?}", self.name, limit);
Ok(limit)
}
@ -946,7 +960,7 @@ impl Serialize for Web3Connection {
state.serialize_field(
"total_requests",
&self.total_requests.load(atomic::Ordering::Relaxed),
&self.frontend_requests.load(atomic::Ordering::Relaxed),
)?;
let head_block_id = &*self.head_block_id.read();
@ -999,7 +1013,8 @@ mod tests {
url: "ws://example.com".to_string(),
http_client: None,
active_requests: 0.into(),
total_requests: 0.into(),
frontend_requests: 0.into(),
internal_requests: 0.into(),
provider: AsyncRwLock::new(None),
hard_limit: None,
soft_limit: 1_000,
@ -1027,13 +1042,15 @@ mod tests {
let metrics = OpenRequestHandleMetrics::default();
// TODO: this is getting long. have a `impl Default`
let x = Web3Connection {
name: "name".to_string(),
display_name: None,
url: "ws://example.com".to_string(),
http_client: None,
active_requests: 0.into(),
total_requests: 0.into(),
frontend_requests: 0.into(),
internal_requests: 0.into(),
provider: AsyncRwLock::new(None),
hard_limit: None,
soft_limit: 1_000,

@ -215,7 +215,7 @@ impl Web3Connections {
min_head_rpcs,
});
let authorization = Arc::new(Authorization::local(db_conn.clone())?);
let authorization = Arc::new(Authorization::internal(db_conn.clone())?);
let handle = {
let connections = connections.clone();
@ -857,7 +857,8 @@ mod tests {
url: "ws://example.com/synced".to_string(),
http_client: None,
active_requests: 0.into(),
total_requests: 0.into(),
frontend_requests: 0.into(),
internal_requests: 0.into(),
provider: AsyncRwLock::new(Some(Arc::new(Web3Provider::Mock))),
hard_limit: None,
soft_limit: 1_000,
@ -873,7 +874,8 @@ mod tests {
url: "ws://example.com/lagged".to_string(),
http_client: None,
active_requests: 0.into(),
total_requests: 0.into(),
frontend_requests: 0.into(),
internal_requests: 0.into(),
provider: AsyncRwLock::new(Some(Arc::new(Web3Provider::Mock))),
hard_limit: None,
soft_limit: 1_000,
@ -914,7 +916,7 @@ mod tests {
min_sum_soft_limit: 1,
};
let authorization = Arc::new(Authorization::local(None).unwrap());
let authorization = Arc::new(Authorization::internal(None).unwrap());
let (head_block_sender, _head_block_receiver) =
watch::channel::<ArcBlock>(Default::default());

@ -1,6 +1,6 @@
use super::connection::Web3Connection;
use super::provider::Web3Provider;
use crate::frontend::authorization::Authorization;
use crate::frontend::authorization::{AuthorizatioType, Authorization};
use crate::metered::{JsonRpcErrorCount, ProviderErrorCount};
use anyhow::Context;
use chrono::Utc;
@ -42,14 +42,16 @@ pub struct OpenRequestHandle {
/// Depending on the context, RPC errors can require different handling.
pub enum RequestErrorHandler {
/// Potentially save the revert. Users can tune how often this happens
SaveReverts,
/// Log at the trace level. Use when errors are expected.
TraceLevel,
/// Log at the debug level. Use when errors are expected.
DebugLevel,
/// Log at the error level. Use when errors are bad.
ErrorLevel,
/// Log at the warn level. Use when errors do not cause problems.
WarnLevel,
/// Potentially save the revert. Users can tune how often this happens
SaveReverts,
}
// TODO: second param could be skipped since we don't need it here
@ -65,6 +67,7 @@ struct EthCallFirstParams {
impl From<Level> for RequestErrorHandler {
fn from(level: Level) -> Self {
match level {
Level::Trace => RequestErrorHandler::TraceLevel,
Level::Debug => RequestErrorHandler::DebugLevel,
Level::Error => RequestErrorHandler::ErrorLevel,
Level::Warn => RequestErrorHandler::WarnLevel,
@ -136,7 +139,16 @@ impl OpenRequestHandle {
// TODO: handle overflows?
// TODO: what ordering?
conn.total_requests.fetch_add(1, atomic::Ordering::Relaxed);
match authorization.as_ref().authorization_type {
AuthorizatioType::Frontend => {
conn.frontend_requests
.fetch_add(1, atomic::Ordering::Relaxed);
}
AuthorizatioType::Internal => {
conn.internal_requests
.fetch_add(1, atomic::Ordering::Relaxed);
}
}
let metrics = conn.open_request_handle_metrics.clone();
let used = false.into();
@ -273,6 +285,7 @@ impl OpenRequestHandle {
false
};
// TODO: think more about the method and param logs. those can be sensitive information
match error_handler {
RequestErrorHandler::DebugLevel => {
// TODO: think about this revert check more. sometimes we might want reverts logged so this needs a flag
@ -283,19 +296,38 @@ impl OpenRequestHandle {
);
}
}
RequestErrorHandler::ErrorLevel => {
error!(
RequestErrorHandler::TraceLevel => {
trace!(
"bad response from {}! method={} params={:?} err={:?}",
self.conn, method, params, err
self.conn,
method,
params,
err
);
}
RequestErrorHandler::ErrorLevel => {
// TODO: include params if not running in release mode
error!(
"bad response from {}! method={} err={:?}",
self.conn, method, err
);
}
RequestErrorHandler::WarnLevel => {
// TODO: include params if not running in release mode
warn!(
"bad response from {}! method={} params={:?} err={:?}",
self.conn, method, params, err
"bad response from {}! method={} err={:?}",
self.conn, method, err
);
}
RequestErrorHandler::SaveReverts => {
trace!(
"bad response from {}! method={} params={:?} err={:?}",
self.conn,
method,
params,
err
);
// TODO: do not unwrap! (doesn't matter much since we check method as a string above)
let method: Method = Method::try_from_value(&method.to_string()).unwrap();