diff --git a/nym-node-status-api/nym-node-status-api/.env.example b/nym-node-status-api/nym-node-status-api/.env.example new file mode 100644 index 0000000000..7625347a7c --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/.env.example @@ -0,0 +1,32 @@ +# Example environment variables for nym-node-status-api + +# Database configuration +# For SQLite: +# DATABASE_URL=sqlite://nym-node-status-api.sqlite + +# For PostgreSQL: +# DATABASE_URL=postgres://testuser:testpass@localhost:5433/nym_node_status_api_test + +# Network configuration +NETWORK_NAME=sandbox +NYM_API=https://sandbox-nym-api1.nymtech.net/api +NYXD=https://rpc.sandbox.nymtech.net + +# API configuration +NYM_NODE_STATUS_API_HTTP_PORT=8000 +NYM_API_CLIENT_TIMEOUT=15 +SQLX_BUSY_TIMEOUT_S=5 + +# Monitoring intervals +NODE_STATUS_API_MONITOR_REFRESH_INTERVAL=300 +NODE_STATUS_API_TESTRUN_REFRESH_INTERVAL=300 +NODE_STATUS_API_GEODATA_TTL=86400 + +# Agent keys (comma-separated list) +NODE_STATUS_API_AGENT_KEY_LIST= + +# External service tokens +IPINFO_API_TOKEN=your_token_here + +# MixNodes (Optional) +DATA_PROVIDER_DELEGATION_LIST= \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-01ee4a30bc3104712e5bc371a45d614a89d88adf02358800433e06100c13c548.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-01ee4a30bc3104712e5bc371a45d614a89d88adf02358800433e06100c13c548.json deleted file mode 100644 index d59ea9da1a..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-01ee4a30bc3104712e5bc371a45d614a89d88adf02358800433e06100c13c548.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO mixnode_daily_stats (\n mix_id, date_utc,\n total_stake, packets_received,\n packets_sent, packets_dropped\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(mix_id, date_utc) DO UPDATE SET\n total_stake = excluded.total_stake,\n packets_received = mixnode_daily_stats.packets_received + excluded.packets_received,\n packets_sent = mixnode_daily_stats.packets_sent + excluded.packets_sent,\n packets_dropped = mixnode_daily_stats.packets_dropped + excluded.packets_dropped\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "01ee4a30bc3104712e5bc371a45d614a89d88adf02358800433e06100c13c548" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-021c6c65d1ed806d8430bef7883906b42a7e4b280c8efb32db15d7c6a51d7a27.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-021c6c65d1ed806d8430bef7883906b42a7e4b280c8efb32db15d7c6a51d7a27.json index eb5cdd6aaa..8992ec849c 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-021c6c65d1ed806d8430bef7883906b42a7e4b280c8efb32db15d7c6a51d7a27.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-021c6c65d1ed806d8430bef7883906b42a7e4b280c8efb32db15d7c6a51d7a27.json @@ -1,26 +1,26 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "\n SELECT mix_id as node_id, host, http_api_port\n FROM mixnodes\n WHERE bonded = true\n ", "describe": { "columns": [ { - "name": "node_id", "ordinal": 0, - "type_info": "Integer" + "name": "node_id", + "type_info": "Int8" }, { - "name": "host", "ordinal": 1, - "type_info": "Text" + "name": "host", + "type_info": "Varchar" }, { - "name": "http_api_port", "ordinal": 2, - "type_info": "Integer" + "name": "http_api_port", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-06065394c157927e4002ddd5c7c1af626ae15728d615f539470cd7c189312385.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-06065394c157927e4002ddd5c7c1af626ae15728d615f539470cd7c189312385.json deleted file mode 100644 index 205bfdc79b..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-06065394c157927e4002ddd5c7c1af626ae15728d615f539470cd7c189312385.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO mixnode_description (\n mix_id, moniker, website, security_contact, details, last_updated_utc\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (mix_id) DO UPDATE SET\n moniker = excluded.moniker,\n website = excluded.website,\n security_contact = excluded.security_contact,\n details = excluded.details,\n last_updated_utc = excluded.last_updated_utc\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "06065394c157927e4002ddd5c7c1af626ae15728d615f539470cd7c189312385" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json deleted file mode 100644 index ad57224826..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n gateway_identity_key\n FROM\n gateways\n WHERE\n id = ?", - "describe": { - "columns": [ - { - "name": "gateway_identity_key", - "ordinal": 0, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "06b17d1e5f61201a1b7542896ba55c69cd5c1a7e7d87073c94600c783a0a3984" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-0cf0e4d4f30e90caecffd6255ef85dab12730e538be194438f19ed7f198bd50e.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-0cf0e4d4f30e90caecffd6255ef85dab12730e538be194438f19ed7f198bd50e.json deleted file mode 100644 index fda05c400a..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-0cf0e4d4f30e90caecffd6255ef85dab12730e538be194438f19ed7f198bd50e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE\n testruns\n SET\n status = ?\n WHERE\n status = ?\n AND\n last_assigned_utc < ?\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 3 - }, - "nullable": [] - }, - "hash": "0cf0e4d4f30e90caecffd6255ef85dab12730e538be194438f19ed7f198bd50e" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07.json index 75534f6ea7..b32a31ab5a 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07.json @@ -1,43 +1,43 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "\n SELECT\n date_utc as \"date_utc!\",\n SUM(total_stake) as \"total_stake!: i64\",\n SUM(packets_received) as \"total_packets_received!: i64\",\n SUM(packets_sent) as \"total_packets_sent!: i64\",\n SUM(packets_dropped) as \"total_packets_dropped!: i64\"\n FROM (\n SELECT\n date_utc,\n n.total_stake,\n n.packets_received,\n n.packets_sent,\n n.packets_dropped\n FROM nym_node_daily_mixing_stats n\n UNION ALL\n SELECT\n m.date_utc,\n m.total_stake,\n m.packets_received,\n m.packets_sent,\n m.packets_dropped\n FROM mixnode_daily_stats m\n LEFT JOIN nym_node_daily_mixing_stats ON m.mix_id = nym_node_daily_mixing_stats.node_id\n WHERE nym_node_daily_mixing_stats.node_id IS NULL\n )\n GROUP BY date_utc\n ORDER BY date_utc ASC\n ", "describe": { "columns": [ { - "name": "date_utc!", "ordinal": 0, - "type_info": "Text" + "name": "date_utc!", + "type_info": "Varchar" }, { - "name": "total_stake!: i64", "ordinal": 1, - "type_info": "Integer" + "name": "total_stake!: i64", + "type_info": "Numeric" }, { - "name": "total_packets_received!: i64", "ordinal": 2, - "type_info": "Integer" + "name": "total_packets_received!: i64", + "type_info": "Int8" }, { - "name": "total_packets_sent!: i64", "ordinal": 3, - "type_info": "Integer" + "name": "total_packets_sent!: i64", + "type_info": "Int8" }, { - "name": "total_packets_dropped!: i64", "ordinal": 4, - "type_info": "Integer" + "name": "total_packets_dropped!: i64", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ - false, - false, - true, - true, - true + null, + null, + null, + null, + null ] }, "hash": "124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07" diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json index 810e133a8a..c0373a1f5c 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-1327b5118f9144dddbcf8edb11f7dc549cf503409fd6dfedcdc02dbcd61d5454.json @@ -1,29 +1,29 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n key as \"key!\",\n value_json as \"value_json!\",\n last_updated_utc as \"last_updated_utc!\"\n FROM summary", "describe": { "columns": [ { - "name": "key!", "ordinal": 0, - "type_info": "Text" + "name": "key!", + "type_info": "Varchar" }, { - "name": "value_json!", "ordinal": 1, - "type_info": "Text" + "name": "value_json!", + "type_info": "Varchar" }, { - "name": "last_updated_utc!", "ordinal": 2, - "type_info": "Integer" + "name": "last_updated_utc!", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ - true, + false, true, false ] diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-21e44766729777756f6eb04bf3b81df3e591008a1e3fd664ed83ca86ac51bd8c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-21e44766729777756f6eb04bf3b81df3e591008a1e3fd664ed83ca86ac51bd8c.json deleted file mode 100644 index 52929bc782..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-21e44766729777756f6eb04bf3b81df3e591008a1e3fd664ed83ca86ac51bd8c.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO mixnode_packet_stats_raw (\n mix_id, timestamp_utc, packets_received, packets_sent, packets_dropped\n ) VALUES (?, ?, ?, ?, ?)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 5 - }, - "nullable": [] - }, - "hash": "21e44766729777756f6eb04bf3b81df3e591008a1e3fd664ed83ca86ac51bd8c" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json deleted file mode 100644 index 0e24c697ac..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n id,\n gateway_identity_key\n FROM gateways\n WHERE id = ?\n LIMIT 1", - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "gateway_identity_key", - "ordinal": 1, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false - ] - }, - "hash": "2236299f9f691376db54cbd58ec5ceb89b9925cba46efcf4ed79ef0759a01129" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-227539374e7473f6f9642289c5b5d1bcd636315ab23537cb5f6d2f82a2bcb7bf.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-227539374e7473f6f9642289c5b5d1bcd636315ab23537cb5f6d2f82a2bcb7bf.json index a6b5055677..f459f7d5c7 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-227539374e7473f6f9642289c5b5d1bcd636315ab23537cb5f6d2f82a2bcb7bf.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-227539374e7473f6f9642289c5b5d1bcd636315ab23537cb5f6d2f82a2bcb7bf.json @@ -1,21 +1,21 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n node_id,\n bond_info as \"bond_info: serde_json::Value\"\n FROM\n nym_nodes\n WHERE\n bond_info IS NOT NULL\n AND\n self_described IS NOT NULL\n ", "describe": { "columns": [ { - "name": "node_id", "ordinal": 0, - "type_info": "Integer" + "name": "node_id", + "type_info": "Int4" }, { - "name": "bond_info: serde_json::Value", "ordinal": 1, + "name": "bond_info: serde_json::Value", "type_info": "Text" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-25300e435780101fa207c8e26ef2f49ba5db84d63e89440bb494e8327fe73686.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-25300e435780101fa207c8e26ef2f49ba5db84d63e89440bb494e8327fe73686.json index fa5ef3a17f..45ec922037 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-25300e435780101fa207c8e26ef2f49ba5db84d63e89440bb494e8327fe73686.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-25300e435780101fa207c8e26ef2f49ba5db84d63e89440bb494e8327fe73686.json @@ -1,16 +1,16 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "\n SELECT gateway_identity_key\n FROM gateways\n WHERE bonded = true\n ", "describe": { "columns": [ { - "name": "gateway_identity_key", "ordinal": 0, - "type_info": "Text" + "name": "gateway_identity_key", + "type_info": "Varchar" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-283f49a65c7d70bf271702ff6a5c7ad6e68c81932d295ff18ed198c54706a57c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-283f49a65c7d70bf271702ff6a5c7ad6e68c81932d295ff18ed198c54706a57c.json index 5413fe16e5..e92d2f1edf 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-283f49a65c7d70bf271702ff6a5c7ad6e68c81932d295ff18ed198c54706a57c.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-283f49a65c7d70bf271702ff6a5c7ad6e68c81932d295ff18ed198c54706a57c.json @@ -1,71 +1,71 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n node_id,\n ed25519_identity_pubkey,\n total_stake,\n ip_addresses as \"ip_addresses!: serde_json::Value\",\n mix_port,\n x25519_sphinx_pubkey,\n node_role as \"node_role: serde_json::Value\",\n supported_roles as \"supported_roles: serde_json::Value\",\n entry as \"entry: serde_json::Value\",\n performance,\n self_described as \"self_described: serde_json::Value\",\n bond_info as \"bond_info: serde_json::Value\"\n FROM\n nym_nodes\n WHERE\n self_described IS NOT NULL\n AND\n bond_info IS NOT NULL\n ", "describe": { "columns": [ { - "name": "node_id", "ordinal": 0, - "type_info": "Integer" + "name": "node_id", + "type_info": "Int4" }, { - "name": "ed25519_identity_pubkey", "ordinal": 1, - "type_info": "Text" + "name": "ed25519_identity_pubkey", + "type_info": "Varchar" }, { - "name": "total_stake", "ordinal": 2, - "type_info": "Integer" + "name": "total_stake", + "type_info": "Int8" }, { - "name": "ip_addresses!: serde_json::Value", "ordinal": 3, + "name": "ip_addresses!: serde_json::Value", "type_info": "Text" }, { - "name": "mix_port", "ordinal": 4, - "type_info": "Integer" + "name": "mix_port", + "type_info": "Int4" }, { - "name": "x25519_sphinx_pubkey", "ordinal": 5, - "type_info": "Text" + "name": "x25519_sphinx_pubkey", + "type_info": "Varchar" }, { - "name": "node_role: serde_json::Value", "ordinal": 6, + "name": "node_role: serde_json::Value", "type_info": "Text" }, { - "name": "supported_roles: serde_json::Value", "ordinal": 7, + "name": "supported_roles: serde_json::Value", "type_info": "Text" }, { - "name": "entry: serde_json::Value", "ordinal": 8, + "name": "entry: serde_json::Value", "type_info": "Text" }, { - "name": "performance", "ordinal": 9, - "type_info": "Text" + "name": "performance", + "type_info": "Varchar" }, { - "name": "self_described: serde_json::Value", "ordinal": 10, + "name": "self_described: serde_json::Value", "type_info": "Text" }, { - "name": "bond_info: serde_json::Value", "ordinal": 11, + "name": "bond_info: serde_json::Value", "type_info": "Text" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-3243cf5646255a9430d1e6710970505d0dbcc62703f40e090e80ff48c77723c4.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3243cf5646255a9430d1e6710970505d0dbcc62703f40e090e80ff48c77723c4.json deleted file mode 100644 index 7aeb02d48b..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-3243cf5646255a9430d1e6710970505d0dbcc62703f40e090e80ff48c77723c4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT OR IGNORE INTO gateway_session_stats\n (gateway_identity_key, node_id, day,\n unique_active_clients, session_started, users_hashes,\n vpn_sessions, mixnet_sessions, unknown_sessions)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", - "describe": { - "columns": [], - "parameters": { - "Right": 9 - }, - "nullable": [] - }, - "hash": "3243cf5646255a9430d1e6710970505d0dbcc62703f40e090e80ff48c77723c4" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-3cd5cb4bfca4243925da4ddbccd811e842090e98982e1032670df77961870b32.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3cd5cb4bfca4243925da4ddbccd811e842090e98982e1032670df77961870b32.json deleted file mode 100644 index 60ecc30618..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-3cd5cb4bfca4243925da4ddbccd811e842090e98982e1032670df77961870b32.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO mixnodes\n (mix_id, identity_key, bonded, total_stake,\n host, http_api_port, full_details,\n self_described, last_updated_utc, is_dp_delegatee)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(mix_id) DO UPDATE SET\n bonded=excluded.bonded,\n total_stake=excluded.total_stake, host=excluded.host,\n http_api_port=excluded.http_api_port,\n full_details=excluded.full_details,self_described=excluded.self_described,\n last_updated_utc=excluded.last_updated_utc,\n is_dp_delegatee = excluded.is_dp_delegatee;", - "describe": { - "columns": [], - "parameters": { - "Right": 10 - }, - "nullable": [] - }, - "hash": "3cd5cb4bfca4243925da4ddbccd811e842090e98982e1032670df77961870b32" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-3e7e987780937873cdb393b157d7708c9f01047b0689eb0d4f7a973b328c609d.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3e7e987780937873cdb393b157d7708c9f01047b0689eb0d4f7a973b328c609d.json deleted file mode 100644 index d6b7e9be72..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-3e7e987780937873cdb393b157d7708c9f01047b0689eb0d4f7a973b328c609d.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n id as \"id!\",\n gateway_identity_key as \"gateway_identity_key!\",\n self_described as \"self_described?\",\n explorer_pretty_bond as \"explorer_pretty_bond?\"\n FROM gateways\n WHERE gateway_identity_key = ?\n AND bonded = true\n ORDER BY gateway_identity_key\n LIMIT 1", - "describe": { - "columns": [ - { - "name": "id!", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "gateway_identity_key!", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "self_described?", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "explorer_pretty_bond?", - "ordinal": 3, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - true, - false, - false, - true - ] - }, - "hash": "3e7e987780937873cdb393b157d7708c9f01047b0689eb0d4f7a973b328c609d" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-3eb1d8491bda3c1d6e071b6eb364b9a979f4bdb11ea81b2d0f022555bab51ecb.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3eb1d8491bda3c1d6e071b6eb364b9a979f4bdb11ea81b2d0f022555bab51ecb.json deleted file mode 100644 index 78a970dc41..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-3eb1d8491bda3c1d6e071b6eb364b9a979f4bdb11ea81b2d0f022555bab51ecb.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n gw.gateway_identity_key as \"gateway_identity_key!\",\n gw.bonded as \"bonded: bool\",\n gw.performance as \"performance!\",\n gw.self_described as \"self_described?\",\n gw.explorer_pretty_bond as \"explorer_pretty_bond?\",\n gw.last_probe_result as \"last_probe_result?\",\n gw.last_probe_log as \"last_probe_log?\",\n gw.last_testrun_utc as \"last_testrun_utc?\",\n gw.last_updated_utc as \"last_updated_utc!\",\n COALESCE(gd.moniker, \"NA\") as \"moniker!\",\n COALESCE(gd.website, \"NA\") as \"website!\",\n COALESCE(gd.security_contact, \"NA\") as \"security_contact!\",\n COALESCE(gd.details, \"NA\") as \"details!\"\n FROM gateways gw\n LEFT JOIN gateway_description gd\n ON gw.gateway_identity_key = gd.gateway_identity_key\n ORDER BY gw.gateway_identity_key", - "describe": { - "columns": [ - { - "name": "gateway_identity_key!", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "bonded: bool", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "performance!", - "ordinal": 2, - "type_info": "Integer" - }, - { - "name": "self_described?", - "ordinal": 3, - "type_info": "Text" - }, - { - "name": "explorer_pretty_bond?", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "last_probe_result?", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "last_probe_log?", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "last_testrun_utc?", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "last_updated_utc!", - "ordinal": 8, - "type_info": "Integer" - }, - { - "name": "moniker!", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "website!", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "security_contact!", - "ordinal": 11, - "type_info": "Text" - }, - { - "name": "details!", - "ordinal": 12, - "type_info": "Text" - } - ], - "parameters": { - "Right": 0 - }, - "nullable": [ - false, - false, - false, - false, - true, - true, - true, - true, - false, - false, - false, - false, - false - ] - }, - "hash": "3eb1d8491bda3c1d6e071b6eb364b9a979f4bdb11ea81b2d0f022555bab51ecb" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-3fc2baabf194b147b20be2a49401cc0c100a1d7a7c347393adde2410fa6f4dfe.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-3fc2baabf194b147b20be2a49401cc0c100a1d7a7c347393adde2410fa6f4dfe.json deleted file mode 100644 index 9f31fbd172..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-3fc2baabf194b147b20be2a49401cc0c100a1d7a7c347393adde2410fa6f4dfe.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n total_stake\n FROM mixnodes\n WHERE mix_id = ?\n ", - "describe": { - "columns": [ - { - "name": "total_stake", - "ordinal": 0, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "3fc2baabf194b147b20be2a49401cc0c100a1d7a7c347393adde2410fa6f4dfe" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json deleted file mode 100644 index f9eb3657e7..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE testruns SET status = ? WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "418944f2eccb838cb3882f34469203c8569f03fdd39ce09d7b74177896e52a8c" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json deleted file mode 100644 index 6a9fd9d4eb..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE gateways SET last_probe_log = ? WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "4afcc6673890f795c2793f1e2f8570ee787fc7daf00fcb916f18d1cb7d6c8f08" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-4d865e873c9cb133883da94db72dcdebd4969e1f240def9fb1bf946f4a1f342f.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-4d865e873c9cb133883da94db72dcdebd4969e1f240def9fb1bf946f4a1f342f.json deleted file mode 100644 index 08b9e93fff..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-4d865e873c9cb133883da94db72dcdebd4969e1f240def9fb1bf946f4a1f342f.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO testruns (gateway_id, status, ip_address, created_utc, log) VALUES (?, ?, ?, ?, ?)", - "describe": { - "columns": [], - "parameters": { - "Right": 5 - }, - "nullable": [] - }, - "hash": "4d865e873c9cb133883da94db72dcdebd4969e1f240def9fb1bf946f4a1f342f" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-4fca38abbb416d9457c34a8ba4faf481a837eda4f3e1bee1d430a4eb102a5b3d.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-4fca38abbb416d9457c34a8ba4faf481a837eda4f3e1bee1d430a4eb102a5b3d.json new file mode 100644 index 0000000000..ee07d52cc2 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-4fca38abbb416d9457c34a8ba4faf481a837eda4f3e1bee1d430a4eb102a5b3d.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO gateway_session_stats\n (gateway_identity_key, node_id, day,\n unique_active_clients, session_started, users_hashes,\n vpn_sessions, mixnet_sessions, unknown_sessions)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)\n ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Int8", + "Date", + "Int8", + "Int8", + "Varchar", + "Varchar", + "Varchar", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "4fca38abbb416d9457c34a8ba4faf481a837eda4f3e1bee1d430a4eb102a5b3d" +} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-5912ea335a957d217f5e2b3a63a25b31715c2098310fe7a9db688bc2fd36aad4.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-5912ea335a957d217f5e2b3a63a25b31715c2098310fe7a9db688bc2fd36aad4.json deleted file mode 100644 index 08bc84273c..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-5912ea335a957d217f5e2b3a63a25b31715c2098310fe7a9db688bc2fd36aad4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO nym_node_daily_mixing_stats (\n node_id, date_utc,\n total_stake, packets_received,\n packets_sent, packets_dropped\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(node_id, date_utc) DO UPDATE SET\n total_stake = excluded.total_stake,\n packets_received = nym_node_daily_mixing_stats.packets_received + excluded.packets_received,\n packets_sent = nym_node_daily_mixing_stats.packets_sent + excluded.packets_sent,\n packets_dropped = nym_node_daily_mixing_stats.packets_dropped + excluded.packets_dropped\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "5912ea335a957d217f5e2b3a63a25b31715c2098310fe7a9db688bc2fd36aad4" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-5e9cbb39f5fb53774803270f422989e199aac4d4a71913c7074359b4bd676b02.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-5e9cbb39f5fb53774803270f422989e199aac4d4a71913c7074359b4bd676b02.json deleted file mode 100644 index 0fd89dbe54..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-5e9cbb39f5fb53774803270f422989e199aac4d4a71913c7074359b4bd676b02.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE testruns\n SET\n status = ?,\n last_assigned_utc = ?\n WHERE rowid =\n (\n SELECT rowid\n FROM testruns\n WHERE status = ?\n ORDER BY created_utc asc\n LIMIT 1\n )\n RETURNING\n id as \"id!\",\n gateway_id\n ", - "describe": { - "columns": [ - { - "name": "id!", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "gateway_id", - "ordinal": 1, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 3 - }, - "nullable": [ - false, - false - ] - }, - "hash": "5e9cbb39f5fb53774803270f422989e199aac4d4a71913c7074359b4bd676b02" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-664e059ac2c58e1115fe214376a6b326b31c93298f20019772cce2e277a194f8.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-664e059ac2c58e1115fe214376a6b326b31c93298f20019772cce2e277a194f8.json deleted file mode 100644 index 2ba3ec13fa..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-664e059ac2c58e1115fe214376a6b326b31c93298f20019772cce2e277a194f8.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO nym_nodes\n (node_id, ed25519_identity_pubkey,\n total_stake,\n ip_addresses, mix_port,\n x25519_sphinx_pubkey, node_role,\n supported_roles, entry,\n self_described,\n bond_info,\n performance, last_updated_utc\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(node_id) DO UPDATE SET\n ed25519_identity_pubkey=excluded.ed25519_identity_pubkey,\n ip_addresses=excluded.ip_addresses,\n mix_port=excluded.mix_port,\n x25519_sphinx_pubkey=excluded.x25519_sphinx_pubkey,\n node_role=excluded.node_role,\n supported_roles=excluded.supported_roles,\n entry=excluded.entry,\n self_described=excluded.self_described,\n bond_info=excluded.bond_info,\n performance=excluded.performance,\n last_updated_utc=excluded.last_updated_utc\n ;", - "describe": { - "columns": [], - "parameters": { - "Right": 13 - }, - "nullable": [] - }, - "hash": "664e059ac2c58e1115fe214376a6b326b31c93298f20019772cce2e277a194f8" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json index dca66fc2ad..5e60c5a545 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b.json @@ -1,19 +1,19 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT count(id) FROM mixnodes", "describe": { "columns": [ { - "name": "count(id)", "ordinal": 0, - "type_info": "Integer" + "name": "count", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ - false + null ] }, "hash": "670b7ed7d57a6986181b24be24ca667e8cacdf677ccb906415b3fe92be0c436b" diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-6a9780aad1f2f0c8ef780e51fe856679d5e28f95143f4e2a2b409009dc0f55ba.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-6a9780aad1f2f0c8ef780e51fe856679d5e28f95143f4e2a2b409009dc0f55ba.json deleted file mode 100644 index 6ff736dbbb..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-6a9780aad1f2f0c8ef780e51fe856679d5e28f95143f4e2a2b409009dc0f55ba.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO nym_node_descriptions (\n node_id, moniker, website, security_contact, details, last_updated_utc\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (node_id) DO UPDATE SET\n moniker = excluded.moniker,\n website = excluded.website,\n security_contact = excluded.security_contact,\n details = excluded.details,\n last_updated_utc = excluded.last_updated_utc\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "6a9780aad1f2f0c8ef780e51fe856679d5e28f95143f4e2a2b409009dc0f55ba" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json deleted file mode 100644 index 9d93b219f9..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE gateways SET last_probe_result = ? WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "6ef3efde571d46961244cd90420f3de5949a5ff2083453cb879af8a1689efe2f" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json index e697946d25..bdea8047ad 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-7600823da7ce80b8ffda933608603a2752e28df775d1af8fd943a5fc8d7dc00d.json @@ -1,34 +1,34 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n id as \"id!\",\n date as \"date!\",\n timestamp_utc as \"timestamp_utc!\",\n value_json as \"value_json!\"\n FROM summary_history\n ORDER BY date DESC\n LIMIT 30", "describe": { "columns": [ { - "name": "id!", "ordinal": 0, - "type_info": "Integer" + "name": "id!", + "type_info": "Int4" }, { - "name": "date!", "ordinal": 1, - "type_info": "Text" + "name": "date!", + "type_info": "Varchar" }, { - "name": "timestamp_utc!", "ordinal": 2, - "type_info": "Integer" + "name": "timestamp_utc!", + "type_info": "Int8" }, { - "name": "value_json!", "ordinal": 3, - "type_info": "Text" + "name": "value_json!", + "type_info": "Varchar" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ - true, + false, false, false, true diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-786b6a5d954e38b204cebf322711c74c8cf1c08e5e2896a1d6d5b85c91991753.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-786b6a5d954e38b204cebf322711c74c8cf1c08e5e2896a1d6d5b85c91991753.json deleted file mode 100644 index b68078e512..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-786b6a5d954e38b204cebf322711c74c8cf1c08e5e2896a1d6d5b85c91991753.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n COALESCE(packets_received, 0) as \"packets_received!: _\",\n COALESCE(packets_sent, 0) as \"packets_sent!: _\",\n COALESCE(packets_dropped, 0) as \"packets_dropped!: _\"\n FROM mixnode_packet_stats_raw\n WHERE mix_id = ?\n ORDER BY timestamp_utc DESC\n LIMIT 1 OFFSET 1\n ", - "describe": { - "columns": [ - { - "name": "packets_received!: _", - "ordinal": 0, - "type_info": "Null" - }, - { - "name": "packets_sent!: _", - "ordinal": 1, - "type_info": "Null" - }, - { - "name": "packets_dropped!: _", - "ordinal": 2, - "type_info": "Null" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - null, - null, - null - ] - }, - "hash": "786b6a5d954e38b204cebf322711c74c8cf1c08e5e2896a1d6d5b85c91991753" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json deleted file mode 100644 index 5252ccf2e7..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO summary_history\n (date, timestamp_utc, value_json)\n VALUES (?, ?, ?)\n ON CONFLICT(date) DO UPDATE SET\n timestamp_utc=excluded.timestamp_utc,\n value_json=excluded.value_json;", - "describe": { - "columns": [], - "parameters": { - "Right": 3 - }, - "nullable": [] - }, - "hash": "788515c34588aec352773df4b6e6c5e41f3c0bb56a27648b5e25466b8634a578" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json index 89c1e86878..3d922cb7f0 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5.json @@ -1,19 +1,19 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT count(id) FROM gateways", "describe": { "columns": [ { - "name": "count(id)", "ordinal": 0, - "type_info": "Integer" + "name": "count", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ - false + null ] }, "hash": "86ff64db477a1d6235179b0b88d86b86d1b9be62336c9eac0eef44987a5451b5" diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-8bdf85a61e443fa5f4835bffd0bffc8ed1011f56714fde6007e50951e569854b.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-8bdf85a61e443fa5f4835bffd0bffc8ed1011f56714fde6007e50951e569854b.json deleted file mode 100644 index b3a5353a1f..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-8bdf85a61e443fa5f4835bffd0bffc8ed1011f56714fde6007e50951e569854b.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n COALESCE(packets_received, 0) as \"packets_received!: _\",\n COALESCE(packets_sent, 0) as \"packets_sent!: _\",\n COALESCE(packets_dropped, 0) as \"packets_dropped!: _\"\n FROM nym_nodes_packet_stats_raw\n WHERE node_id = ?\n ORDER BY timestamp_utc DESC\n LIMIT 1 OFFSET 1\n ", - "describe": { - "columns": [ - { - "name": "packets_received!: _", - "ordinal": 0, - "type_info": "Null" - }, - { - "name": "packets_sent!: _", - "ordinal": 1, - "type_info": "Null" - }, - { - "name": "packets_dropped!: _", - "ordinal": 2, - "type_info": "Null" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - null, - null, - null - ] - }, - "hash": "8bdf85a61e443fa5f4835bffd0bffc8ed1011f56714fde6007e50951e569854b" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json index 993afdac99..d87f4c21ca 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-930a41e612b4e964ae214843da190f6c66c14d4267a2cc2ca73354becc2c8bb8.json @@ -1,21 +1,21 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n gateway_identity_key as \"gateway_identity_key!\",\n bonded as \"bonded: bool\"\n FROM gateways\n ORDER BY last_testrun_utc", "describe": { "columns": [ { - "name": "gateway_identity_key!", "ordinal": 0, - "type_info": "Text" + "name": "gateway_identity_key!", + "type_info": "Varchar" }, { - "name": "bonded: bool", "ordinal": 1, - "type_info": "Integer" + "name": "bonded: bool", + "type_info": "Bool" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-9796d354ae075eab4cbd3438839c39da94025494395ec7b093aefef696f2d0c5.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-9796d354ae075eab4cbd3438839c39da94025494395ec7b093aefef696f2d0c5.json deleted file mode 100644 index 967a2c648c..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-9796d354ae075eab4cbd3438839c39da94025494395ec7b093aefef696f2d0c5.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO gateways\n (gateway_identity_key, bonded,\n self_described, explorer_pretty_bond,\n last_updated_utc, performance)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(gateway_identity_key) DO UPDATE SET\n bonded=excluded.bonded,\n self_described=excluded.self_described,\n explorer_pretty_bond=excluded.explorer_pretty_bond,\n last_updated_utc=excluded.last_updated_utc,\n performance = excluded.performance;", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "9796d354ae075eab4cbd3438839c39da94025494395ec7b093aefef696f2d0c5" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-a1d9eb816acd1a91ed0975c801c9295c01a78861a2a0597ad28b1579a14bf008.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-a1d9eb816acd1a91ed0975c801c9295c01a78861a2a0597ad28b1579a14bf008.json deleted file mode 100644 index 7a370a2753..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-a1d9eb816acd1a91ed0975c801c9295c01a78861a2a0597ad28b1579a14bf008.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n id as \"id!\",\n gateway_id as \"gateway_id!\",\n status as \"status!\",\n created_utc as \"created_utc!\",\n ip_address as \"ip_address!\",\n log as \"log!\",\n last_assigned_utc\n FROM testruns\n WHERE gateway_id = ? AND status != 2\n ORDER BY id DESC\n LIMIT 1", - "describe": { - "columns": [ - { - "name": "id!", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "gateway_id!", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "status!", - "ordinal": 2, - "type_info": "Integer" - }, - { - "name": "created_utc!", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "ip_address!", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "log!", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "last_assigned_utc", - "ordinal": 6, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true - ] - }, - "hash": "a1d9eb816acd1a91ed0975c801c9295c01a78861a2a0597ad28b1579a14bf008" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-a79a61b87325f3f1d9c5a4fb386ccd585be0641e5878acb6283b879f22ed2b4c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-a79a61b87325f3f1d9c5a4fb386ccd585be0641e5878acb6283b879f22ed2b4c.json deleted file mode 100644 index d4324443b4..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-a79a61b87325f3f1d9c5a4fb386ccd585be0641e5878acb6283b879f22ed2b4c.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n COUNT(id) as \"count: i64\"\n FROM testruns\n WHERE\n status = ?\n ", - "describe": { - "columns": [ - { - "name": "count: i64", - "ordinal": 0, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "a79a61b87325f3f1d9c5a4fb386ccd585be0641e5878acb6283b879f22ed2b4c" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-aa602604c0e7b6eef41ea3cd83c16610e15be2d7ee3f6c4d3debf23f95fb9c2e.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-aa602604c0e7b6eef41ea3cd83c16610e15be2d7ee3f6c4d3debf23f95fb9c2e.json deleted file mode 100644 index 62ac2b4bb6..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-aa602604c0e7b6eef41ea3cd83c16610e15be2d7ee3f6c4d3debf23f95fb9c2e.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n nd.node_id,\n moniker,\n website,\n security_contact,\n details\n FROM\n nym_node_descriptions nd\n INNER JOIN\n nym_nodes\n WHERE\n bond_info IS NOT NULL\n ", - "describe": { - "columns": [ - { - "name": "node_id", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "moniker", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "website", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "security_contact", - "ordinal": 3, - "type_info": "Text" - }, - { - "name": "details", - "ordinal": 4, - "type_info": "Text" - } - ], - "parameters": { - "Right": 0 - }, - "nullable": [ - false, - true, - true, - true, - true - ] - }, - "hash": "aa602604c0e7b6eef41ea3cd83c16610e15be2d7ee3f6c4d3debf23f95fb9c2e" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-b68796d1d8d2384b30f1aace06269682c4ae96f774261f5c298264d3c12e5b67.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-b68796d1d8d2384b30f1aace06269682c4ae96f774261f5c298264d3c12e5b67.json index 383c3681f0..141b3da977 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-b68796d1d8d2384b30f1aace06269682c4ae96f774261f5c298264d3c12e5b67.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-b68796d1d8d2384b30f1aace06269682c4ae96f774261f5c298264d3c12e5b67.json @@ -1,10 +1,10 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "UPDATE nym_nodes\n SET\n self_described = NULL,\n bond_info = NULL", "describe": { "columns": [], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [] }, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json deleted file mode 100644 index 8cc95e72de..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "UPDATE gateways SET last_testrun_utc = ?, last_updated_utc = ? WHERE id = ?", - "describe": { - "columns": [], - "parameters": { - "Right": 3 - }, - "nullable": [] - }, - "hash": "c214c001acbbf79fa499816f36ec586c4c29c03efb4cf0c40b73a5c76159cf5c" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-c42917c9542c1d720d92035863064741aefc9f7a7d1630f6b863ebd8174b6684.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c42917c9542c1d720d92035863064741aefc9f7a7d1630f6b863ebd8174b6684.json index 86b8a642bd..8fd572d965 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-c42917c9542c1d720d92035863064741aefc9f7a7d1630f6b863ebd8174b6684.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-c42917c9542c1d720d92035863064741aefc9f7a7d1630f6b863ebd8174b6684.json @@ -1,10 +1,10 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "UPDATE\n mixnodes\n SET\n bonded = false\n ", "describe": { "columns": [], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [] }, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-9334f0c91252fcd7ec72558a271222615bb282e5334665700709ae475a5daea2.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c48d04fc3de59dd484f0a63d40336ced54e08785f77e9ef85f3157d004ec85dc.json similarity index 83% rename from nym-node-status-api/nym-node-status-api/.sqlx/query-9334f0c91252fcd7ec72558a271222615bb282e5334665700709ae475a5daea2.json rename to nym-node-status-api/nym-node-status-api/.sqlx/query-c48d04fc3de59dd484f0a63d40336ced54e08785f77e9ef85f3157d004ec85dc.json index 55968f7c3a..d25be8f69a 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-9334f0c91252fcd7ec72558a271222615bb282e5334665700709ae475a5daea2.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-c48d04fc3de59dd484f0a63d40336ced54e08785f77e9ef85f3157d004ec85dc.json @@ -1,71 +1,71 @@ { - "db_name": "SQLite", - "query": "SELECT\n node_id,\n ed25519_identity_pubkey,\n total_stake,\n ip_addresses as \"ip_addresses!: serde_json::Value\",\n mix_port,\n x25519_sphinx_pubkey,\n node_role as \"node_role: serde_json::Value\",\n supported_roles as \"supported_roles: serde_json::Value\",\n entry as \"entry: serde_json::Value\",\n performance,\n self_described as \"self_described: serde_json::Value\",\n bond_info as \"bond_info: serde_json::Value\"\n FROM\n nym_nodes\n ", + "db_name": "PostgreSQL", + "query": "SELECT\n node_id,\n ed25519_identity_pubkey,\n total_stake,\n ip_addresses as \"ip_addresses!: serde_json::Value\",\n mix_port,\n x25519_sphinx_pubkey,\n node_role as \"node_role: serde_json::Value\",\n supported_roles as \"supported_roles: serde_json::Value\",\n entry as \"entry: serde_json::Value\",\n performance,\n self_described as \"self_described: serde_json::Value\",\n bond_info as \"bond_info: serde_json::Value\"\n FROM\n nym_nodes\n ORDER BY\n node_id\n ", "describe": { "columns": [ { - "name": "node_id", "ordinal": 0, - "type_info": "Integer" + "name": "node_id", + "type_info": "Int4" }, { - "name": "ed25519_identity_pubkey", "ordinal": 1, - "type_info": "Text" + "name": "ed25519_identity_pubkey", + "type_info": "Varchar" }, { - "name": "total_stake", "ordinal": 2, - "type_info": "Integer" + "name": "total_stake", + "type_info": "Int8" }, { - "name": "ip_addresses!: serde_json::Value", "ordinal": 3, + "name": "ip_addresses!: serde_json::Value", "type_info": "Text" }, { - "name": "mix_port", "ordinal": 4, - "type_info": "Integer" + "name": "mix_port", + "type_info": "Int4" }, { - "name": "x25519_sphinx_pubkey", "ordinal": 5, - "type_info": "Text" + "name": "x25519_sphinx_pubkey", + "type_info": "Varchar" }, { - "name": "node_role: serde_json::Value", "ordinal": 6, + "name": "node_role: serde_json::Value", "type_info": "Text" }, { - "name": "supported_roles: serde_json::Value", "ordinal": 7, + "name": "supported_roles: serde_json::Value", "type_info": "Text" }, { - "name": "entry: serde_json::Value", "ordinal": 8, + "name": "entry: serde_json::Value", "type_info": "Text" }, { - "name": "performance", "ordinal": 9, - "type_info": "Text" + "name": "performance", + "type_info": "Varchar" }, { - "name": "self_described: serde_json::Value", "ordinal": 10, + "name": "self_described: serde_json::Value", "type_info": "Text" }, { - "name": "bond_info: serde_json::Value", "ordinal": 11, + "name": "bond_info: serde_json::Value", "type_info": "Text" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, @@ -82,5 +82,5 @@ true ] }, - "hash": "9334f0c91252fcd7ec72558a271222615bb282e5334665700709ae475a5daea2" + "hash": "c48d04fc3de59dd484f0a63d40336ced54e08785f77e9ef85f3157d004ec85dc" } diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-c7656b2b1b4328415772ce69d0568bd5438d6c8496ca9cbdcfb70bb5375b345e.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c7656b2b1b4328415772ce69d0568bd5438d6c8496ca9cbdcfb70bb5375b345e.json index 54fef15e56..a3dec3dad6 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-c7656b2b1b4328415772ce69d0568bd5438d6c8496ca9cbdcfb70bb5375b345e.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-c7656b2b1b4328415772ce69d0568bd5438d6c8496ca9cbdcfb70bb5375b345e.json @@ -1,21 +1,21 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "SELECT\n node_id,\n self_described as \"self_described: serde_json::Value\"\n FROM\n nym_nodes\n WHERE\n self_described IS NOT NULL\n ORDER BY\n node_id\n ", "describe": { "columns": [ { - "name": "node_id", "ordinal": 0, - "type_info": "Integer" + "name": "node_id", + "type_info": "Int4" }, { - "name": "self_described: serde_json::Value", "ordinal": 1, + "name": "self_described: serde_json::Value", "type_info": "Text" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-c910788edefe64bbb34379702bcbde9ec6159c9fa03b13652e1f620dcd92125e.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c910788edefe64bbb34379702bcbde9ec6159c9fa03b13652e1f620dcd92125e.json index 5c88b5737e..14fa1c9f12 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-c910788edefe64bbb34379702bcbde9ec6159c9fa03b13652e1f620dcd92125e.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-c910788edefe64bbb34379702bcbde9ec6159c9fa03b13652e1f620dcd92125e.json @@ -1,16 +1,16 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "\n SELECT mix_id\n FROM mixnodes\n WHERE bonded = true\n ", "describe": { "columns": [ { - "name": "mix_id", "ordinal": 0, - "type_info": "Integer" + "name": "mix_id", + "type_info": "Int8" } ], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [ false diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-c9e61180ec35dfab8623333fafa3b216b93440d0fddc0a37dd1b6c1813741f6a.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-c9e61180ec35dfab8623333fafa3b216b93440d0fddc0a37dd1b6c1813741f6a.json deleted file mode 100644 index 0d313098b6..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-c9e61180ec35dfab8623333fafa3b216b93440d0fddc0a37dd1b6c1813741f6a.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "DELETE FROM gateway_session_stats WHERE day <= ?", - "describe": { - "columns": [], - "parameters": { - "Right": 1 - }, - "nullable": [] - }, - "hash": "c9e61180ec35dfab8623333fafa3b216b93440d0fddc0a37dd1b6c1813741f6a" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-d2e07d44594ca5b44a6100482ff432c39d761f2a0ac1d6515cf73416f2eb6c61.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-d2e07d44594ca5b44a6100482ff432c39d761f2a0ac1d6515cf73416f2eb6c61.json deleted file mode 100644 index 09138b5556..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-d2e07d44594ca5b44a6100482ff432c39d761f2a0ac1d6515cf73416f2eb6c61.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n SELECT\n total_stake\n FROM nym_nodes\n WHERE node_id = ?\n ", - "describe": { - "columns": [ - { - "name": "total_stake", - "ordinal": 0, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - }, - "hash": "d2e07d44594ca5b44a6100482ff432c39d761f2a0ac1d6515cf73416f2eb6c61" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json deleted file mode 100644 index 5f7443bd50..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT INTO summary\n (key, value_json, last_updated_utc)\n VALUES (?, ?, ?)\n ON CONFLICT(key) DO UPDATE SET\n value_json=excluded.value_json,\n last_updated_utc=excluded.last_updated_utc;", - "describe": { - "columns": [], - "parameters": { - "Right": 3 - }, - "nullable": [] - }, - "hash": "e0c76a959276e3b0f44c720af9c74a5bf4912ee73468e62e7d0d96b1d9074cbe" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-e9790b63ebe4bff5172bb8cb7bfc288364855003cf0e4d63e95047e7b502c650.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-e9790b63ebe4bff5172bb8cb7bfc288364855003cf0e4d63e95047e7b502c650.json deleted file mode 100644 index 9f0d25204f..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-e9790b63ebe4bff5172bb8cb7bfc288364855003cf0e4d63e95047e7b502c650.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO gateway_description (\n gateway_identity_key,\n moniker,\n website,\n security_contact,\n details,\n last_updated_utc\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT (gateway_identity_key) DO UPDATE SET\n moniker = excluded.moniker,\n website = excluded.website,\n security_contact = excluded.security_contact,\n details = excluded.details,\n last_updated_utc = excluded.last_updated_utc\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 6 - }, - "nullable": [] - }, - "hash": "e9790b63ebe4bff5172bb8cb7bfc288364855003cf0e4d63e95047e7b502c650" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-f0c64794cbaed87a1d3166251d8e6720c9a9fc929144188460849be85d915004.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-f0c64794cbaed87a1d3166251d8e6720c9a9fc929144188460849be85d915004.json deleted file mode 100644 index 7790b606af..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-f0c64794cbaed87a1d3166251d8e6720c9a9fc929144188460849be85d915004.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n id as \"id!\",\n gateway_id as \"gateway_id!\",\n status as \"status!\",\n created_utc as \"created_utc!\",\n ip_address as \"ip_address!\",\n log as \"log!\",\n last_assigned_utc\n FROM testruns\n WHERE\n id = ?\n AND\n status = ?\n ORDER BY created_utc\n LIMIT 1", - "describe": { - "columns": [ - { - "name": "id!", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "gateway_id!", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "status!", - "ordinal": 2, - "type_info": "Integer" - }, - { - "name": "created_utc!", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "ip_address!", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "log!", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "last_assigned_utc", - "ordinal": 6, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true - ] - }, - "hash": "f0c64794cbaed87a1d3166251d8e6720c9a9fc929144188460849be85d915004" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-f75af377da33db1455c6e0f612e0fa9583888f343b8b59faf37fc6799b244379.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-f75af377da33db1455c6e0f612e0fa9583888f343b8b59faf37fc6799b244379.json deleted file mode 100644 index 7e222fb211..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-f75af377da33db1455c6e0f612e0fa9583888f343b8b59faf37fc6799b244379.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT\n mn.mix_id as \"mix_id!\",\n mn.bonded as \"bonded: bool\",\n mn.is_dp_delegatee as \"is_dp_delegatee: bool\",\n mn.total_stake as \"total_stake!\",\n mn.full_details as \"full_details!\",\n mn.self_described as \"self_described\",\n mn.last_updated_utc as \"last_updated_utc!\",\n COALESCE(md.moniker, \"NA\") as \"moniker!\",\n COALESCE(md.website, \"NA\") as \"website!\",\n COALESCE(md.security_contact, \"NA\") as \"security_contact!\",\n COALESCE(md.details, \"NA\") as \"details!\"\n FROM mixnodes mn\n LEFT JOIN mixnode_description md ON mn.mix_id = md.mix_id\n ORDER BY mn.mix_id", - "describe": { - "columns": [ - { - "name": "mix_id!", - "ordinal": 0, - "type_info": "Integer" - }, - { - "name": "bonded: bool", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "is_dp_delegatee: bool", - "ordinal": 2, - "type_info": "Integer" - }, - { - "name": "total_stake!", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "full_details!", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "self_described", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "last_updated_utc!", - "ordinal": 6, - "type_info": "Integer" - }, - { - "name": "moniker!", - "ordinal": 7, - "type_info": "Text" - }, - { - "name": "website!", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "security_contact!", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "details!", - "ordinal": 10, - "type_info": "Text" - } - ], - "parameters": { - "Right": 0 - }, - "nullable": [ - false, - false, - false, - false, - true, - true, - false, - false, - false, - false, - false - ] - }, - "hash": "f75af377da33db1455c6e0f612e0fa9583888f343b8b59faf37fc6799b244379" -} diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-f7e3fa31d68c028bf39cc95389f29f8758ec922dd2e7ea064a1e537e580c9ee5.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-f7e3fa31d68c028bf39cc95389f29f8758ec922dd2e7ea064a1e537e580c9ee5.json index da95053996..bfa4d81356 100644 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-f7e3fa31d68c028bf39cc95389f29f8758ec922dd2e7ea064a1e537e580c9ee5.json +++ b/nym-node-status-api/nym-node-status-api/.sqlx/query-f7e3fa31d68c028bf39cc95389f29f8758ec922dd2e7ea064a1e537e580c9ee5.json @@ -1,10 +1,10 @@ { - "db_name": "SQLite", + "db_name": "PostgreSQL", "query": "UPDATE\n gateways\n SET\n bonded = false\n ", "describe": { "columns": [], "parameters": { - "Right": 0 + "Left": [] }, "nullable": [] }, diff --git a/nym-node-status-api/nym-node-status-api/.sqlx/query-fcb1698d9e0e3a14524c92e7c99a811588c2bbc50d4975487a0464321a1b18c9.json b/nym-node-status-api/nym-node-status-api/.sqlx/query-fcb1698d9e0e3a14524c92e7c99a811588c2bbc50d4975487a0464321a1b18c9.json deleted file mode 100644 index 296c6389d2..0000000000 --- a/nym-node-status-api/nym-node-status-api/.sqlx/query-fcb1698d9e0e3a14524c92e7c99a811588c2bbc50d4975487a0464321a1b18c9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n INSERT INTO nym_nodes_packet_stats_raw (\n node_id, timestamp_utc, packets_received, packets_sent, packets_dropped\n ) VALUES (?, ?, ?, ?, ?)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 5 - }, - "nullable": [] - }, - "hash": "fcb1698d9e0e3a14524c92e7c99a811588c2bbc50d4975487a0464321a1b18c9" -} diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 916f30eb1f..edd0e777e4 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -28,11 +28,15 @@ moka = { workspace = true, features = ["future"] } # Nym API: revert after Cheddar is out nym-contracts-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } nym-mixnet-contract-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } -nym-bin-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar", features = ["openapi"]} +nym-bin-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar", features = [ + "openapi", +] } nym-node-status-client = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } nym-crypto = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } nym-http-api-client = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } -nym-http-api-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar", features = ["middleware"]} +nym-http-api-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar", features = [ + "middleware", +] } nym-network-defaults = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } nym-serde-helpers = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } nym-statistics-common = { git = "https://github.com/nymtech/nym.git", branch = "release/2025.11-cheddar" } @@ -62,7 +66,7 @@ serde_json = { workspace = true } serde_json_path = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true } -sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "time"] } +sqlx = { workspace = true, features = ["runtime-tokio-rustls", "time"] } thiserror = { workspace = true } time = { workspace = true, features = ["formatting"] } tokio = { workspace = true, features = ["rt-multi-thread"] } @@ -77,13 +81,16 @@ utoipauto = { workspace = true } nym-node-metrics = { path = "../../nym-node/nym-node-metrics" } +[features] +default = ["pg"] +sqlite = ["sqlx/sqlite"] +pg = ["sqlx/postgres"] [build-dependencies] anyhow = { workspace = true } tokio = { workspace = true, features = ["macros"] } sqlx = { workspace = true, features = [ "runtime-tokio-rustls", - "sqlite", "macros", "migrate", ] } diff --git a/nym-node-status-api/nym-node-status-api/Makefile b/nym-node-status-api/nym-node-status-api/Makefile new file mode 100644 index 0000000000..1b2db88b23 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/Makefile @@ -0,0 +1,104 @@ +# Makefile for nym-node-status-api database management + +# --- Configuration --- +TEST_DATABASE_URL := postgres://testuser:testpass@localhost:5433/nym_node_status_api_test + +# Docker compose service names +DB_SERVICE_NAME := postgres-test +DB_CONTAINER_NAME := nym_node_status_api_postgres_test + +# Default target +.PHONY: default +default: help + +# --- Main Targets --- +.PHONY: prepare-pg +prepare-pg: test-db-up test-db-wait test-db-migrate test-db-prepare test-db-down ## Setup PostgreSQL and prepare SQLx offline cache + +.PHONY: test-db +test-db: test-db-up test-db-wait test-db-migrate test-db-run test-db-down ## Run tests with PostgreSQL database + +.PHONY: dev-db +dev-db: test-db-up test-db-wait test-db-migrate ## Start PostgreSQL for development (keeps running) + @echo "PostgreSQL is running on port 5433" + @echo "Connection string: $(TEST_DATABASE_URL)" + +# --- Docker Compose Targets --- +.PHONY: test-db-up +test-db-up: ## Start the PostgreSQL test database in the background + @echo "Starting PostgreSQL test database..." + docker compose up -d $(DB_SERVICE_NAME) + +.PHONY: test-db-wait +test-db-wait: ## Wait for the PostgreSQL database to be healthy + @echo "Waiting for PostgreSQL database..." + @while ! docker inspect --format='{{.State.Health.Status}}' $(DB_CONTAINER_NAME) 2>/dev/null | grep -q 'healthy'; do \ + echo -n "."; \ + sleep 1; \ + done; \ + echo " Database is healthy!" + +.PHONY: test-db-down +test-db-down: ## Stop and remove the test database + @echo "Stopping PostgreSQL test database..." + docker compose down + +# --- SQLx Targets --- +.PHONY: test-db-migrate +test-db-migrate: ## Run database migrations against PostgreSQL + @echo "Running PostgreSQL migrations..." + DATABASE_URL="$(TEST_DATABASE_URL)" sqlx migrate run --source migrations_pg + +.PHONY: test-db-prepare +test-db-prepare: ## Run sqlx prepare for compile-time query verification + @echo "Running sqlx prepare for PostgreSQL..." + DATABASE_URL="$(TEST_DATABASE_URL)" cargo sqlx prepare -- --features pg + +# --- Build and Test Targets --- +.PHONY: test-db-run +test-db-run: ## Run tests with PostgreSQL feature + @echo "Running tests with PostgreSQL..." + DATABASE_URL="$(TEST_DATABASE_URL)" cargo test --features pg --no-default-features + +.PHONY: build-pg +build-pg: ## Build with PostgreSQL feature + @echo "Building with PostgreSQL feature..." + cargo build --features pg --no-default-features + +.PHONY: build-sqlite +build-sqlite: ## Build with SQLite feature (default) + @echo "Building with SQLite feature..." + cargo build --features sqlite --no-default-features + +.PHONY: check-pg +check-pg: ## Check code with PostgreSQL feature + @echo "Checking code with PostgreSQL feature..." + cargo check --features pg --no-default-features + +.PHONY: check-sqlite +check-sqlite: ## Check code with SQLite feature + @echo "Checking code with SQLite feature..." + cargo check --features sqlite --no-default-features + +# --- Cleanup Targets --- +.PHONY: clean +clean: ## Clean build artifacts and SQLx cache + cargo clean + rm -rf .sqlx + +.PHONY: clean-db +clean-db: test-db-down ## Stop database and clean volumes + docker volume rm -f nym-node-status-api_postgres_test_data 2>/dev/null || true + +# --- Utility Targets --- +.PHONY: sqlx-cli +sqlx-cli: ## Install sqlx-cli if not already installed + @command -v sqlx >/dev/null 2>&1 || cargo install sqlx-cli --features postgres,sqlite + +.PHONY: psql +psql: ## Connect to the running PostgreSQL database with psql + @docker exec -it $(DB_CONTAINER_NAME) psql -U testuser -d nym_node_status_api_test + +.PHONY: help +help: ## Show help for Makefile targets + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' diff --git a/nym-node-status-api/nym-node-status-api/README_PG.md b/nym-node-status-api/nym-node-status-api/README_PG.md new file mode 100644 index 0000000000..8a6d2c3f0b --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/README_PG.md @@ -0,0 +1,104 @@ +# PostgreSQL Support for nym-node-status-api + +This project now supports both SQLite (default) and PostgreSQL databases. + +## Quick Start with PostgreSQL + +### 1. Install Prerequisites + +```bash +# Install sqlx-cli if not already installed +make sqlx-cli +``` + +### 2. Prepare PostgreSQL for Development + +```bash +# This will: +# - Start PostgreSQL in Docker +# - Run migrations +# - Generate SQLx offline query cache +# - Stop the database +make prepare-pg +``` + +### 3. Build with PostgreSQL + +```bash +# Build with PostgreSQL feature +make build-pg + +# Or manually: +cargo build --features pg --no-default-features +``` + +### 4. Run with PostgreSQL + +```bash +# Start PostgreSQL for development (keeps running) +make dev-db + +# In another terminal, run the application +DATABASE_URL=postgres://testuser:testpass@localhost:5433/nym_node_status_api_test \ +cargo run --features pg --no-default-features +``` + +## Database Features + +- `sqlite` (default): Uses SQLite database +- `pg`: Uses PostgreSQL database + +Only one database feature can be active at a time. + +## Migration Differences + +SQLite migrations are in `migrations/`, PostgreSQL migrations are in `migrations_pg/`. + +Key differences: +- **AUTOINCREMENT** → **SERIAL** +- **INTEGER CHECK (0,1)** → **BOOLEAN** +- **REAL** → **DOUBLE PRECISION** +- No table recreation needed for constraint changes in PostgreSQL + +## Makefile Targets + +```bash +make help # Show all available targets +make prepare-pg # Setup PostgreSQL and prepare SQLx cache +make dev-db # Start PostgreSQL for development +make test-db # Run tests with PostgreSQL +make build-pg # Build with PostgreSQL +make build-sqlite # Build with SQLite +make psql # Connect to running PostgreSQL +make clean # Clean build artifacts +make clean-db # Stop database and clean volumes +``` + +## Environment Variables + +See `.env.example` for all configuration options. Key variable: + +```bash +# For PostgreSQL: +DATABASE_URL=postgres://testuser:testpass@localhost:5433/nym_node_status_api_test + +# For SQLite: +DATABASE_URL=sqlite://nym-node-status-api.sqlite +``` + +## Troubleshooting + +### SQLx Offline Mode + +If you see "no cached data for this query" errors: + +1. Ensure PostgreSQL is running: `make dev-db` +2. Run: `make test-db-prepare` + +### Connection Refused + +If you see "Connection refused" errors: + +1. Check Docker is running: `docker ps` +2. Check PostgreSQL container: `docker ps | grep nym_node_status_api_postgres_test` +3. Restart database: `make test-db-down && make dev-db` \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/build.rs b/nym-node-status-api/nym-node-status-api/build.rs index 9da6d48d2a..9f237d54ba 100644 --- a/nym-node-status-api/nym-node-status-api/build.rs +++ b/nym-node-status-api/nym-node-status-api/build.rs @@ -1,17 +1,20 @@ -use anyhow::{anyhow, Result}; +use anyhow::Result; +#[cfg(feature = "sqlite")] use sqlx::{Connection, SqliteConnection}; +#[cfg(feature = "sqlite")] #[cfg(target_family = "unix")] use std::fs::Permissions; +#[cfg(feature = "sqlite")] #[cfg(target_family = "unix")] use std::os::unix::fs::PermissionsExt; +#[cfg(feature = "sqlite")] use tokio::{fs::File, io::AsyncWriteExt}; +#[cfg(feature = "sqlite")] const SQLITE_DB_FILENAME: &str = "nym-node-status-api.sqlite"; -/// If you need to re-run migrations or reset the db, just run -/// cargo clean -p nym-node-status-api -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<()> { +#[cfg(feature = "sqlite")] +async fn init_db() -> Result<()> { let out_dir = read_env_var("OUT_DIR")?; let database_path = format!("{out_dir}/{SQLITE_DB_FILENAME}?mode=rwc"); @@ -30,11 +33,30 @@ async fn main() -> Result<()> { Ok(()) } +#[cfg(all(feature = "pg", not(feature = "sqlite")))] +async fn init_db() -> Result<()> { + // PostgreSQL doesn't need build-time initialization + // Just ensure DATABASE_URL is available for runtime + if let Ok(database_url) = std::env::var("DATABASE_URL") { + println!("cargo::rustc-env=DATABASE_URL={database_url}"); + } + Ok(()) +} + +/// If you need to re-run migrations or reset the db, just run +/// cargo clean -p nym-node-status-api +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<()> { + init_db().await +} + +#[cfg(feature = "sqlite")] fn read_env_var(var: &str) -> Result { - std::env::var(var).map_err(|_| anyhow!("You need to set {} env var", var)) + std::env::var(var).map_err(|_| anyhow::anyhow!("You need to set {} env var", var)) } /// use `./enter_db.sh` to inspect DB +#[cfg(feature = "sqlite")] async fn write_db_path_to_file(out_dir: &str, db_filename: &str) -> anyhow::Result<()> { let mut file = File::create("settings.sql").await?; let settings = ".mode columns diff --git a/nym-node-status-api/nym-node-status-api/docker-compose.yml b/nym-node-status-api/nym-node-status-api/docker-compose.yml new file mode 100644 index 0000000000..12dbe51031 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/docker-compose.yml @@ -0,0 +1,21 @@ +services: + postgres-test: + image: postgres:16-alpine + container_name: nym_node_status_api_postgres_test + environment: + POSTGRES_DB: nym_node_status_api_test + POSTGRES_USER: testuser + POSTGRES_PASSWORD: testpass + ports: + - '5433:5432' # Map to 5433 to avoid conflicts with default PostgreSQL + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U testuser -d nym_node_status_api_test'] + interval: 5s + timeout: 5s + retries: 5 + # Optional: Add volume for persistent data during development + # volumes: + # - postgres_test_data:/var/lib/postgresql/data + +# volumes: +# postgres_test_data: \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000000_init.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000000_init.sql new file mode 100644 index 0000000000..23f84e8667 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000000_init.sql @@ -0,0 +1,113 @@ +CREATE TABLE gateways +( + id SERIAL PRIMARY KEY, + gateway_identity_key VARCHAR NOT NULL UNIQUE, + self_described VARCHAR NOT NULL, + explorer_pretty_bond VARCHAR, + last_probe_result VARCHAR, + last_probe_log VARCHAR, + config_score INTEGER NOT NULL DEFAULT 0, + config_score_successes DOUBLE PRECISION NOT NULL DEFAULT 0, + config_score_samples DOUBLE PRECISION NOT NULL DEFAULT 0, + routing_score INTEGER NOT NULL DEFAULT 0, + routing_score_successes DOUBLE PRECISION NOT NULL DEFAULT 0, + routing_score_samples DOUBLE PRECISION NOT NULL DEFAULT 0, + test_run_samples DOUBLE PRECISION NOT NULL DEFAULT 0, + last_testrun_utc BIGINT, + last_updated_utc BIGINT NOT NULL, + bonded BOOLEAN NOT NULL DEFAULT FALSE, + blacklisted BOOLEAN NOT NULL DEFAULT FALSE, + performance INTEGER NOT NULL DEFAULT 0 +); + +CREATE INDEX idx_gateway_description_gateway_identity_key ON gateways (gateway_identity_key); + + +CREATE TABLE mixnodes ( + id SERIAL PRIMARY KEY, + identity_key VARCHAR NOT NULL UNIQUE, + mix_id BIGINT NOT NULL UNIQUE, + bonded BOOLEAN NOT NULL DEFAULT FALSE, + total_stake BIGINT NOT NULL, + host VARCHAR NOT NULL, + http_api_port BIGINT NOT NULL, + blacklisted BOOLEAN NOT NULL DEFAULT FALSE, + full_details VARCHAR, + self_described VARCHAR, + last_updated_utc BIGINT NOT NULL, + is_dp_delegatee BOOLEAN NOT NULL DEFAULT FALSE +); + +CREATE INDEX idx_mixnodes_mix_id ON mixnodes (mix_id); +CREATE INDEX idx_mixnodes_identity_key ON mixnodes (identity_key); + +CREATE TABLE mixnode_description ( + id SERIAL PRIMARY KEY, + mix_id BIGINT UNIQUE NOT NULL, + moniker VARCHAR, + website VARCHAR, + security_contact VARCHAR, + details VARCHAR, + last_updated_utc BIGINT NOT NULL, + FOREIGN KEY (mix_id) REFERENCES mixnodes (mix_id) +); + +-- Indexes for description table +CREATE INDEX idx_mixnode_description_mix_id ON mixnode_description (mix_id); + + +CREATE TABLE summary +( + key VARCHAR PRIMARY KEY, + value_json VARCHAR, + last_updated_utc BIGINT NOT NULL +); + + +CREATE TABLE summary_history +( + id SERIAL PRIMARY KEY, + date VARCHAR UNIQUE NOT NULL, + timestamp_utc BIGINT NOT NULL, + value_json VARCHAR +); + +CREATE INDEX idx_summary_history_timestamp_utc ON summary_history (timestamp_utc); +CREATE INDEX idx_summary_history_date ON summary_history (date); + + +CREATE TABLE gateway_description ( + id SERIAL PRIMARY KEY, + gateway_identity_key VARCHAR UNIQUE NOT NULL, + moniker VARCHAR, + website VARCHAR, + security_contact VARCHAR, + details VARCHAR, + last_updated_utc BIGINT NOT NULL, + FOREIGN KEY (gateway_identity_key) REFERENCES gateways (gateway_identity_key) +); + + +CREATE TABLE mixnode_daily_stats ( + id SERIAL PRIMARY KEY, + mix_id BIGINT NOT NULL, + total_stake BIGINT NOT NULL, + date_utc VARCHAR NOT NULL, + packets_received INTEGER DEFAULT 0, + packets_sent INTEGER DEFAULT 0, + packets_dropped INTEGER DEFAULT 0, + FOREIGN KEY (mix_id) REFERENCES mixnodes (mix_id), + UNIQUE (mix_id, date_utc) -- This constraint automatically creates an index +); + + +CREATE TABLE testruns +( + id SERIAL PRIMARY KEY, + gateway_id INTEGER NOT NULL, + status INTEGER NOT NULL, -- 0=pending, 1=in-progress, 2=complete + timestamp_utc BIGINT NOT NULL, + ip_address VARCHAR NOT NULL, + log VARCHAR NOT NULL, + FOREIGN KEY (gateway_id) REFERENCES gateways (id) +); \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000001_last_assigned_utc.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000001_last_assigned_utc.sql new file mode 100644 index 0000000000..f5929f0034 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000001_last_assigned_utc.sql @@ -0,0 +1,5 @@ +ALTER TABLE testruns +RENAME COLUMN timestamp_utc TO created_utc; + +ALTER TABLE testruns +ADD COLUMN last_assigned_utc BIGINT; \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000002_session_stats.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000002_session_stats.sql new file mode 100644 index 0000000000..e2d8e8440c --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000002_session_stats.sql @@ -0,0 +1,16 @@ +CREATE TABLE gateway_session_stats ( + id SERIAL PRIMARY KEY, + gateway_identity_key VARCHAR NOT NULL, + node_id BIGINT NOT NULL, + day DATE NOT NULL, + unique_active_clients BIGINT NOT NULL, + session_started BIGINT NOT NULL, + users_hashes VARCHAR, + vpn_sessions VARCHAR, + mixnet_sessions VARCHAR, + unknown_sessions VARCHAR, + UNIQUE (node_id, day) -- This constraint automatically creates an index +); + +CREATE INDEX idx_gateway_session_stats_identity_key ON gateway_session_stats (gateway_identity_key); +CREATE INDEX idx_gateway_session_stats_day ON gateway_session_stats (day); \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000003_scraper_tables.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000003_scraper_tables.sql new file mode 100644 index 0000000000..ba591789d5 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000003_scraper_tables.sql @@ -0,0 +1,11 @@ +CREATE TABLE mixnode_packet_stats_raw ( + id SERIAL PRIMARY KEY, + mix_id BIGINT NOT NULL, + timestamp_utc BIGINT NOT NULL, + packets_received INTEGER, + packets_sent INTEGER, + packets_dropped INTEGER, + FOREIGN KEY (mix_id) REFERENCES mixnodes (mix_id) +); + +CREATE INDEX idx_mixnode_packet_stats_raw_mix_id_timestamp_utc ON mixnode_packet_stats_raw (mix_id, timestamp_utc); \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000004_obsolete_fields.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000004_obsolete_fields.sql new file mode 100644 index 0000000000..a473ab1190 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000004_obsolete_fields.sql @@ -0,0 +1,54 @@ +ALTER TABLE mixnodes DROP COLUMN blacklisted; +ALTER TABLE gateways DROP COLUMN blacklisted; + +CREATE TABLE nym_nodes ( + node_id INTEGER PRIMARY KEY, + ed25519_identity_pubkey VARCHAR NOT NULL UNIQUE, + total_stake BIGINT NOT NULL, + ip_addresses TEXT NOT NULL, + mix_port INTEGER NOT NULL, + x25519_sphinx_pubkey VARCHAR NOT NULL UNIQUE, + node_role TEXT NOT NULL, + supported_roles TEXT NOT NULL, + performance VARCHAR NOT NULL, + entry TEXT, + last_updated_utc INTEGER NOT NULL +); + +CREATE INDEX idx_nym_nodes_node_id ON nym_nodes (node_id); +CREATE INDEX idx_nym_nodes_ed25519_identity_pubkey ON nym_nodes (ed25519_identity_pubkey); + +CREATE TABLE nym_node_descriptions ( + id SERIAL PRIMARY KEY, + node_id INTEGER UNIQUE NOT NULL, + moniker VARCHAR, + website VARCHAR, + security_contact VARCHAR, + details VARCHAR, + last_updated_utc INTEGER NOT NULL, + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id) +); + +CREATE TABLE nym_nodes_packet_stats_raw ( + id SERIAL PRIMARY KEY, + node_id INTEGER NOT NULL, + timestamp_utc INTEGER NOT NULL, + packets_received INTEGER, + packets_sent INTEGER, + packets_dropped INTEGER, + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id) +); + +CREATE INDEX idx_nym_nodes_packet_stats_raw_node_id_timestamp_utc ON nym_nodes_packet_stats_raw (node_id, timestamp_utc); + +CREATE TABLE nym_node_daily_mixing_stats ( + id SERIAL PRIMARY KEY, + node_id INTEGER NOT NULL, + total_stake BIGINT NOT NULL, + date_utc VARCHAR NOT NULL, + packets_received INTEGER DEFAULT 0, + packets_sent INTEGER DEFAULT 0, + packets_dropped INTEGER DEFAULT 0, + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id), + UNIQUE (node_id, date_utc) -- This constraint automatically creates an index +); \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000005_node_self_described.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000005_node_self_described.sql new file mode 100644 index 0000000000..8e7bc7ef10 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000005_node_self_described.sql @@ -0,0 +1,23 @@ +ALTER TABLE nym_nodes ADD COLUMN self_described TEXT; +ALTER TABLE nym_nodes ADD COLUMN bond_info TEXT; + +-- PostgreSQL doesn't need table recreation for adding ON DELETE CASCADE +-- We can drop and recreate the foreign key constraints directly + +-- Drop existing foreign key constraints +ALTER TABLE nym_node_descriptions DROP CONSTRAINT IF EXISTS nym_node_descriptions_node_id_fkey; +ALTER TABLE nym_nodes_packet_stats_raw DROP CONSTRAINT IF EXISTS nym_nodes_packet_stats_raw_node_id_fkey; +ALTER TABLE nym_node_daily_mixing_stats DROP CONSTRAINT IF EXISTS nym_node_daily_mixing_stats_node_id_fkey; + +-- Add foreign key constraints with ON DELETE CASCADE +ALTER TABLE nym_node_descriptions + ADD CONSTRAINT nym_node_descriptions_node_id_fkey + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id) ON DELETE CASCADE; + +ALTER TABLE nym_nodes_packet_stats_raw + ADD CONSTRAINT nym_nodes_packet_stats_raw_node_id_fkey + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id) ON DELETE CASCADE; + +ALTER TABLE nym_node_daily_mixing_stats + ADD CONSTRAINT nym_node_daily_mixing_stats_node_id_fkey + FOREIGN KEY (node_id) REFERENCES nym_nodes (node_id) ON DELETE CASCADE; \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000006_remove_unique_constraint.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000006_remove_unique_constraint.sql new file mode 100644 index 0000000000..98a7b75ca7 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000006_remove_unique_constraint.sql @@ -0,0 +1,9 @@ +-- Removing UNIQUE constraints on nym_nodes +-- In PostgreSQL, we can drop constraints directly without recreating the table + +-- Drop the unique constraints +ALTER TABLE nym_nodes DROP CONSTRAINT IF EXISTS nym_nodes_ed25519_identity_pubkey_key; +ALTER TABLE nym_nodes DROP CONSTRAINT IF EXISTS nym_nodes_x25519_sphinx_pubkey_key; + +-- The columns and indexes remain, only the unique constraints are removed +-- The existing indexes idx_nym_nodes_node_id and idx_nym_nodes_ed25519_identity_pubkey remain unchanged \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000007_date_fix.sql b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000007_date_fix.sql new file mode 100644 index 0000000000..64fb3064f7 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/migrations_pg/20240101000007_date_fix.sql @@ -0,0 +1,112 @@ +-- for a couple of days after migrating chrono -> time, we stored dates as +-- 2025-June-DD instead of 2025-06-DD. This migration fixes those entries. +-- +-- Because of a UNIQUE constraint on (node_id, date_utc), we can't just rename in-place. +-- - merge (add) node stats back to the original table where conflict (node_id, date_utc) would exist +-- - delete invalid records from original table (those stats were merged into correct rows above) +-- - insert rows that did not have a conflicting (node_Id, date_utc) combo +-- Conflicts affect only the date which has both kinds of entries, +-- e.g. 2025-06-05 and 2025-June-05 (date when this change was deployed) +-- +-- This applies to both affected tables. + +-- ---------------------------------------- +-- mixnode_daily_stats +-- ---------------------------------------- + +-- First, copy over rows with invalid date to a temp table (in the correct date format) +CREATE TEMP TABLE tmp_mix AS +SELECT + mix_id, + REPLACE(date_utc,'June','06') AS new_date, + SUM(total_stake) AS total_stake_sum, + SUM(packets_received) AS packets_received_sum, + SUM(packets_sent) AS packets_sent_sum, + SUM(packets_dropped) AS packets_dropped_sum +FROM mixnode_daily_stats +WHERE date_utc LIKE '%June%' +GROUP BY mix_id, new_date; + +UPDATE mixnode_daily_stats AS m +SET + total_stake = m.total_stake, + packets_received = m.packets_received + (SELECT packets_received_sum FROM tmp_mix WHERE mix_id = m.mix_id AND new_date = m.date_utc), + packets_sent = m.packets_sent + (SELECT packets_sent_sum FROM tmp_mix WHERE mix_id = m.mix_id AND new_date = m.date_utc), + packets_dropped = m.packets_dropped + (SELECT packets_dropped_sum FROM tmp_mix WHERE mix_id = m.mix_id AND new_date = m.date_utc) +WHERE EXISTS ( + SELECT 1 FROM tmp_mix + WHERE mix_id = m.mix_id + AND new_date = m.date_utc +); + +DELETE FROM mixnode_daily_stats + WHERE date_utc LIKE '%June%'; + +INSERT INTO mixnode_daily_stats + (mix_id, date_utc, total_stake, packets_received, packets_sent, packets_dropped) +SELECT + mix_id, + new_date, + total_stake_sum, + packets_received_sum, + packets_sent_sum, + packets_dropped_sum +FROM tmp_mix AS t +-- only those whose new_date did _not_ already exist +WHERE NOT EXISTS ( + SELECT 1 FROM mixnode_daily_stats AS m + WHERE m.mix_id = t.mix_id + AND m.date_utc = t.new_date +); + +DROP TABLE tmp_mix; + + +-- ---------------------------------------- +-- nym_node_daily_mixing_stats +-- ---------------------------------------- + +CREATE TEMP TABLE tmp_nym_node_stats AS +SELECT + node_id, + REPLACE(date_utc,'June','06') AS new_date, + SUM(total_stake) AS total_stake_sum, + SUM(packets_received) AS packets_received_sum, + SUM(packets_sent) AS packets_sent_sum, + SUM(packets_dropped) AS packets_dropped_sum +FROM nym_node_daily_mixing_stats +WHERE date_utc LIKE '%June%' +GROUP BY node_id, new_date; + +UPDATE nym_node_daily_mixing_stats AS m +SET + total_stake = m.total_stake, + packets_received = m.packets_received + (SELECT packets_received_sum FROM tmp_nym_node_stats WHERE node_id = m.node_id AND new_date = m.date_utc), + packets_sent = m.packets_sent + (SELECT packets_sent_sum FROM tmp_nym_node_stats WHERE node_id = m.node_id AND new_date = m.date_utc), + packets_dropped = m.packets_dropped + (SELECT packets_dropped_sum FROM tmp_nym_node_stats WHERE node_id = m.node_id AND new_date = m.date_utc) +WHERE EXISTS ( + SELECT 1 FROM tmp_nym_node_stats + WHERE node_id = m.node_id + AND new_date = m.date_utc +); + +DELETE FROM nym_node_daily_mixing_stats + WHERE date_utc LIKE '%June%'; + +INSERT INTO nym_node_daily_mixing_stats + (node_id, date_utc, total_stake, packets_received, packets_sent, packets_dropped) +SELECT + node_id, + new_date, + total_stake_sum, + packets_received_sum, + packets_sent_sum, + packets_dropped_sum +FROM tmp_nym_node_stats AS t +WHERE NOT EXISTS ( + SELECT 1 FROM nym_node_daily_mixing_stats AS m + WHERE m.node_id = t.node_id + AND m.date_utc = t.new_date +); + +DROP TABLE tmp_nym_node_stats; \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/src/db/mod.rs b/nym-node-status-api/nym-node-status-api/src/db/mod.rs index 3f7d944906..ecc4e85446 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/mod.rs @@ -1,24 +1,53 @@ use anyhow::{anyhow, Result}; -use sqlx::{ - migrate::Migrator, - query, - sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteSynchronous}, - ConnectOptions, SqlitePool, -}; use std::{str::FromStr, time::Duration}; pub(crate) mod models; pub(crate) mod queries; +pub(crate) mod query_wrapper; +// Re-export the query wrapper functions for easier access +pub(crate) use query_wrapper::query; +#[allow(unused_imports)] +pub(crate) use query_wrapper::{query_as, query_scalar}; + +#[cfg(feature = "sqlite")] +use sqlx::{ + migrate::Migrator, + sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteSynchronous}, + ConnectOptions, SqlitePool, +}; + +#[cfg(feature = "pg")] +use sqlx::{ + migrate::Migrator, + postgres::PgConnectOptions, + ConnectOptions, PgPool, +}; + +#[cfg(feature = "sqlite")] static MIGRATOR: Migrator = sqlx::migrate!("./migrations"); +#[cfg(feature = "pg")] +static MIGRATOR: Migrator = sqlx::migrate!("./migrations_pg"); + +#[cfg(feature = "sqlite")] pub(crate) type DbPool = SqlitePool; +#[cfg(feature = "pg")] +pub(crate) type DbPool = PgPool; + +#[cfg(feature = "sqlite")] +pub(crate) type DbConnection = sqlx::pool::PoolConnection; + +#[cfg(feature = "pg")] +pub(crate) type DbConnection = sqlx::pool::PoolConnection; + pub(crate) struct Storage { pool: DbPool, } impl Storage { + #[cfg(feature = "sqlite")] pub async fn init(connection_url: String, busy_timeout: Duration) -> Result { let connect_options = SqliteConnectOptions::from_str(&connection_url)? .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal) @@ -41,16 +70,31 @@ impl Storage { Ok(Storage { pool }) } + #[cfg(feature = "pg")] + pub async fn init(connection_url: String, _busy_timeout: Duration) -> Result { + let connect_options = PgConnectOptions::from_str(&connection_url)? + .disable_statement_logging(); + + let pool = sqlx::PgPool::connect_with(connect_options) + .await + .map_err(|err| anyhow!("Failed to connect to {}: {}", &connection_url, err))?; + + MIGRATOR.run(&pool).await?; + + Ok(Storage { pool }) + } + /// Cloning pool is cheap, it's the same underlying set of connections pub fn pool_owned(&self) -> DbPool { self.pool.clone() } + #[cfg(feature = "sqlite")] async fn assert_busy_timeout(pool: DbPool, expected_busy_timeout_s: i64) -> Result<()> { let mut conn = pool.acquire().await?; // Sqlite stores this value as miliseconds // https://www.sqlite.org/pragma.html#pragma_busy_timeout - let busy_timeout_db = query!("PRAGMA busy_timeout;") + let busy_timeout_db = sqlx::query!("PRAGMA busy_timeout;") .fetch_one(conn.as_mut()) .await?; @@ -68,4 +112,4 @@ impl Storage { Ok(()) } -} +} \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs index adb4241835..63bd5da284 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways.rs @@ -3,17 +3,16 @@ use std::collections::HashSet; use crate::{ db::{ models::{GatewayDto, GatewayInsertRecord}, - DbPool, + DbConnection, DbPool, }, http::models::Gateway, mixnet_scraper::helpers::NodeDescriptionResponse, }; use futures_util::TryStreamExt; -use sqlx::{pool::PoolConnection, Sqlite}; use tracing::error; pub(crate) async fn select_gateway_identity( - conn: &mut PoolConnection, + conn: &mut DbConnection, gateway_pk: i64, ) -> anyhow::Result { let record = sqlx::query!( @@ -131,7 +130,7 @@ pub(crate) async fn get_bonded_gateway_id_keys(pool: &DbPool) -> anyhow::Result< } pub(crate) async fn insert_gateway_description( - conn: &mut PoolConnection, + conn: &mut DbConnection, identity_key: &str, description: &NodeDescriptionResponse, timestamp: i64, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs index 8ba813ee1f..41ddf8ee04 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/gateways_stats.rs @@ -6,6 +6,7 @@ use futures_util::TryStreamExt; use time::Date; use tracing::error; +#[cfg(feature = "sqlite")] pub(crate) async fn insert_session_records( pool: &DbPool, records: Vec, @@ -36,6 +37,38 @@ pub(crate) async fn insert_session_records( Ok(()) } +#[cfg(feature = "pg")] +pub(crate) async fn insert_session_records( + pool: &DbPool, + records: Vec, +) -> anyhow::Result<()> { + let mut tx = pool.begin().await?; + for record in records { + sqlx::query!( + "INSERT INTO gateway_session_stats + (gateway_identity_key, node_id, day, + unique_active_clients, session_started, users_hashes, + vpn_sessions, mixnet_sessions, unknown_sessions) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + ON CONFLICT DO NOTHING", + record.gateway_identity_key, + record.node_id, + record.day, + record.unique_active_clients, + record.session_started, + record.users_hashes, + record.vpn_sessions, + record.mixnet_sessions, + record.unknown_sessions, + ) + .execute(&mut *tx) + .await?; + } + tx.commit().await?; + + Ok(()) +} + pub(crate) async fn get_sessions_stats(pool: &DbPool) -> anyhow::Result> { let mut conn = pool.acquire().await?; let items = sqlx::query_as( diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs index 98709e099e..6bec0ba226 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/mixnodes.rs @@ -1,13 +1,12 @@ use std::collections::HashSet; use futures_util::TryStreamExt; -use sqlx::{pool::PoolConnection, Sqlite}; use tracing::error; use crate::{ db::{ models::{MixnodeDto, MixnodeRecord}, - DbPool, + DbConnection, DbPool, }, http::models::{DailyStats, Mixnode}, mixnet_scraper::helpers::NodeDescriptionResponse, @@ -31,9 +30,9 @@ pub(crate) async fn update_mixnodes( .await?; // existing nodes get updated on insert - for record in mixnodes.iter() { + for record in mixnodes.into_iter() { // https://www.sqlite.org/lang_upsert.html - sqlx::query!( + crate::db::query( "INSERT INTO mixnodes (mix_id, identity_key, bonded, total_stake, host, http_api_port, full_details, @@ -46,17 +45,17 @@ pub(crate) async fn update_mixnodes( full_details=excluded.full_details,self_described=excluded.self_described, last_updated_utc=excluded.last_updated_utc, is_dp_delegatee = excluded.is_dp_delegatee;", - record.mix_id, - record.identity_key, - record.bonded, - record.total_stake, - record.host, - record.http_port, - record.full_details, - record.self_described, - record.last_updated_utc, - record.is_dp_delegatee ) + .bind(record.mix_id as i64) + .bind(record.identity_key) + .bind(record.bonded) + .bind(record.total_stake) + .bind(record.host) + .bind(record.http_port as i32) + .bind(record.full_details) + .bind(record.self_described) + .bind(record.last_updated_utc) + .bind(record.is_dp_delegatee) .execute(&mut *tx) .await?; } @@ -161,7 +160,7 @@ pub(crate) async fn get_bonded_mix_ids(pool: &DbPool) -> anyhow::Result, + conn: &mut DbConnection, mix_id: &i64, description: &NodeDescriptionResponse, timestamp: i64, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs index 5595b10fcc..ad1a6a9531 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/nym_nodes.rs @@ -4,14 +4,13 @@ use nym_validator_client::{ client::{NodeId, NymNodeDetails}, models::NymNodeDescription, }; -use sqlx::{pool::PoolConnection, Sqlite}; use std::collections::HashMap; use tracing::instrument; use crate::{ db::{ models::{NymNodeDto, NymNodeInsertRecord}, - DbPool, + DbConnection, DbPool, }, mixnet_scraper::helpers::NodeDescriptionResponse, }; @@ -266,7 +265,7 @@ pub(crate) async fn get_bonded_node_description( } pub(crate) async fn insert_nym_node_description( - conn: &mut PoolConnection, + conn: &mut DbConnection, node_id: &i64, description: &NodeDescriptionResponse, timestamp: i64, diff --git a/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs b/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs index 469442296c..dfbe0d8122 100644 --- a/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs +++ b/nym-node-status-api/nym-node-status-api/src/db/queries/testruns.rs @@ -1,29 +1,27 @@ use crate::db::models::{TestRunDto, TestRunStatus}; +use crate::db::DbConnection; use crate::db::DbPool; use crate::http::models::TestrunAssignment; use crate::utils::now_utc; -use sqlx::{pool::PoolConnection, Sqlite}; use time::Duration; -pub(crate) async fn count_testruns_in_progress( - conn: &mut PoolConnection, -) -> anyhow::Result { - sqlx::query_scalar!( - r#"SELECT - COUNT(id) as "count: i64" - FROM testruns - WHERE - status = ? - "#, - TestRunStatus::InProgress as i64, - ) - .fetch_one(conn.as_mut()) - .await - .map_err(anyhow::Error::from) +pub(crate) async fn count_testruns_in_progress(conn: &mut DbConnection) -> anyhow::Result { + #[cfg(feature = "sqlite")] + let sql = "SELECT COUNT(id) FROM testruns WHERE status = ?"; + + #[cfg(feature = "pg")] + let sql = "SELECT COUNT(id) FROM testruns WHERE status = $1"; + + let count: i64 = sqlx::query_scalar(sql) + .bind(TestRunStatus::InProgress as i64) + .fetch_one(conn.as_mut()) + .await?; + + Ok(count) } pub(crate) async fn get_in_progress_testrun_by_id( - conn: &mut PoolConnection, + conn: &mut DbConnection, testrun_id: i64, ) -> anyhow::Result { sqlx::query_as!( @@ -89,7 +87,7 @@ pub(crate) async fn update_testruns_assigned_before( } pub(crate) async fn assign_oldest_testrun( - conn: &mut PoolConnection, + conn: &mut DbConnection, ) -> anyhow::Result> { let now = now_utc().unix_timestamp(); // find & mark as "In progress" in the same transaction to avoid race conditions @@ -142,7 +140,7 @@ pub(crate) async fn assign_oldest_testrun( } pub(crate) async fn update_testrun_status( - conn: &mut PoolConnection, + conn: &mut DbConnection, testrun_id: i64, status: TestRunStatus, ) -> anyhow::Result<()> { @@ -159,7 +157,7 @@ pub(crate) async fn update_testrun_status( } pub(crate) async fn update_gateway_last_probe_log( - conn: &mut PoolConnection, + conn: &mut DbConnection, gateway_pk: i64, log: &str, ) -> anyhow::Result<()> { @@ -175,7 +173,7 @@ pub(crate) async fn update_gateway_last_probe_log( } pub(crate) async fn update_gateway_last_probe_result( - conn: &mut PoolConnection, + conn: &mut DbConnection, gateway_pk: i64, result: &str, ) -> anyhow::Result<()> { @@ -191,7 +189,7 @@ pub(crate) async fn update_gateway_last_probe_result( } pub(crate) async fn update_gateway_score( - conn: &mut PoolConnection, + conn: &mut DbConnection, gateway_pk: i64, ) -> anyhow::Result<()> { let now = now_utc().unix_timestamp(); diff --git a/nym-node-status-api/nym-node-status-api/src/db/query_wrapper.rs b/nym-node-status-api/nym-node-status-api/src/db/query_wrapper.rs new file mode 100644 index 0000000000..1fac3874b1 --- /dev/null +++ b/nym-node-status-api/nym-node-status-api/src/db/query_wrapper.rs @@ -0,0 +1,122 @@ +use sqlx::Database; + +/// Converts SQLite-style ? placeholders to PostgreSQL $N format +#[cfg(feature = "pg")] +fn convert_placeholders(query: &str) -> String { + let mut result = String::with_capacity(query.len() + 10); + let mut placeholder_count = 0; + let mut chars = query.chars().peekable(); + let mut in_string = false; + let mut escape_next = false; + + while let Some(ch) = chars.next() { + if escape_next { + result.push(ch); + escape_next = false; + continue; + } + + match ch { + '\\' => { + result.push(ch); + escape_next = true; + } + '\'' => { + result.push(ch); + in_string = !in_string; + } + '?' if !in_string => { + placeholder_count += 1; + result.push_str(&format!("${}", placeholder_count)); + } + _ => { + result.push(ch); + } + } + } + + result +} + +/// Creates a query that automatically handles placeholder conversion +#[cfg(feature = "sqlite")] +pub fn query(sql: &str) -> sqlx::query::Query<'_, sqlx::Sqlite, ::Arguments<'_>> { + sqlx::query(sql) +} + +#[cfg(feature = "pg")] +pub fn query(sql: &str) -> sqlx::query::Query<'static, sqlx::Postgres, ::Arguments<'static>> { + let converted = convert_placeholders(sql); + sqlx::query(Box::leak(converted.into_boxed_str())) +} + +/// Creates a query_as that automatically handles placeholder conversion +#[cfg(feature = "sqlite")] +pub fn query_as(sql: &str) -> sqlx::query::QueryAs<'_, sqlx::Sqlite, O, ::Arguments<'_>> +where + O: for<'r> sqlx::FromRow<'r, ::Row>, +{ + sqlx::query_as(sql) +} + +#[cfg(feature = "pg")] +pub fn query_as(sql: &str) -> sqlx::query::QueryAs<'static, sqlx::Postgres, O, ::Arguments<'static>> +where + O: for<'r> sqlx::FromRow<'r, ::Row>, +{ + let converted = convert_placeholders(sql); + sqlx::query_as(Box::leak(converted.into_boxed_str())) +} + +/// Creates a query_scalar that automatically handles placeholder conversion +#[cfg(feature = "sqlite")] +pub fn query_scalar(sql: &str) -> sqlx::query::QueryScalar<'_, sqlx::Sqlite, O, ::Arguments<'_>> +where + (O,): for<'r> sqlx::FromRow<'r, ::Row>, +{ + sqlx::query_scalar(sql) +} + +#[cfg(feature = "pg")] +pub fn query_scalar(sql: &str) -> sqlx::query::QueryScalar<'static, sqlx::Postgres, O, ::Arguments<'static>> +where + (O,): for<'r> sqlx::FromRow<'r, ::Row>, +{ + let converted = convert_placeholders(sql); + sqlx::query_scalar(Box::leak(converted.into_boxed_str())) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(feature = "pg")] + fn test_convert_placeholders() { + assert_eq!( + convert_placeholders("SELECT * FROM table WHERE id = ?"), + "SELECT * FROM table WHERE id = $1" + ); + + assert_eq!( + convert_placeholders("INSERT INTO table (a, b, c) VALUES (?, ?, ?)"), + "INSERT INTO table (a, b, c) VALUES ($1, $2, $3)" + ); + + assert_eq!( + convert_placeholders("SELECT * FROM table WHERE name = 'test?' AND id = ?"), + "SELECT * FROM table WHERE name = 'test?' AND id = $1" + ); + + assert_eq!( + convert_placeholders("UPDATE table SET a = ?, b = ? WHERE id = ?"), + "UPDATE table SET a = $1, b = $2 WHERE id = $3" + ); + + // Test with 10 placeholders (like in update_mixnodes) + assert_eq!( + convert_placeholders("INSERT INTO t VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), + "INSERT INTO t VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)" + ); + } +} \ No newline at end of file diff --git a/nym-node-status-api/nym-node-status-api/src/main.rs b/nym-node-status-api/nym-node-status-api/src/main.rs index 7db3015a7d..8b6ba55659 100644 --- a/nym-node-status-api/nym-node-status-api/src/main.rs +++ b/nym-node-status-api/nym-node-status-api/src/main.rs @@ -5,6 +5,12 @@ use nym_task::signal::wait_for_signal; use nym_validator_client::nyxd::NyxdClient; use std::sync::Arc; +#[cfg(all(feature = "sqlite", feature = "pg"))] +compile_error!("Features 'sqlite' and 'pg' are mutually exclusive"); + +#[cfg(not(any(feature = "sqlite", feature = "pg")))] +compile_error!("Either 'sqlite' or 'pg' feature must be enabled"); + mod cli; mod db; mod http; diff --git a/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/helpers.rs b/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/helpers.rs index 986f1472c5..d62d911b9a 100644 --- a/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/helpers.rs +++ b/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/helpers.rs @@ -5,6 +5,7 @@ use crate::{ get_raw_node_stats, insert_daily_node_stats, insert_node_packet_stats, insert_scraped_node_description, }, + DbPool, }, utils::{generate_node_name, now_utc}, }; @@ -12,7 +13,6 @@ use ammonia::Builder; use anyhow::{anyhow, Result}; use reqwest; use serde::{Deserialize, Serialize}; -use sqlx::SqlitePool; use std::time::Duration; use time::UtcDateTime; @@ -116,7 +116,7 @@ pub fn sanitize_description( } } -pub async fn scrape_and_store_description(pool: &SqlitePool, node: &ScraperNodeInfo) -> Result<()> { +pub async fn scrape_and_store_description(pool: &DbPool, node: &ScraperNodeInfo) -> Result<()> { let client = build_client()?; let urls = node.contact_addresses(); @@ -157,7 +157,7 @@ pub async fn scrape_and_store_description(pool: &SqlitePool, node: &ScraperNodeI } pub async fn scrape_and_store_packet_stats( - pool: &SqlitePool, + pool: &DbPool, node: &ScraperNodeInfo, ) -> Result<()> { let client = build_client()?; @@ -198,7 +198,7 @@ pub async fn scrape_and_store_packet_stats( } pub async fn update_daily_stats( - pool: &SqlitePool, + pool: &DbPool, node: &ScraperNodeInfo, timestamp: UtcDateTime, current_stats: &NodeStats, diff --git a/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/mod.rs b/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/mod.rs index 686d043987..af65cf2895 100644 --- a/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/mixnet_scraper/mod.rs @@ -4,7 +4,7 @@ use std::time::Duration; pub mod helpers; use anyhow::Result; use helpers::{scrape_and_store_description, scrape_and_store_packet_stats}; -use sqlx::SqlitePool; +use crate::db::DbPool; use tracing::{debug, error, instrument, warn}; use crate::db::models::ScraperNodeInfo; @@ -19,13 +19,13 @@ static TASK_COUNTER: AtomicUsize = AtomicUsize::new(0); static TASK_ID_COUNTER: AtomicUsize = AtomicUsize::new(0); pub struct Scraper { - pool: SqlitePool, + pool: DbPool, description_queue: Arc>>, packet_queue: Arc>>, } impl Scraper { - pub fn new(pool: SqlitePool) -> Self { + pub fn new(pool: DbPool) -> Self { Self { pool, description_queue: Arc::new(Mutex::new(Vec::new())), @@ -71,7 +71,7 @@ impl Scraper { #[instrument(level = "info", name = "description_scraper", skip_all)] async fn run_description_scraper( - pool: &SqlitePool, + pool: &DbPool, queue: Arc>>, ) -> Result<()> { let nodes = get_nodes_for_scraping(pool).await?; @@ -88,7 +88,7 @@ impl Scraper { #[instrument(level = "info", name = "packet_scraper", skip_all)] async fn run_packet_scraper( - pool: &SqlitePool, + pool: &DbPool, queue: Arc>>, ) -> Result<()> { let nodes = get_nodes_for_scraping(pool).await?; @@ -104,7 +104,7 @@ impl Scraper { Ok(()) } - async fn process_description_queue(pool: &SqlitePool, queue: Arc>>) { + async fn process_description_queue(pool: &DbPool, queue: Arc>>) { loop { let running_tasks = TASK_COUNTER.load(Ordering::Relaxed); @@ -149,7 +149,7 @@ impl Scraper { } } - async fn process_packet_queue(pool: &SqlitePool, queue: Arc>>) { + async fn process_packet_queue(pool: &DbPool, queue: Arc>>) { loop { let running_tasks = TASK_COUNTER.load(Ordering::Relaxed); diff --git a/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs b/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs index 0711299088..844d7afd41 100644 --- a/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/monitor/mod.rs @@ -495,15 +495,31 @@ impl Monitor { async fn historical_count(pool: &DbPool) -> anyhow::Result<(usize, usize)> { let mut conn = pool.acquire().await?; + #[cfg(feature = "sqlite")] let all_historical_gateways = sqlx::query_scalar!(r#"SELECT count(id) FROM gateways"#) .fetch_one(&mut *conn) .await? .cast_checked()?; + #[cfg(feature = "pg")] + let all_historical_gateways = sqlx::query_scalar!(r#"SELECT count(id) FROM gateways"#) + .fetch_one(&mut *conn) + .await? + .unwrap_or(0) + .cast_checked()?; + + #[cfg(feature = "sqlite")] let all_historical_mixnodes = sqlx::query_scalar!(r#"SELECT count(id) FROM mixnodes"#) .fetch_one(&mut *conn) .await? .cast_checked()?; + #[cfg(feature = "pg")] + let all_historical_mixnodes = sqlx::query_scalar!(r#"SELECT count(id) FROM mixnodes"#) + .fetch_one(&mut *conn) + .await? + .unwrap_or(0) + .cast_checked()?; + Ok((all_historical_gateways, all_historical_mixnodes)) } diff --git a/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs b/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs index e36dc548f8..5d5b8f12bf 100644 --- a/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs +++ b/nym-node-status-api/nym-node-status-api/src/testruns/queue.rs @@ -1,13 +1,12 @@ use crate::db::models::{GatewayInfoDto, TestRunDto, TestRunStatus}; +use crate::db::DbConnection; use crate::testruns::models::TestRun; use crate::utils::now_utc; use anyhow::anyhow; use futures_util::TryStreamExt; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; pub(crate) async fn try_queue_testrun( - conn: &mut PoolConnection, + conn: &mut DbConnection, identity_key: String, ip_address: String, ) -> anyhow::Result { @@ -88,7 +87,7 @@ pub(crate) async fn try_queue_testrun( let log = format!("Test for {identity_key} requested at {timestamp_pretty} UTC\n\n"); let id = sqlx::query!( - "INSERT INTO testruns (gateway_id, status, ip_address, created_utc, log) VALUES (?, ?, ?, ?, ?)", + "INSERT INTO testruns (gateway_id, status, ip_address, created_utc, log) VALUES ($1, $2, $3, $4, $5)", gateway_id, status, ip_address,