mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-08-25 06:39:53 -04:00
remove full_url, add migration to change scheme of node.monerodevs.org to http
This commit is contained in:
parent
8741ac7619
commit
dc21ab9cee
5 changed files with 62 additions and 24 deletions
|
@ -0,0 +1,33 @@
|
||||||
|
-- Remove full_url column from monero_nodes table as it can be derived from scheme, host, and port
|
||||||
|
|
||||||
|
-- Drop the index first
|
||||||
|
DROP INDEX IF EXISTS idx_nodes_full_url;
|
||||||
|
|
||||||
|
-- Create a new table without the full_url column
|
||||||
|
CREATE TABLE monero_nodes_new (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
scheme TEXT NOT NULL,
|
||||||
|
host TEXT NOT NULL,
|
||||||
|
port INTEGER NOT NULL,
|
||||||
|
network TEXT NOT NULL, -- mainnet/stagenet/testnet - always known at insertion time
|
||||||
|
first_seen_at TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
-- Create a unique constraint on scheme, host, and port instead of full_url
|
||||||
|
UNIQUE(scheme, host, port)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Copy data from old table to new table
|
||||||
|
INSERT INTO monero_nodes_new (id, scheme, host, port, network, first_seen_at, created_at, updated_at)
|
||||||
|
SELECT id, scheme, host, port, network, first_seen_at, created_at, updated_at
|
||||||
|
FROM monero_nodes;
|
||||||
|
|
||||||
|
-- Drop the old table
|
||||||
|
DROP TABLE monero_nodes;
|
||||||
|
|
||||||
|
-- Rename the new table to the original name
|
||||||
|
ALTER TABLE monero_nodes_new RENAME TO monero_nodes;
|
||||||
|
|
||||||
|
-- Recreate the indexes (excluding the full_url index)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_nodes_network ON monero_nodes(network);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_nodes_scheme_host_port ON monero_nodes(scheme, host, port);
|
|
@ -0,0 +1,12 @@
|
||||||
|
-- Fix monerodevs.org nodes: change from https to http
|
||||||
|
UPDATE monero_nodes
|
||||||
|
SET scheme = 'http'
|
||||||
|
WHERE host = 'node.monerodevs.org' AND network = 'stagenet';
|
||||||
|
|
||||||
|
UPDATE monero_nodes
|
||||||
|
SET scheme = 'http'
|
||||||
|
WHERE host = 'node2.monerodevs.org' AND network = 'stagenet';
|
||||||
|
|
||||||
|
UPDATE monero_nodes
|
||||||
|
SET scheme = 'http'
|
||||||
|
WHERE host = 'node3.monerodevs.org' AND network = 'stagenet';
|
|
@ -12,7 +12,6 @@ pub struct MoneroNode {
|
||||||
pub scheme: String, // http or https
|
pub scheme: String, // http or https
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub port: i64,
|
pub port: i64,
|
||||||
pub full_url: String,
|
|
||||||
pub network: String, // mainnet, stagenet, or testnet - always known at insertion time
|
pub network: String, // mainnet, stagenet, or testnet - always known at insertion time
|
||||||
pub first_seen_at: String, // ISO 8601 timestamp when first discovered
|
pub first_seen_at: String, // ISO 8601 timestamp when first discovered
|
||||||
// Computed fields from health_checks (not stored in monero_nodes table)
|
// Computed fields from health_checks (not stored in monero_nodes table)
|
||||||
|
@ -49,14 +48,14 @@ pub struct HealthCheck {
|
||||||
|
|
||||||
impl MoneroNode {
|
impl MoneroNode {
|
||||||
pub fn new(scheme: String, host: String, port: i64, network: String) -> Self {
|
pub fn new(scheme: String, host: String, port: i64, network: String) -> Self {
|
||||||
let full_url = format!("{}://{}:{}", scheme, host, port);
|
// TODO: Do this in the database
|
||||||
let now = chrono::Utc::now().to_rfc3339();
|
let now = chrono::Utc::now().to_rfc3339();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: None,
|
id: None,
|
||||||
scheme,
|
scheme,
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
full_url,
|
|
||||||
network,
|
network,
|
||||||
first_seen_at: now,
|
first_seen_at: now,
|
||||||
// These are computed from health_checks
|
// These are computed from health_checks
|
||||||
|
@ -73,6 +72,10 @@ impl MoneroNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn full_url(&self) -> String {
|
||||||
|
format!("{}://{}:{}", self.scheme, self.host, self.port)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn success_rate(&self) -> f64 {
|
pub fn success_rate(&self) -> f64 {
|
||||||
let total = self.success_count + self.failure_count;
|
let total = self.success_count + self.failure_count;
|
||||||
if total == 0 {
|
if total == 0 {
|
||||||
|
@ -318,7 +321,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
@ -402,7 +404,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
@ -592,7 +593,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
@ -696,7 +696,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
@ -810,7 +809,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
@ -917,7 +915,6 @@ impl Database {
|
||||||
scheme: row.scheme,
|
scheme: row.scheme,
|
||||||
host: row.host,
|
host: row.host,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
full_url: row.full_url,
|
|
||||||
network: row.network,
|
network: row.network,
|
||||||
first_seen_at: row.first_seen_at,
|
first_seen_at: row.first_seen_at,
|
||||||
success_count: row.success_count,
|
success_count: row.success_count,
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl NodePool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidate_nodes.len() == 1 {
|
if candidate_nodes.len() == 1 {
|
||||||
return Ok(Some(candidate_nodes[0].full_url.clone()));
|
return Ok(Some(candidate_nodes[0].full_url()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Power of Two Choices: pick 2 random nodes, select the better one
|
// Power of Two Choices: pick 2 random nodes, select the better one
|
||||||
|
@ -71,9 +71,10 @@ impl NodePool {
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Selected node using P2C for network {}: {}",
|
"Selected node using P2C for network {}: {}",
|
||||||
self.network, selected.full_url
|
self.network, selected.full_url()
|
||||||
);
|
);
|
||||||
Ok(Some(selected.full_url.clone()))
|
|
||||||
|
Ok(Some(selected.full_url()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate goodness score based on usage-based recency
|
/// Calculate goodness score based on usage-based recency
|
||||||
|
@ -127,7 +128,7 @@ impl NodePool {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.take(5)
|
.take(5)
|
||||||
.map(|node| ReliableNodeInfo {
|
.map(|node| ReliableNodeInfo {
|
||||||
url: node.full_url.clone(),
|
url: node.full_url(),
|
||||||
success_rate: node.success_rate(),
|
success_rate: node.success_rate(),
|
||||||
avg_latency_ms: node.avg_latency_ms,
|
avg_latency_ms: node.avg_latency_ms,
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ use axum::{
|
||||||
response::Response,
|
response::Response,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{error::Error, time::Instant};
|
use std::time::Instant;
|
||||||
use tracing::{debug, error, info_span, Instrument};
|
use tracing::{debug, error, info_span, Instrument};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ async fn raw_http_request(
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(30))
|
.timeout(std::time::Duration::from_secs(30))
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| HandlerError::RequestError(e.to_string()))?;
|
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
||||||
|
|
||||||
let url = format!("{}{}", node_url, path);
|
let url = format!("{}{}", node_url, path);
|
||||||
|
|
||||||
|
@ -119,19 +119,14 @@ async fn raw_http_request(
|
||||||
let response = request_builder
|
let response = request_builder
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| HandlerError::RequestError(e.to_string()))?;
|
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
||||||
|
|
||||||
// Convert to axum Response preserving everything
|
// Convert to axum Response preserving everything
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
let response_headers = response.headers().clone();
|
let response_headers = response.headers().clone();
|
||||||
|
|
||||||
let body_bytes = response.bytes().await.map_err(|e| {
|
let body_bytes = response.bytes().await.map_err(|e| {
|
||||||
let mut error_msg = format!("Failed to read response body: {}", e);
|
HandlerError::RequestError(format!("Failed to read response body: {:#?}", e))
|
||||||
if let Some(source) = e.source() {
|
|
||||||
error_msg.push_str(&format!(" (source: {})", source));
|
|
||||||
}
|
|
||||||
|
|
||||||
HandlerError::RequestError(error_msg)
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut axum_response = Response::new(Body::from(body_bytes));
|
let mut axum_response = Response::new(Body::from(body_bytes));
|
||||||
|
@ -189,7 +184,7 @@ async fn single_raw_request(
|
||||||
let (parts, body_stream) = response.into_parts();
|
let (parts, body_stream) = response.into_parts();
|
||||||
let body_bytes = axum::body::to_bytes(body_stream, usize::MAX)
|
let body_bytes = axum::body::to_bytes(body_stream, usize::MAX)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| HandlerError::RequestError(e.to_string()))?;
|
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
||||||
|
|
||||||
if is_jsonrpc_error(&body_bytes) {
|
if is_jsonrpc_error(&body_bytes) {
|
||||||
record_failure(state, &node_url).await;
|
record_failure(state, &node_url).await;
|
||||||
|
@ -253,7 +248,7 @@ async fn race_requests(
|
||||||
|
|
||||||
let pool: Vec<String> = reliable_nodes
|
let pool: Vec<String> = reliable_nodes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|node| node.full_url)
|
.map(|node| node.full_url())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
pool
|
pool
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue