From 3be9e06bef1ea56c469d3234637c7e303ab381e4 Mon Sep 17 00:00:00 2001 From: durch Date: Thu, 15 May 2025 13:28:30 +0200 Subject: [PATCH] sqlx prepare, bunch of nits --- ...fb84ab5e7d7435297573523e2532560c2e302.json | 26 ----- ...027595b91739f3579e1f289b0c722ea91bbcc.json | 44 +++++++++ ...83ead09f4d7319b7997fa2a9bb628f9404166.json | 26 ----- .../20250513104800_routes_table.sql | 29 +++--- nym-api/src/support/storage/manager.rs | 97 ++++++++++--------- 5 files changed, 108 insertions(+), 114 deletions(-) delete mode 100644 nym-api/.sqlx/query-676299beb2004ab89f7b38cf21ffb84ab5e7d7435297573523e2532560c2e302.json create mode 100644 nym-api/.sqlx/query-6b2479c02cf1ef5ae674ce0ab4d027595b91739f3579e1f289b0c722ea91bbcc.json delete mode 100644 nym-api/.sqlx/query-c19e1b3768bf2929407599e6e8783ead09f4d7319b7997fa2a9bb628f9404166.json diff --git a/nym-api/.sqlx/query-676299beb2004ab89f7b38cf21ffb84ab5e7d7435297573523e2532560c2e302.json b/nym-api/.sqlx/query-676299beb2004ab89f7b38cf21ffb84ab5e7d7435297573523e2532560c2e302.json deleted file mode 100644 index 35be81ffcb..0000000000 --- a/nym-api/.sqlx/query-676299beb2004ab89f7b38cf21ffb84ab5e7d7435297573523e2532560c2e302.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n d.node_id as \"node_id: NodeId\",\n CASE WHEN count(*) > 3 THEN AVG(reliability) ELSE 100 END as \"value: f32\"\n FROM\n gateway_details d\n JOIN\n gateway_status s on d.id = s.gateway_details_id\n WHERE\n timestamp >= ? AND\n timestamp <= ?\n GROUP BY 1\n ", - "describe": { - "columns": [ - { - "name": "node_id: NodeId", - "ordinal": 0, - "type_info": "Int64" - }, - { - "name": "value: f32", - "ordinal": 1, - "type_info": "Int" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - true - ] - }, - "hash": "676299beb2004ab89f7b38cf21ffb84ab5e7d7435297573523e2532560c2e302" -} diff --git a/nym-api/.sqlx/query-6b2479c02cf1ef5ae674ce0ab4d027595b91739f3579e1f289b0c722ea91bbcc.json b/nym-api/.sqlx/query-6b2479c02cf1ef5ae674ce0ab4d027595b91739f3579e1f289b0c722ea91bbcc.json new file mode 100644 index 0000000000..f1ef38dc95 --- /dev/null +++ b/nym-api/.sqlx/query-6b2479c02cf1ef5ae674ce0ab4d027595b91739f3579e1f289b0c722ea91bbcc.json @@ -0,0 +1,44 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n layer1 as \"layer1\",\n layer2 as \"layer2\",\n layer3 as \"layer3\",\n gw as \"gw\",\n success\n FROM routes\n WHERE timestamp >= ? AND timestamp <= ?\n ORDER BY timestamp ASC\n ", + "describe": { + "columns": [ + { + "name": "layer1", + "ordinal": 0, + "type_info": "Int64" + }, + { + "name": "layer2", + "ordinal": 1, + "type_info": "Int64" + }, + { + "name": "layer3", + "ordinal": 2, + "type_info": "Int64" + }, + { + "name": "gw", + "ordinal": 3, + "type_info": "Int64" + }, + { + "name": "success", + "ordinal": 4, + "type_info": "Bool" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "6b2479c02cf1ef5ae674ce0ab4d027595b91739f3579e1f289b0c722ea91bbcc" +} diff --git a/nym-api/.sqlx/query-c19e1b3768bf2929407599e6e8783ead09f4d7319b7997fa2a9bb628f9404166.json b/nym-api/.sqlx/query-c19e1b3768bf2929407599e6e8783ead09f4d7319b7997fa2a9bb628f9404166.json deleted file mode 100644 index 0c6d2f6072..0000000000 --- a/nym-api/.sqlx/query-c19e1b3768bf2929407599e6e8783ead09f4d7319b7997fa2a9bb628f9404166.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n d.mix_id as \"mix_id: NodeId\",\n AVG(s.reliability) as \"value: f32\"\n FROM\n mixnode_details d\n JOIN\n mixnode_status s on d.id = s.mixnode_details_id\n WHERE\n timestamp >= ? AND\n timestamp <= ?\n GROUP BY 1\n ", - "describe": { - "columns": [ - { - "name": "mix_id: NodeId", - "ordinal": 0, - "type_info": "Int64" - }, - { - "name": "value: f32", - "ordinal": 1, - "type_info": "Int64" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - true - ] - }, - "hash": "c19e1b3768bf2929407599e6e8783ead09f4d7319b7997fa2a9bb628f9404166" -} diff --git a/nym-api/migrations/20250513104800_routes_table.sql b/nym-api/migrations/20250513104800_routes_table.sql index 122c230479..89d5c009ce 100644 --- a/nym-api/migrations/20250513104800_routes_table.sql +++ b/nym-api/migrations/20250513104800_routes_table.sql @@ -1,16 +1,17 @@ --- Drop the table if it exists -DROP TABLE IF EXISTS routes; - --- Create the routes table -CREATE TABLE routes ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - layer1 INTEGER, - layer2 INTEGER, - layer3 INTEGER, - gw INTEGER, - success BOOLEAN +-- Add routes table for storing route metrics data +CREATE TABLE IF NOT EXISTS routes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + layer1 INTEGER NOT NULL, -- NodeId of layer 1 mixnode + layer2 INTEGER NOT NULL, -- NodeId of layer 2 mixnode + layer3 INTEGER NOT NULL, -- NodeId of layer 3 mixnode + gw INTEGER NOT NULL, -- NodeId of gateway + success BOOLEAN NOT NULL, -- Whether the packet was delivered successfully + timestamp INTEGER NOT NULL DEFAULT (unixepoch()) -- When the measurement was taken ); --- Create an index on created_at -CREATE INDEX routes_created_at ON routes(created_at); +-- Add indexes for efficient querying +CREATE INDEX IF NOT EXISTS idx_routes_timestamp ON routes(timestamp); +CREATE INDEX IF NOT EXISTS idx_routes_layer1 ON routes(layer1); +CREATE INDEX IF NOT EXISTS idx_routes_layer2 ON routes(layer2); +CREATE INDEX IF NOT EXISTS idx_routes_layer3 ON routes(layer3); +CREATE INDEX IF NOT EXISTS idx_routes_gw ON routes(gw); \ No newline at end of file diff --git a/nym-api/src/support/storage/manager.rs b/nym-api/src/support/storage/manager.rs index 3d8bd07bfa..836ea4b600 100644 --- a/nym-api/src/support/storage/manager.rs +++ b/nym-api/src/support/storage/manager.rs @@ -96,27 +96,25 @@ impl StorageManager { start_ts_secs: i64, end_ts_secs: i64, ) -> Result, sqlx::Error> { - let result = sqlx::query_as!( - AvgMixnodeReliability, - r#" - SELECT - d.mix_id as "mix_id: NodeId", - AVG(s.reliability) as "value: f32" - FROM - mixnode_details d - JOIN - mixnode_status s on d.id = s.mixnode_details_id - WHERE - timestamp >= ? AND - timestamp <= ? - GROUP BY 1 - "#, - start_ts_secs, - end_ts_secs - ) - .fetch_all(&self.connection_pool) - .await?; - Ok(result) + let corrected_reliabilities = self + .calculate_corrected_node_reliabilities_for_interval(start_ts_secs, end_ts_secs) + .await + .map_err(|_e| sqlx::Error::PoolClosed)?; // Example: map anyhow::Error to sqlx::Error; adjust as needed + + let mut avg_mix_reliabilities = Vec::new(); + + for corrected_node_info in corrected_reliabilities { + // Check if this node_id is a mixnode by attempting to fetch its identity key as a mixnode. + // This relies on get_mixnode_identity_key returning Some for mixnodes and None (or error) for non-mixnodes. + if self.get_mixnode_identity_key(corrected_node_info.node_id).await?.is_some() { + avg_mix_reliabilities.push(AvgMixnodeReliability { + mix_id: corrected_node_info.node_id, + value: Some(corrected_node_info.reliability as f32), + }); + } + } + + Ok(avg_mix_reliabilities) } pub(super) async fn get_all_avg_gateway_reliability_in_interval( @@ -124,27 +122,30 @@ impl StorageManager { start_ts_secs: i64, end_ts_secs: i64, ) -> Result, sqlx::Error> { - let result = sqlx::query_as!( - AvgGatewayReliability, - r#" - SELECT - d.node_id as "node_id: NodeId", - CASE WHEN count(*) > 3 THEN AVG(reliability) ELSE 100 END as "value: f32" - FROM - gateway_details d - JOIN - gateway_status s on d.id = s.gateway_details_id - WHERE - timestamp >= ? AND - timestamp <= ? - GROUP BY 1 - "#, - start_ts_secs, - end_ts_secs - ) - .fetch_all(&self.connection_pool) - .await?; - Ok(result) + let corrected_reliabilities = self + .calculate_corrected_node_reliabilities_for_interval(start_ts_secs, end_ts_secs) + .await + .map_err(|_e| sqlx::Error::PoolClosed)?; // Example: map anyhow::Error to sqlx::Error; adjust as needed + + let mut avg_gateway_reliabilities = Vec::new(); + + for corrected_node_info in corrected_reliabilities { + // Check if this node_id is a gateway. + if self.get_gateway_identity_key(corrected_node_info.node_id).await?.is_some() { + let total_samples = corrected_node_info.pos_samples_in_interval + corrected_node_info.neg_samples_in_interval; + let reliability_value = if total_samples <= 3 { + 100.0 // Default to 100% if 3 or fewer samples + } else { + corrected_node_info.reliability as f32 + }; + + avg_gateway_reliabilities.push(AvgGatewayReliability { + node_id: corrected_node_info.node_id, // AvgGatewayReliability uses node_id + value: Some(reliability_value), + }); + } + } + Ok(avg_gateway_reliabilities) } /// Tries to obtain row id of given mixnode given its identity. @@ -1387,11 +1388,11 @@ impl StorageManager { // Temporary struct to match the expected columns from the 'routes' table // NodeId here is assumed to be compatible with how layer1, etc. are stored (e.g. u32/i32/i64) struct RawRouteData { - layer1: NodeId, - layer2: NodeId, - layer3: NodeId, - gw: NodeId, - success: bool, + layer1: i64, + layer2: i64, + layer3: i64, + gw: i64, + success: Option, // timestamp: i64, // Not explicitly selected into struct, but used in WHERE and ORDER BY } @@ -1420,7 +1421,7 @@ impl StorageManager { Ok(db_routes .into_iter() - .map(|r| (r.layer1, r.layer2, r.layer3, r.gw, r.success)) + .map(|r| (r.layer1 as NodeId, r.layer2 as NodeId, r.layer3 as NodeId, r.gw as NodeId, r.success.unwrap_or_default())) .collect()) }