Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- GUI: Speedup startup by concurrently bootstrapping Tor and requesting the user to select a wallet
- GUI: Add white background to QR code modal to make it better scannable
- GUI + CLI + ASB: Add `/dns4/rendezvous.observer/tcp/8888/p2p/12D3KooWMjceGXrYuGuDMGrfmJxALnSDbK4km6s1i1sJEgDTgGQa` to the default list of rendezvous points
- GUI + CLI + ASB: Monero RPC pool now prioritizes nodes with pre-established TCP connections

## [3.0.0-beta.6] - 2025-08-07

Expand Down

This file was deleted.

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

2 changes: 1 addition & 1 deletion monero-rpc-pool/src/bin/stress_test_downloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let client = Arc::new(
reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(3 * 60 + 30)) // used in wallet2
.timeout(std::time::Duration::from_secs(10 * 60 + 30)) // used in wallet2
.build()
.expect("Failed to build reqwest client"),
);
Expand Down
14 changes: 14 additions & 0 deletions monero-rpc-pool/src/connection_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,18 @@ impl ConnectionPool {
}
}
}

/// Check if there's an available (unlocked) connection for the given key.
pub async fn has_available_connection(&self, key: &StreamKey) -> bool {
let map = self.inner.read().await;
if let Some(vec_lock) = map.get(key) {
let vec = vec_lock.read().await;
for sender_mutex in vec.iter() {
if sender_mutex.try_lock().is_ok() {
return true;
}
}
}
false
}
}
62 changes: 38 additions & 24 deletions monero-rpc-pool/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,38 +232,52 @@ impl Database {
}

/// Get top nodes based on success rate
/// Adds randomness
pub async fn get_top_nodes_by_recent_success(
&self,
network: &str,
limit: i64,
) -> Result<Vec<NodeAddress>> {
// Randomized ordering: r = max of 3 Uniform(0,1) (biased toward 1).
// Rank by (base_score * r) so top nodes remain preferred but can shuffle.
// r is drawn once per row in the CTE and reused in ORDER BY.
// Increase RANDOM() terms in MAX(...) to strengthen the bias.
let rows = sqlx::query!(
r#"
SELECT
n.scheme,
n.host,
n.port
FROM monero_nodes n
LEFT JOIN (
WITH scored AS (
SELECT
node_id,
SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count
FROM (
SELECT node_id, was_successful
FROM health_checks
ORDER BY timestamp DESC
LIMIT 1000
) recent_checks
GROUP BY node_id
) stats ON n.id = stats.node_id
WHERE n.network = ?
ORDER BY
CASE
WHEN (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0
THEN CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)
ELSE 0.0
END DESC
n.scheme,
n.host,
n.port,
CASE
WHEN (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0
THEN CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)
ELSE 0.0
END as base_score,
MAX(
ABS(RANDOM()) / CAST(0x7fffffffffffffff AS REAL),
ABS(RANDOM()) / CAST(0x7fffffffffffffff AS REAL),
ABS(RANDOM()) / CAST(0x7fffffffffffffff AS REAL)
) as r
FROM monero_nodes n
LEFT JOIN (
SELECT
node_id,
SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count
FROM (
SELECT node_id, was_successful
FROM health_checks
ORDER BY timestamp DESC
LIMIT 1000
) recent_checks
GROUP BY node_id
) stats ON n.id = stats.node_id
WHERE n.network = ?
)
SELECT scheme, host, port
FROM scored
ORDER BY (base_score * r) DESC, r DESC
LIMIT ?
"#,
network,
Expand Down
Loading
Loading