mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-08-24 14:15:55 -04:00
refactor(monero-rpc-pool): Pass around tuple of (scheme, host, port) as nodes
This commit is contained in:
parent
dc21ab9cee
commit
1c5acdc1c7
25 changed files with 792 additions and 810 deletions
20
monero-rpc-pool/.sqlx/query-03e5b2bccf8bffb962a56443448311800bb832efe37fe6c52181bd7bf631740c.json
generated
Normal file
20
monero-rpc-pool/.sqlx/query-03e5b2bccf8bffb962a56443448311800bb832efe37fe6c52181bd7bf631740c.json
generated
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT id FROM monero_nodes WHERE scheme = ? AND host = ? AND port = ?",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "03e5b2bccf8bffb962a56443448311800bb832efe37fe6c52181bd7bf631740c"
|
||||||
|
}
|
110
monero-rpc-pool/.sqlx/query-08d143b977a7fa23b289c22dee3cab4d64debeea9932c58047cc6244d136f80d.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-08d143b977a7fa23b289c22dee3cab4d64debeea9932c58047cc6244d136f80d.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ? AND (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0\n ORDER BY \n (CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)) DESC,\n stats.avg_latency_ms ASC\n LIMIT ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "08d143b977a7fa23b289c22dee3cab4d64debeea9932c58047cc6244d136f80d"
|
||||||
|
}
|
110
monero-rpc-pool/.sqlx/query-0aa34e769813a40e0518f5311ff95685fd5278103d13f56795ff5a51b0ef8036.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-0aa34e769813a40e0518f5311ff95685fd5278103d13f56795ff5a51b0ef8036.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY stats.avg_latency_ms ASC, stats.success_count DESC\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "0aa34e769813a40e0518f5311ff95685fd5278103d13f56795ff5a51b0ef8036"
|
||||||
|
}
|
110
monero-rpc-pool/.sqlx/query-2a378cb109fe284ba3a939aed1bcb50dc694c89ef1eb08bf3d62e7d9e0902a4e.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-2a378cb109fe284ba3a939aed1bcb50dc694c89ef1eb08bf3d62e7d9e0902a4e.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY RANDOM()\n LIMIT ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "2a378cb109fe284ba3a939aed1bcb50dc694c89ef1eb08bf3d62e7d9e0902a4e"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "\n SELECT \n id as \"id!: i64\",\n scheme,\n host,\n port,\n full_url,\n network as \"network!: String\",\n first_seen_at\n FROM monero_nodes \n ORDER BY id\n ",
|
"query": "\n SELECT \n id as \"id!: i64\",\n scheme,\n host,\n port,\n network as \"network!: String\",\n first_seen_at\n FROM monero_nodes \n ORDER BY id\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -24,25 +24,27 @@
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "full_url",
|
"name": "network!: String",
|
||||||
"ordinal": 4,
|
"ordinal": 4,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "network!: String",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "first_seen_at",
|
"name": "first_seen_at",
|
||||||
"ordinal": 6,
|
"ordinal": 5,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 0
|
"Right": 0
|
||||||
},
|
},
|
||||||
"nullable": [false, false, false, false, false, false, false]
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"hash": "3e8f39a6ec4443cec6497672891d12bbf7c1d0aca061827740af88ced863ae23"
|
"hash": "37157927724c8bc647bf4f76f5698631cbd40637778dfa83e8f644ae6a7cf75b"
|
||||||
}
|
}
|
20
monero-rpc-pool/.sqlx/query-3870c77c7c5fbb9bdd57c365765178a08de20e442a07f3e734e61c410e4f338e.json
generated
Normal file
20
monero-rpc-pool/.sqlx/query-3870c77c7c5fbb9bdd57c365765178a08de20e442a07f3e734e61c410e4f338e.json
generated
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n INSERT INTO monero_nodes (scheme, host, port, network, first_seen_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(scheme, host, port) DO UPDATE SET\n network = excluded.network,\n updated_at = excluded.updated_at\n RETURNING id\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 6
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "3870c77c7c5fbb9bdd57c365765178a08de20e442a07f3e734e61c410e4f338e"
|
||||||
|
}
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ? AND (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0\n ORDER BY \n (CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)) DESC,\n stats.avg_latency_ms ASC\n LIMIT ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "549f5ef13ec7bf5d987dcb893753a9c903edcafa3a66bd82965b40a9e7f238b6"
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n UPDATE monero_nodes \n SET network = ?, updated_at = ?\n WHERE full_url = ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "5736de2aac47eb69d7f6835d266aa28732b02a5e8e055ffaebcb452ed1b5044c"
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n INSERT INTO monero_nodes (scheme, host, port, full_url, network, first_seen_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(full_url) DO UPDATE SET\n network = excluded.network,\n updated_at = excluded.updated_at\n RETURNING id\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 7
|
|
||||||
},
|
|
||||||
"nullable": [false]
|
|
||||||
},
|
|
||||||
"hash": "5798d9589772742f074e0ecc2551a40d943bfb7ed2e295f09f12d77cb65ce821"
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY RANDOM()\n LIMIT ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "5a25c95c04b11a60a04ad97b5fb684e9a0cc2eb5daf64f33e924f0c38a2edfec"
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY stats.avg_latency_ms ASC, stats.success_count DESC\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "5ff27bdd9b6e7aadc8dd4936e0ee7e6a611aaef28697a0e9535dfb30d1c4861d"
|
|
||||||
}
|
|
110
monero-rpc-pool/.sqlx/query-75ad770e6f70443871f919c26c189aaefc306e2a72b456fc2d03d4aa870e150b.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-75ad770e6f70443871f919c26c189aaefc306e2a72b456fc2d03d4aa870e150b.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ? AND stats.success_count > 0\n ORDER BY stats.avg_latency_ms ASC, stats.success_count DESC\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "75ad770e6f70443871f919c26c189aaefc306e2a72b456fc2d03d4aa870e150b"
|
||||||
|
}
|
110
monero-rpc-pool/.sqlx/query-9f6d042ab61e1d3d652d85c7d77d86a847c4a25d4ee0eab57380d10b94d2686d.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-9f6d042ab61e1d3d652d85c7d77d86a847c4a25d4ee0eab57380d10b94d2686d.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY RANDOM()\n LIMIT ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 3
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "9f6d042ab61e1d3d652d85c7d77d86a847c4a25d4ee0eab57380d10b94d2686d"
|
||||||
|
}
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(1 AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n WHERE n.network = ? AND (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0\n ORDER BY \n (CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN stats.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(stats.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END DESC\n LIMIT 4\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "a032eb9773d4553aeaff4fb15ed99dbaef7d16d48750ee7bd4ab83233a9a732b"
|
|
||||||
}
|
|
12
monero-rpc-pool/.sqlx/query-b6d85d42bf72888afa22e27710e8cfe3885ed226ae6ae02d6585c1f2f4140d68.json
generated
Normal file
12
monero-rpc-pool/.sqlx/query-b6d85d42bf72888afa22e27710e8cfe3885ed226ae6ae02d6585c1f2f4140d68.json
generated
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE monero_nodes \n SET network = ?, updated_at = ?\n WHERE scheme = ? AND host = ? AND port = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 5
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "b6d85d42bf72888afa22e27710e8cfe3885ed226ae6ae02d6585c1f2f4140d68"
|
||||||
|
}
|
110
monero-rpc-pool/.sqlx/query-b96b866cfc801e275e39e788993d26f6dba1a17a0dee265333c4ae5817ff1e55.json
generated
Normal file
110
monero-rpc-pool/.sqlx/query-b96b866cfc801e275e39e788993d26f6dba1a17a0dee265333c4ae5817ff1e55.json
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(1 AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n WHERE n.network = ? AND (COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0)) > 0\n ORDER BY \n (CAST(COALESCE(stats.success_count, 0) AS REAL) / CAST(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(stats.success_count, 0) + COALESCE(stats.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN stats.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(stats.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END DESC\n LIMIT 4\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id!: i64",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scheme",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "network",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "first_seen_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "success_count!: i64",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "failure_count!: i64",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_success?: String",
|
||||||
|
"ordinal": 8,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_failure?: String",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_checked?: String",
|
||||||
|
"ordinal": 10,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_reliable!: i64",
|
||||||
|
"ordinal": 11,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avg_latency_ms?: f64",
|
||||||
|
"ordinal": 12,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_latency_ms?: f64",
|
||||||
|
"ordinal": 13,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_latency_ms?: f64",
|
||||||
|
"ordinal": 14,
|
||||||
|
"type_info": "Null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "last_latency_ms?: f64",
|
||||||
|
"ordinal": 15,
|
||||||
|
"type_info": "Float"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "b96b866cfc801e275e39e788993d26f6dba1a17a0dee265333c4ae5817ff1e55"
|
||||||
|
}
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ?\n ORDER BY RANDOM()\n LIMIT ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 3
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "ba231efaf208a42fa857f716ef296b428c937f2eb7c8ce9c631f7f721e914c14"
|
|
||||||
}
|
|
|
@ -17,7 +17,10 @@
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
},
|
||||||
"nullable": [true, true]
|
"nullable": [
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"hash": "d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9"
|
"hash": "d32d91ca2debc4212841282533482b2ff081234c7f9f848a7223ae04234995d9"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "SELECT id FROM monero_nodes WHERE full_url = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [true]
|
|
||||||
},
|
|
||||||
"hash": "e0865335c2dcb040a34e3f1305fe1a823d6fcde4a061def602cba30971817781"
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n SELECT \n n.id as \"id!: i64\",\n n.scheme,\n n.host,\n n.port,\n n.full_url,\n n.network,\n n.first_seen_at,\n CAST(COALESCE(stats.success_count, 0) AS INTEGER) as \"success_count!: i64\",\n CAST(COALESCE(stats.failure_count, 0) AS INTEGER) as \"failure_count!: i64\",\n stats.last_success as \"last_success?: String\",\n stats.last_failure as \"last_failure?: String\",\n stats.last_checked as \"last_checked?: String\",\n CAST(CASE WHEN reliable_nodes.node_id IS NOT NULL THEN 1 ELSE 0 END AS INTEGER) as \"is_reliable!: i64\",\n stats.avg_latency_ms as \"avg_latency_ms?: f64\",\n stats.min_latency_ms as \"min_latency_ms?: f64\",\n stats.max_latency_ms as \"max_latency_ms?: f64\",\n stats.last_latency_ms as \"last_latency_ms?: f64\"\n FROM monero_nodes n\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n MAX(CASE WHEN was_successful THEN timestamp END) as last_success,\n MAX(CASE WHEN NOT was_successful THEN timestamp END) as last_failure,\n MAX(timestamp) as last_checked,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,\n MIN(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as min_latency_ms,\n MAX(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as max_latency_ms,\n (SELECT latency_ms FROM health_checks hc2 WHERE hc2.node_id = health_checks.node_id ORDER BY timestamp DESC LIMIT 1) as last_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) stats ON n.id = stats.node_id\n LEFT JOIN (\n SELECT DISTINCT node_id FROM (\n SELECT \n n2.id as node_id,\n COALESCE(s2.success_count, 0) as success_count,\n COALESCE(s2.failure_count, 0) as failure_count,\n s2.avg_latency_ms,\n (CAST(COALESCE(s2.success_count, 0) AS REAL) / CAST(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0) AS REAL)) * \n (MIN(COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0), 200) / 200.0) * 0.8 +\n CASE \n WHEN s2.avg_latency_ms IS NOT NULL THEN (1.0 - (MIN(s2.avg_latency_ms, 2000) / 2000.0)) * 0.2\n ELSE 0.0 \n END as reliability_score\n FROM monero_nodes n2\n LEFT JOIN (\n SELECT \n node_id,\n SUM(CASE WHEN was_successful THEN 1 ELSE 0 END) as success_count,\n SUM(CASE WHEN NOT was_successful THEN 1 ELSE 0 END) as failure_count,\n AVG(CASE WHEN was_successful AND latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms\n FROM health_checks \n GROUP BY node_id\n ) s2 ON n2.id = s2.node_id\n WHERE n2.network = ? AND (COALESCE(s2.success_count, 0) + COALESCE(s2.failure_count, 0)) > 0\n ORDER BY reliability_score DESC\n LIMIT 4\n )\n ) reliable_nodes ON n.id = reliable_nodes.node_id\n WHERE n.network = ? AND stats.success_count > 0\n ORDER BY stats.avg_latency_ms ASC, stats.success_count DESC\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id!: i64",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "scheme",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Integer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "full_url",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "network",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "first_seen_at",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "success_count!: i64",
|
|
||||||
"ordinal": 7,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failure_count!: i64",
|
|
||||||
"ordinal": 8,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_success?: String",
|
|
||||||
"ordinal": 9,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_failure?: String",
|
|
||||||
"ordinal": 10,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_checked?: String",
|
|
||||||
"ordinal": 11,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "is_reliable!: i64",
|
|
||||||
"ordinal": 12,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "avg_latency_ms?: f64",
|
|
||||||
"ordinal": 13,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "min_latency_ms?: f64",
|
|
||||||
"ordinal": 14,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "max_latency_ms?: f64",
|
|
||||||
"ordinal": 15,
|
|
||||||
"type_info": "Null"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "last_latency_ms?: f64",
|
|
||||||
"ordinal": 16,
|
|
||||||
"type_info": "Float"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "fac12e3ca6ac1db1a4812a5390a333ec95a2e5e2cd554c169ceecc61b7ff2864"
|
|
||||||
}
|
|
|
@ -22,7 +22,11 @@
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 2
|
"Right": 2
|
||||||
},
|
},
|
||||||
"nullable": [false, true, false]
|
"nullable": [
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"hash": "ffa1b76d20c86d6bea02bd03e5e7de159adbb7c7c0ef585ce4df9ec648bea7f8"
|
"hash": "ffa1b76d20c86d6bea02bd03e5e7de159adbb7c7c0ef585ce4df9ec648bea7f8"
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,14 +149,13 @@ impl Database {
|
||||||
port: i64,
|
port: i64,
|
||||||
network: &str,
|
network: &str,
|
||||||
) -> Result<i64> {
|
) -> Result<i64> {
|
||||||
let full_url = format!("{}://{}:{}", scheme, host, port);
|
|
||||||
let now = chrono::Utc::now().to_rfc3339();
|
let now = chrono::Utc::now().to_rfc3339();
|
||||||
|
|
||||||
let result = sqlx::query!(
|
let result = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO monero_nodes (scheme, host, port, full_url, network, first_seen_at, updated_at)
|
INSERT INTO monero_nodes (scheme, host, port, network, first_seen_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT(full_url) DO UPDATE SET
|
ON CONFLICT(scheme, host, port) DO UPDATE SET
|
||||||
network = excluded.network,
|
network = excluded.network,
|
||||||
updated_at = excluded.updated_at
|
updated_at = excluded.updated_at
|
||||||
RETURNING id
|
RETURNING id
|
||||||
|
@ -164,7 +163,6 @@ impl Database {
|
||||||
scheme,
|
scheme,
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
full_url,
|
|
||||||
network,
|
network,
|
||||||
now,
|
now,
|
||||||
now
|
now
|
||||||
|
@ -176,26 +174,28 @@ impl Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update a node's network after it has been identified
|
/// Update a node's network after it has been identified
|
||||||
pub async fn update_node_network(&self, url: &str, network: &str) -> Result<()> {
|
pub async fn update_node_network(&self, scheme: &str, host: &str, port: i64, network: &str) -> Result<()> {
|
||||||
let now = chrono::Utc::now().to_rfc3339();
|
let now = chrono::Utc::now().to_rfc3339();
|
||||||
|
|
||||||
let result = sqlx::query!(
|
let result = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
UPDATE monero_nodes
|
UPDATE monero_nodes
|
||||||
SET network = ?, updated_at = ?
|
SET network = ?, updated_at = ?
|
||||||
WHERE full_url = ?
|
WHERE scheme = ? AND host = ? AND port = ?
|
||||||
"#,
|
"#,
|
||||||
network,
|
network,
|
||||||
now,
|
now,
|
||||||
url
|
scheme,
|
||||||
|
host,
|
||||||
|
port
|
||||||
)
|
)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if result.rows_affected() > 0 {
|
if result.rows_affected() > 0 {
|
||||||
debug!("Updated network for node {} to {}", url, network);
|
debug!("Updated network for node {}://{}:{} to {}", scheme, host, port, network);
|
||||||
} else {
|
} else {
|
||||||
warn!("Failed to update network for node {}: not found", url);
|
warn!("Failed to update network for node {}://{}:{}: not found", scheme, host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -204,21 +204,23 @@ impl Database {
|
||||||
/// Record a health check event
|
/// Record a health check event
|
||||||
pub async fn record_health_check(
|
pub async fn record_health_check(
|
||||||
&self,
|
&self,
|
||||||
url: &str,
|
scheme: &str,
|
||||||
|
host: &str,
|
||||||
|
port: i64,
|
||||||
was_successful: bool,
|
was_successful: bool,
|
||||||
latency_ms: Option<f64>,
|
latency_ms: Option<f64>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let now = chrono::Utc::now().to_rfc3339();
|
let now = chrono::Utc::now().to_rfc3339();
|
||||||
|
|
||||||
// First get the node_id
|
// First get the node_id
|
||||||
let node_row = sqlx::query!("SELECT id FROM monero_nodes WHERE full_url = ?", url)
|
let node_row = sqlx::query!("SELECT id FROM monero_nodes WHERE scheme = ? AND host = ? AND port = ?", scheme, host, port)
|
||||||
.fetch_optional(&self.pool)
|
.fetch_optional(&self.pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let node_id = match node_row {
|
let node_id = match node_row {
|
||||||
Some(row) => row.id,
|
Some(row) => row.id,
|
||||||
None => {
|
None => {
|
||||||
warn!("Cannot record health check for unknown node: {}", url);
|
warn!("Cannot record health check for unknown node: {}://{}:{}", scheme, host, port);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -248,7 +250,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
@ -353,7 +354,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
@ -516,7 +516,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
@ -623,7 +622,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
@ -734,7 +732,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
@ -835,7 +832,6 @@ impl Database {
|
||||||
n.scheme,
|
n.scheme,
|
||||||
n.host,
|
n.host,
|
||||||
n.port,
|
n.port,
|
||||||
n.full_url,
|
|
||||||
n.network,
|
n.network,
|
||||||
n.first_seen_at,
|
n.first_seen_at,
|
||||||
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
CAST(COALESCE(stats.success_count, 0) AS INTEGER) as "success_count!: i64",
|
||||||
|
|
|
@ -116,7 +116,7 @@ impl NodeDiscovery {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enhanced health check that detects network and validates node identity
|
/// Enhanced health check that detects network and validates node identity
|
||||||
pub async fn check_node_health(&self, url: &str) -> Result<HealthCheckOutcome> {
|
pub async fn check_node_health(&self, scheme: &str, host: &str, port: i64) -> Result<HealthCheckOutcome> {
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let rpc_request = serde_json::json!({
|
let rpc_request = serde_json::json!({
|
||||||
|
@ -125,8 +125,8 @@ impl NodeDiscovery {
|
||||||
"method": "get_info"
|
"method": "get_info"
|
||||||
});
|
});
|
||||||
|
|
||||||
let full_url = format!("{}/json_rpc", url);
|
let node_url = format!("{}://{}:{}/json_rpc", scheme, host, port);
|
||||||
let response = self.client.post(&full_url).json(&rpc_request).send().await;
|
let response = self.client.post(&node_url).json(&rpc_request).send().await;
|
||||||
|
|
||||||
let latency = start_time.elapsed();
|
let latency = start_time.elapsed();
|
||||||
|
|
||||||
|
@ -214,7 +214,6 @@ impl NodeDiscovery {
|
||||||
scheme,
|
scheme,
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
full_url,
|
|
||||||
network as "network!: String",
|
network as "network!: String",
|
||||||
first_seen_at
|
first_seen_at
|
||||||
FROM monero_nodes
|
FROM monero_nodes
|
||||||
|
@ -229,12 +228,14 @@ impl NodeDiscovery {
|
||||||
let mut corrected_count = 0;
|
let mut corrected_count = 0;
|
||||||
|
|
||||||
for node in all_nodes {
|
for node in all_nodes {
|
||||||
match self.check_node_health(&node.full_url).await {
|
match self.check_node_health(&node.scheme, &node.host, node.port).await {
|
||||||
Ok(outcome) => {
|
Ok(outcome) => {
|
||||||
// Always record the health check
|
// Always record the health check
|
||||||
self.db
|
self.db
|
||||||
.record_health_check(
|
.record_health_check(
|
||||||
&node.full_url,
|
&node.scheme,
|
||||||
|
&node.host,
|
||||||
|
node.port,
|
||||||
outcome.was_successful,
|
outcome.was_successful,
|
||||||
if outcome.was_successful {
|
if outcome.was_successful {
|
||||||
Some(outcome.latency.as_millis() as f64)
|
Some(outcome.latency.as_millis() as f64)
|
||||||
|
@ -251,10 +252,11 @@ impl NodeDiscovery {
|
||||||
if let Some(discovered_network) = outcome.discovered_network {
|
if let Some(discovered_network) = outcome.discovered_network {
|
||||||
let discovered_network_str = network_to_string(&discovered_network);
|
let discovered_network_str = network_to_string(&discovered_network);
|
||||||
if node.network != discovered_network_str {
|
if node.network != discovered_network_str {
|
||||||
|
let node_url = format!("{}://{}:{}", node.scheme, node.host, node.port);
|
||||||
warn!("Network mismatch detected for node {}: stored={}, discovered={}. Correcting...",
|
warn!("Network mismatch detected for node {}: stored={}, discovered={}. Correcting...",
|
||||||
node.full_url, node.network, discovered_network_str);
|
node_url, node.network, discovered_network_str);
|
||||||
self.db
|
self.db
|
||||||
.update_node_network(&node.full_url, &discovered_network_str)
|
.update_node_network(&node.scheme, &node.host, node.port, &discovered_network_str)
|
||||||
.await?;
|
.await?;
|
||||||
corrected_count += 1;
|
corrected_count += 1;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +266,7 @@ impl NodeDiscovery {
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
self.db
|
self.db
|
||||||
.record_health_check(&node.full_url, false, None)
|
.record_health_check(&node.scheme, &node.host, node.port, false, None)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,15 +100,15 @@ impl NodePool {
|
||||||
score
|
score
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn record_success(&self, url: &str, latency_ms: f64) -> Result<()> {
|
pub async fn record_success(&self, scheme: &str, host: &str, port: i64, latency_ms: f64) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
.record_health_check(url, true, Some(latency_ms))
|
.record_health_check(scheme, host, port, true, Some(latency_ms))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn record_failure(&self, url: &str) -> Result<()> {
|
pub async fn record_failure(&self, scheme: &str, host: &str, port: i64) -> Result<()> {
|
||||||
self.db.record_health_check(url, false, None).await?;
|
self.db.record_health_check(scheme, host, port, false, None).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn extract_jsonrpc_method(body: &[u8]) -> Option<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn raw_http_request(
|
async fn raw_http_request(
|
||||||
node_url: &str,
|
node_url: (String, String, i64),
|
||||||
path: &str,
|
path: &str,
|
||||||
method: &str,
|
method: &str,
|
||||||
headers: &HeaderMap,
|
headers: &HeaderMap,
|
||||||
|
@ -71,7 +71,8 @@ async fn raw_http_request(
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
||||||
|
|
||||||
let url = format!("{}{}", node_url, path);
|
let (scheme, host, port) = &node_url;
|
||||||
|
let url = format!("{}://{}:{}{}", scheme, host, port, path);
|
||||||
|
|
||||||
// Use generic request method to support any HTTP verb
|
// Use generic request method to support any HTTP verb
|
||||||
let http_method = method
|
let http_method = method
|
||||||
|
@ -148,31 +149,33 @@ async fn raw_http_request(
|
||||||
Ok(axum_response)
|
Ok(axum_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn record_success(state: &AppState, node_url: &str, latency_ms: f64) {
|
async fn record_success(state: &AppState, scheme: &str, host: &str, port: i64, latency_ms: f64) {
|
||||||
let node_pool_guard = state.node_pool.read().await;
|
let node_pool_guard = state.node_pool.read().await;
|
||||||
if let Err(e) = node_pool_guard.record_success(node_url, latency_ms).await {
|
if let Err(e) = node_pool_guard.record_success(scheme, host, port, latency_ms).await {
|
||||||
error!("Failed to record success for {}: {}", node_url, e);
|
error!("Failed to record success for {}://{}:{}: {}", scheme, host, port, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn record_failure(state: &AppState, node_url: &str) {
|
async fn record_failure(state: &AppState, scheme: &str, host: &str, port: i64) {
|
||||||
let node_pool_guard = state.node_pool.read().await;
|
let node_pool_guard = state.node_pool.read().await;
|
||||||
if let Err(e) = node_pool_guard.record_failure(node_url).await {
|
if let Err(e) = node_pool_guard.record_failure(scheme, host, port).await {
|
||||||
error!("Failed to record failure for {}: {}", node_url, e);
|
error!("Failed to record failure for {}://{}:{}: {}", scheme, host, port, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn single_raw_request(
|
async fn single_raw_request(
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
node_url: String,
|
node_url: (String, String, i64),
|
||||||
path: &str,
|
path: &str,
|
||||||
method: &str,
|
method: &str,
|
||||||
headers: &HeaderMap,
|
headers: &HeaderMap,
|
||||||
body: Option<&[u8]>,
|
body: Option<&[u8]>,
|
||||||
) -> Result<(Response, String, f64), HandlerError> {
|
) -> Result<(Response, (String, String, i64), f64), HandlerError> {
|
||||||
|
let (scheme, host, port) = &node_url;
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
match raw_http_request(&node_url, path, method, headers, body).await {
|
match raw_http_request(node_url.clone(), path, method, headers, body).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let elapsed = start_time.elapsed();
|
let elapsed = start_time.elapsed();
|
||||||
let latency_ms = elapsed.as_millis() as f64;
|
let latency_ms = elapsed.as_millis() as f64;
|
||||||
|
@ -187,22 +190,22 @@ async fn single_raw_request(
|
||||||
.map_err(|e| HandlerError::RequestError(format!("{:#?}", e)))?;
|
.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, scheme, host, *port).await;
|
||||||
return Err(HandlerError::RequestError("JSON-RPC error".to_string()));
|
return Err(HandlerError::RequestError("JSON-RPC error".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconstruct response with the body we consumed
|
// Reconstruct response with the body we consumed
|
||||||
let response = Response::from_parts(parts, Body::from(body_bytes));
|
let response = Response::from_parts(parts, Body::from(body_bytes));
|
||||||
record_success(state, &node_url, latency_ms).await;
|
record_success(state, scheme, host, *port, latency_ms).await;
|
||||||
Ok((response, node_url, latency_ms))
|
Ok((response, node_url, latency_ms))
|
||||||
} else {
|
} else {
|
||||||
// For non-JSON-RPC endpoints, HTTP success is enough
|
// For non-JSON-RPC endpoints, HTTP success is enough
|
||||||
record_success(state, &node_url, latency_ms).await;
|
record_success(state, scheme, host, *port, latency_ms).await;
|
||||||
Ok((response, node_url, latency_ms))
|
Ok((response, node_url, latency_ms))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Non-200 status codes are failures
|
// Non-200 status codes are failures
|
||||||
record_failure(state, &node_url).await;
|
record_failure(state, scheme, host, *port).await;
|
||||||
Err(HandlerError::RequestError(format!(
|
Err(HandlerError::RequestError(format!(
|
||||||
"HTTP {}",
|
"HTTP {}",
|
||||||
response.status()
|
response.status()
|
||||||
|
@ -210,7 +213,7 @@ async fn single_raw_request(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
record_failure(state, &node_url).await;
|
record_failure(state, scheme, host, *port).await;
|
||||||
Err(e)
|
Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,9 +249,9 @@ async fn race_requests(
|
||||||
.await
|
.await
|
||||||
.map_err(|e| HandlerError::PoolError(e.to_string()))?;
|
.map_err(|e| HandlerError::PoolError(e.to_string()))?;
|
||||||
|
|
||||||
let pool: Vec<String> = reliable_nodes
|
let pool: Vec<(String, String, i64)> = reliable_nodes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|node| node.full_url())
|
.map(|node| (node.scheme, node.host, node.port))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
pool
|
pool
|
||||||
|
@ -286,7 +289,7 @@ async fn race_requests(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store node URLs for error tracking before consuming them
|
// Store node URLs for error tracking before consuming them
|
||||||
let current_nodes: Vec<String> = [&node1_option, &node2_option]
|
let current_nodes: Vec<(String, String, i64)> = [&node1_option, &node2_option]
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|opt| opt.as_ref())
|
.filter_map(|opt| opt.as_ref())
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -362,6 +365,9 @@ async fn race_requests(
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok((response, winning_node, latency_ms)) => {
|
Ok((response, winning_node, latency_ms)) => {
|
||||||
|
let (scheme, host, port) = &winning_node;
|
||||||
|
let winning_node = format!("{}://{}:{}", scheme, host, port);
|
||||||
|
|
||||||
match &jsonrpc_method {
|
match &jsonrpc_method {
|
||||||
Some(rpc_method) => {
|
Some(rpc_method) => {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -377,14 +383,15 @@ async fn race_requests(
|
||||||
tried_nodes.len()
|
tried_nodes.len()
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
record_success(state, &winning_node, latency_ms).await;
|
record_success(state, scheme, host, *port, latency_ms).await;
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Since we don't know which specific node failed in the race,
|
// Since we don't know which specific node failed in the race,
|
||||||
// record the error for all nodes in this batch
|
// record the error for all nodes in this batch
|
||||||
for node_url in ¤t_nodes {
|
for (scheme, host, port) in ¤t_nodes {
|
||||||
collected_errors.push((node_url.clone(), e.to_string()));
|
let node_display = format!("{}://{}:{}", scheme, host, port);
|
||||||
|
collected_errors.push((node_display, e.to_string()));
|
||||||
}
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"Request failed: {} - retrying with different nodes from pool...",
|
"Request failed: {} - retrying with different nodes from pool...",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue