From c5ae5adc6a74f30f15b13e8964e34e666e4db76b Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 16:47:45 +0900 Subject: [PATCH 1/9] common fallback test --- .../stats/src/charts/counters/total_blocks.rs | 39 +++---------------- stats/stats/src/tests/simple_test.rs | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/stats/stats/src/charts/counters/total_blocks.rs b/stats/stats/src/charts/counters/total_blocks.rs index 4bca4811b..29ac09b49 100644 --- a/stats/stats/src/charts/counters/total_blocks.rs +++ b/stats/stats/src/charts/counters/total_blocks.rs @@ -103,14 +103,15 @@ mod tests { use crate::{ data_source::{types::BlockscoutMigrations, DataSource, UpdateContext, UpdateParameters}, tests::{ - init_db::init_marked_db_all, mock_blockscout::fill_mock_blockscout_data, - simple_test::get_counter, + init_db::init_marked_db_all, + mock_blockscout::fill_mock_blockscout_data, + simple_test::{get_counter, test_counter_fallback}, }, }; use chrono::NaiveDate; use entity::chart_data; - use pretty_assertions::{assert_eq, assert_ne}; - use sea_orm::{DatabaseConnection, DbBackend, EntityTrait, Set, Statement}; + use pretty_assertions::assert_eq; + use sea_orm::{DatabaseConnection, EntityTrait, Set}; use std::str::FromStr; #[tokio::test] @@ -217,34 +218,6 @@ mod tests { #[tokio::test] #[ignore = "needs database to run"] async fn total_blocks_fallback() { - let _ = tracing_subscriber::fmt::try_init(); - let (db, blockscout) = init_marked_db_all("total_blocks_fallback").await; - let current_time = chrono::DateTime::from_str("2023-03-01T12:00:00Z").unwrap(); - let current_date = current_time.date_naive(); - - TotalBlocks::init_recursively(&db.connection, ¤t_time) - .await - .unwrap(); - - fill_mock_blockscout_data(&blockscout.connection, current_date).await; - - // need to analyze or vacuum for `reltuples` to be updated. - // source: https://www.postgresql.org/docs/9.3/planner-stats.html - let _ = blockscout - .connection - .execute(Statement::from_string(DbBackend::Postgres, "ANALYZE;")) - .await - .unwrap(); - - let parameters = UpdateParameters { - db: &db, - blockscout: &blockscout, - blockscout_applied_migrations: BlockscoutMigrations::latest(), - update_time_override: Some(current_time), - force_full: false, - }; - let cx: UpdateContext<'_> = UpdateContext::from_params_now_or_override(parameters.clone()); - let data = get_counter::(&cx).await; - assert_ne!("0", data.value); + test_counter_fallback::("total_blocks_fallback").await; } } diff --git a/stats/stats/src/tests/simple_test.rs b/stats/stats/src/tests/simple_test.rs index 0f7af1ece..318abe22f 100644 --- a/stats/stats/src/tests/simple_test.rs +++ b/stats/stats/src/tests/simple_test.rs @@ -16,6 +16,7 @@ use crate::{ use blockscout_service_launcher::test_database::TestDbGuard; use chrono::{DateTime, NaiveDateTime, Utc}; use pretty_assertions::assert_eq; +use sea_orm::{ConnectionTrait, DbBackend, Statement}; use stats_proto::blockscout::stats::v1::Point; use std::{fmt::Debug, str::FromStr}; @@ -330,6 +331,44 @@ async fn simple_test_counter_inner( assert_eq!(expected, get_counter::(&cx).await.value); } +/// Test that the counter returns non-zero fallback value when both +/// - Blockscout data is populated +/// - Update is not called on the counter +pub async fn test_counter_fallback(test_name: &str) +where + C: DataSource + ChartProperties + QuerySerialized>, +{ + let _ = tracing_subscriber::fmt::try_init(); + let (db, blockscout) = init_marked_db_all(test_name).await; + let current_time = chrono::DateTime::from_str("2023-03-01T12:00:00Z").unwrap(); + let current_date = current_time.date_naive(); + + C::init_recursively(&db.connection, ¤t_time) + .await + .unwrap(); + + fill_mock_blockscout_data(&blockscout.connection, current_date).await; + + // need to analyze or vacuum for `reltuples` to be updated. + // source: https://www.postgresql.org/docs/9.3/planner-stats.html + let _ = blockscout + .connection + .execute(Statement::from_string(DbBackend::Postgres, "ANALYZE;")) + .await + .unwrap(); + + let parameters = UpdateParameters { + db: &db, + blockscout: &blockscout, + blockscout_applied_migrations: BlockscoutMigrations::latest(), + update_time_override: Some(current_time), + force_full: false, + }; + let cx: UpdateContext<'_> = UpdateContext::from_params_now_or_override(parameters.clone()); + let data = get_counter::(&cx).await; + assert_ne!("0", data.value); +} + pub async fn prepare_chart_test( test_name: &str, init_time: Option, From ad71270690c299e8414cbc125f530cae7170620f Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 16:53:52 +0900 Subject: [PATCH 2/9] add fallback for total txns --- .../stats-server/tests/it/indexing_status.rs | 12 +++-- stats/stats/src/charts/counters/total_txns.rs | 44 ++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/stats/stats-server/tests/it/indexing_status.rs b/stats/stats-server/tests/it/indexing_status.rs index ba6be3887..628b45b62 100644 --- a/stats/stats-server/tests/it/indexing_status.rs +++ b/stats/stats-server/tests/it/indexing_status.rs @@ -2,6 +2,7 @@ use blockscout_service_launcher::{ launcher::ConfigSettings, test_server::{get_test_server_settings, init_server, send_get_request}, }; +use itertools::Itertools; use pretty_assertions::assert_eq; use stats::tests::{init_db::init_db_all, mock_blockscout::mock_blockscout_api}; @@ -85,8 +86,11 @@ async fn test_not_indexed_ok() { } } - let mut counters: Counters = send_get_request(&base, "/api/v1/counters").await; - // totalBlocks has fallback with estimate, so it should always return - assert_eq!(counters.counters.pop().unwrap().id, "totalBlocks"); - assert_eq!(counters.counters, vec![]) + let counters: Counters = send_get_request(&base, "/api/v1/counters").await; + // returns onle counters with fallback query logic, + // so they are returned even without calling an update + assert_eq!( + counters.counters.into_iter().map(|c| c.id).collect_vec(), + vec!["totalBlocks", "totalTxns"] + ) } diff --git a/stats/stats/src/charts/counters/total_txns.rs b/stats/stats/src/charts/counters/total_txns.rs index 33bcc40a0..ee2be324c 100644 --- a/stats/stats/src/charts/counters/total_txns.rs +++ b/stats/stats/src/charts/counters/total_txns.rs @@ -1,14 +1,19 @@ use crate::{ + charts::db_interaction::read::query_estimated_table_rows, data_source::kinds::{ data_manipulation::{map::MapToString, sum_point::Sum}, - local_db::DirectPointLocalDbChartSource, + local_db::{parameters::ValueEstimation, DirectPointLocalDbChartSourceWithEstimate}, }, lines::NewTxnsInt, - ChartProperties, MissingDatePolicy, Named, + types::timespans::DateValue, + utils::MarkedDbConnection, + ChartError, ChartProperties, MissingDatePolicy, Named, }; -use chrono::NaiveDate; +use blockscout_db::entity::transactions; +use chrono::{NaiveDate, Utc}; use entity::sea_orm_active_enums::ChartType; +use sea_orm::EntityName; pub struct Properties; @@ -29,16 +34,45 @@ impl ChartProperties for Properties { } } -pub type TotalTxns = DirectPointLocalDbChartSource>, Properties>; +pub struct TotalTxnsEstimation; + +impl ValueEstimation for TotalTxnsEstimation { + async fn estimate(blockscout: &MarkedDbConnection) -> Result, ChartError> { + let now = Utc::now(); + let value = query_estimated_table_rows( + blockscout.connection.as_ref(), + transactions::Entity.table_name(), + ) + .await + .map_err(ChartError::BlockscoutDB)? + .unwrap_or(0); + Ok(DateValue { + timespan: now.date_naive(), + value: value.to_string(), + }) + } +} + +pub type TotalTxns = DirectPointLocalDbChartSourceWithEstimate< + MapToString>, + TotalTxnsEstimation, + Properties, +>; #[cfg(test)] mod tests { use super::*; - use crate::tests::simple_test::simple_test_counter; + use crate::tests::simple_test::{simple_test_counter, test_counter_fallback}; #[tokio::test] #[ignore = "needs database to run"] async fn update_total_txns() { simple_test_counter::("update_total_txns", "47", None).await; } + + #[tokio::test] + #[ignore = "needs database to run"] + async fn total_txns_fallback() { + test_counter_fallback::("total_txns_fallback").await; + } } From 8b5b918b331583a5b3e0715d11e7f5a76e849315 Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 16:56:34 +0900 Subject: [PATCH 3/9] stop filtering by timestamp to improve new txns query performance --- stats/stats/src/charts/lines/new_txns.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stats/stats/src/charts/lines/new_txns.rs b/stats/stats/src/charts/lines/new_txns.rs index 2f3b3fd26..5526050cf 100644 --- a/stats/stats/src/charts/lines/new_txns.rs +++ b/stats/stats/src/charts/lines/new_txns.rs @@ -35,6 +35,9 @@ impl StatementFromRange for NewTxnsStatement { range: Option>>, completed_migrations: &BlockscoutMigrations, ) -> Statement { + // do not filter by `!= to_timestamp(0)` because + // 1. it allows to use index `transactions_block_consensus_index` + // 2. there is no reason not to count genesis transactions if completed_migrations.denormalization { sql_with_range_filter_opt!( DbBackend::Postgres, @@ -44,7 +47,6 @@ impl StatementFromRange for NewTxnsStatement { COUNT(*)::TEXT as value FROM transactions t WHERE - t.block_timestamp != to_timestamp(0) AND t.block_consensus = true {filter} GROUP BY date; "#, @@ -62,7 +64,6 @@ impl StatementFromRange for NewTxnsStatement { FROM transactions t JOIN blocks b ON t.block_hash = b.hash WHERE - b.timestamp != to_timestamp(0) AND b.consensus = true {filter} GROUP BY date; "#, From 19a8a5db8cbb65ade3b8443d101db490b1ea0194 Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 19:01:44 +0900 Subject: [PATCH 4/9] make total_txns an independent sql using query from backend --- stats/stats/src/charts/counters/total_txns.rs | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/stats/stats/src/charts/counters/total_txns.rs b/stats/stats/src/charts/counters/total_txns.rs index ee2be324c..cd3f9dc1f 100644 --- a/stats/stats/src/charts/counters/total_txns.rs +++ b/stats/stats/src/charts/counters/total_txns.rs @@ -1,19 +1,48 @@ use crate::{ charts::db_interaction::read::query_estimated_table_rows, - data_source::kinds::{ - data_manipulation::{map::MapToString, sum_point::Sum}, - local_db::{parameters::ValueEstimation, DirectPointLocalDbChartSourceWithEstimate}, + data_source::{ + kinds::{ + local_db::{parameters::ValueEstimation, DirectPointLocalDbChartSourceWithEstimate}, + remote_db::{RemoteDatabaseSource, RemoteQueryBehaviour}, + }, + UpdateContext, }, - lines::NewTxnsInt, + range::UniversalRange, types::timespans::DateValue, utils::MarkedDbConnection, ChartError, ChartProperties, MissingDatePolicy, Named, }; use blockscout_db::entity::transactions; -use chrono::{NaiveDate, Utc}; +use chrono::{DateTime, NaiveDate, Utc}; use entity::sea_orm_active_enums::ChartType; -use sea_orm::EntityName; +use sea_orm::{EntityName, EntityTrait, PaginatorTrait, QuerySelect}; + +pub struct TotalTxnsQueryBehaviour; + +impl RemoteQueryBehaviour for TotalTxnsQueryBehaviour { + type Output = DateValue; + + async fn query_data( + cx: &UpdateContext<'_>, + _range: UniversalRange>, + ) -> Result { + let now = cx.time; + let value = transactions::Entity::find() + .select_only() + .count(cx.blockscout.connection.as_ref()) + .await + .map_err(ChartError::BlockscoutDB)?; + + let data = DateValue:: { + timespan: now.date_naive(), + value: value.to_string(), + }; + Ok(data) + } +} + +pub type TotalTxnsRemote = RemoteDatabaseSource; pub struct Properties; @@ -53,11 +82,15 @@ impl ValueEstimation for TotalTxnsEstimation { } } -pub type TotalTxns = DirectPointLocalDbChartSourceWithEstimate< - MapToString>, - TotalTxnsEstimation, - Properties, ->; +// We will need it to update on not fully indexed data soon, therefore this counter is +// separated from `NewTxns`. +// +// Separate query not reliant on previous computation helps this counter to work in such +// environments. +// +// todo: make it dependant again if #845 is resolved +pub type TotalTxns = + DirectPointLocalDbChartSourceWithEstimate; #[cfg(test)] mod tests { @@ -67,7 +100,7 @@ mod tests { #[tokio::test] #[ignore = "needs database to run"] async fn update_total_txns() { - simple_test_counter::("update_total_txns", "47", None).await; + simple_test_counter::("update_total_txns", "48", None).await; } #[tokio::test] From cbc34af6a24ae725cda10b639885485efb332076 Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 19:04:06 +0900 Subject: [PATCH 5/9] separate total_txns in its own group --- stats/config/update_groups.json | 1 + stats/stats-server/src/runtime_setup.rs | 1 + stats/stats/src/update_groups.rs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/stats/config/update_groups.json b/stats/config/update_groups.json index c07dab967..8b08037b8 100644 --- a/stats/config/update_groups.json +++ b/stats/config/update_groups.json @@ -6,6 +6,7 @@ "total_addresses_group": "0 0 */3 * * * *", "total_blocks_group": "0 0 */2 * * * *", "total_tokens_group": "0 0 18 * * * *", + "total_txns_group": "0 5 */2 * * * *", "yesterday_txns_group": "0 8 0 * * * *", "active_recurring_accounts_daily_recurrence_60_days_group": "0 0 2 * * * *", "active_recurring_accounts_daily_recurrence_90_days_group": "0 20 2 * * * *", diff --git a/stats/stats-server/src/runtime_setup.rs b/stats/stats-server/src/runtime_setup.rs index d9d07b979..4277b27d1 100644 --- a/stats/stats-server/src/runtime_setup.rs +++ b/stats/stats-server/src/runtime_setup.rs @@ -260,6 +260,7 @@ impl RuntimeSetup { Arc::new(TotalAddressesGroup), Arc::new(TotalBlocksGroup), Arc::new(TotalTokensGroup), + Arc::new(TotalTxnsGroup), Arc::new(YesterdayTxnsGroup), Arc::new(ActiveRecurringAccountsDailyRecurrence60DaysGroup), Arc::new(ActiveRecurringAccountsMonthlyRecurrence60DaysGroup), diff --git a/stats/stats/src/update_groups.rs b/stats/stats/src/update_groups.rs index f18792516..c74c8ceff 100644 --- a/stats/stats/src/update_groups.rs +++ b/stats/stats/src/update_groups.rs @@ -23,6 +23,7 @@ singleton_groups!( TotalAddresses, TotalBlocks, TotalTokens, + TotalTxns, YesterdayTxns, // Each of the `ActiveRecurringAccounts*` charts includes quite heavy SQL query, // thus it's better to have granular control on update times. @@ -167,7 +168,6 @@ construct_update_group!(NewTxnsGroup { TxnsGrowthWeekly, TxnsGrowthMonthly, TxnsGrowthYearly, - TotalTxns, ], }); From 88e63d5c28af55525a5f3ca06023928671415647 Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 20:50:03 +0900 Subject: [PATCH 6/9] truncate negative vals for total_txns --- stats/stats/src/charts/counters/total_txns.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/stats/stats/src/charts/counters/total_txns.rs b/stats/stats/src/charts/counters/total_txns.rs index cd3f9dc1f..94978b184 100644 --- a/stats/stats/src/charts/counters/total_txns.rs +++ b/stats/stats/src/charts/counters/total_txns.rs @@ -74,6 +74,7 @@ impl ValueEstimation for TotalTxnsEstimation { ) .await .map_err(ChartError::BlockscoutDB)? + .map(|n| u64::try_from(n).unwrap_or(0)) .unwrap_or(0); Ok(DateValue { timespan: now.date_naive(), From 864c804a0f8d993df27ce277f389b49f417b39a9 Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Mon, 9 Dec 2024 20:56:13 +0900 Subject: [PATCH 7/9] adapt total_addresses impl to blockscout --- stats/config/update_groups.json | 2 +- .../stats-server/tests/it/indexing_status.rs | 2 +- .../src/charts/counters/total_addresses.rs | 49 ++++++++++++++++--- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/stats/config/update_groups.json b/stats/config/update_groups.json index 8b08037b8..037f4740b 100644 --- a/stats/config/update_groups.json +++ b/stats/config/update_groups.json @@ -3,7 +3,7 @@ "active_accounts_group": "0 0 4 * * * *", "average_block_time_group": "0 */10 * * * * *", "completed_txns_group": "0 5 */3 * * * *", - "total_addresses_group": "0 0 */3 * * * *", + "total_addresses_group": "0 0,30 * * * * *", "total_blocks_group": "0 0 */2 * * * *", "total_tokens_group": "0 0 18 * * * *", "total_txns_group": "0 5 */2 * * * *", diff --git a/stats/stats-server/tests/it/indexing_status.rs b/stats/stats-server/tests/it/indexing_status.rs index 628b45b62..1a108bb8c 100644 --- a/stats/stats-server/tests/it/indexing_status.rs +++ b/stats/stats-server/tests/it/indexing_status.rs @@ -91,6 +91,6 @@ async fn test_not_indexed_ok() { // so they are returned even without calling an update assert_eq!( counters.counters.into_iter().map(|c| c.id).collect_vec(), - vec!["totalBlocks", "totalTxns"] + vec!["totalAddresses", "totalBlocks", "totalTxns"] ) } diff --git a/stats/stats/src/charts/counters/total_addresses.rs b/stats/stats/src/charts/counters/total_addresses.rs index 00513c1a3..3a18a9e9e 100644 --- a/stats/stats/src/charts/counters/total_addresses.rs +++ b/stats/stats/src/charts/counters/total_addresses.rs @@ -1,16 +1,20 @@ use crate::{ + charts::db_interaction::read::query_estimated_table_rows, data_source::{ kinds::{ - local_db::DirectPointLocalDbChartSource, + local_db::{parameters::ValueEstimation, DirectPointLocalDbChartSourceWithEstimate}, remote_db::{PullOne, RemoteDatabaseSource, StatementForOne}, }, types::BlockscoutMigrations, }, - ChartProperties, MissingDatePolicy, Named, + types::timespans::DateValue, + utils::MarkedDbConnection, + ChartError, ChartProperties, MissingDatePolicy, Named, }; -use chrono::NaiveDate; +use blockscout_db::entity::addresses; +use chrono::{NaiveDate, Utc}; use entity::sea_orm_active_enums::ChartType; -use sea_orm::{DbBackend, Statement}; +use sea_orm::{DbBackend, EntityName, Statement}; pub struct TotalAddressesStatement; @@ -57,16 +61,49 @@ impl ChartProperties for Properties { } } -pub type TotalAddresses = DirectPointLocalDbChartSource; +pub struct TotalAddressesEstimation; + +impl ValueEstimation for TotalAddressesEstimation { + async fn estimate(blockscout: &MarkedDbConnection) -> Result, ChartError> { + let now = Utc::now(); + let value = query_estimated_table_rows( + blockscout.connection.as_ref(), + addresses::Entity.table_name(), + ) + .await + .map_err(ChartError::BlockscoutDB)? + .map(|n| u64::try_from(n).unwrap_or(0)) + .unwrap_or(0); + Ok(DateValue { + timespan: now.date_naive(), + value: value.to_string(), + }) + } +} + +pub type TotalAddresses = DirectPointLocalDbChartSourceWithEstimate< + TotalAddressesRemote, + TotalAddressesEstimation, + Properties, +>; #[cfg(test)] mod tests { use super::*; - use crate::tests::simple_test::simple_test_counter; + use crate::{ + counters::TotalTxns, + tests::simple_test::{simple_test_counter, test_counter_fallback}, + }; #[tokio::test] #[ignore = "needs database to run"] async fn update_total_addresses() { simple_test_counter::("update_total_addresses", "33", None).await; } + + #[tokio::test] + #[ignore = "needs database to run"] + async fn total_addresses_fallback() { + test_counter_fallback::("total_addresses_fallback").await; + } } From b4678914ebbc57ec4815300a73f9eeca2f77e4fc Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Wed, 11 Dec 2024 18:19:16 +0900 Subject: [PATCH 8/9] more precise timestamp retrieval for total txns --- .../src/charts/counters/total_addresses.rs | 2 ++ .../stats/src/charts/counters/total_blocks.rs | 2 ++ stats/stats/src/charts/counters/total_txns.rs | 26 ++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/stats/stats/src/charts/counters/total_addresses.rs b/stats/stats/src/charts/counters/total_addresses.rs index 3a18a9e9e..7938af05d 100644 --- a/stats/stats/src/charts/counters/total_addresses.rs +++ b/stats/stats/src/charts/counters/total_addresses.rs @@ -65,6 +65,8 @@ pub struct TotalAddressesEstimation; impl ValueEstimation for TotalAddressesEstimation { async fn estimate(blockscout: &MarkedDbConnection) -> Result, ChartError> { + // `now()` is more relevant when taken right before the query rather than + // `cx.time` measured a bit earlier. let now = Utc::now(); let value = query_estimated_table_rows( blockscout.connection.as_ref(), diff --git a/stats/stats/src/charts/counters/total_blocks.rs b/stats/stats/src/charts/counters/total_blocks.rs index 29ac09b49..c98c7cddf 100644 --- a/stats/stats/src/charts/counters/total_blocks.rs +++ b/stats/stats/src/charts/counters/total_blocks.rs @@ -77,6 +77,8 @@ pub struct TotalBlocksEstimation; impl ValueEstimation for TotalBlocksEstimation { async fn estimate(blockscout: &MarkedDbConnection) -> Result, ChartError> { + // `now()` is more relevant when taken right before the query rather than + // `cx.time` measured a bit earlier. let now = Utc::now(); let value = query_estimated_table_rows(blockscout.connection.as_ref(), blocks::Entity.table_name()) diff --git a/stats/stats/src/charts/counters/total_txns.rs b/stats/stats/src/charts/counters/total_txns.rs index 94978b184..f67776553 100644 --- a/stats/stats/src/charts/counters/total_txns.rs +++ b/stats/stats/src/charts/counters/total_txns.rs @@ -13,10 +13,12 @@ use crate::{ ChartError, ChartProperties, MissingDatePolicy, Named, }; -use blockscout_db::entity::transactions; -use chrono::{DateTime, NaiveDate, Utc}; +use blockscout_db::entity::{blocks, transactions}; +use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use entity::sea_orm_active_enums::ChartType; -use sea_orm::{EntityName, EntityTrait, PaginatorTrait, QuerySelect}; +use sea_orm::{ + prelude::Expr, ColumnTrait, EntityName, EntityTrait, PaginatorTrait, QueryFilter, QuerySelect, +}; pub struct TotalTxnsQueryBehaviour; @@ -27,15 +29,25 @@ impl RemoteQueryBehaviour for TotalTxnsQueryBehaviour { cx: &UpdateContext<'_>, _range: UniversalRange>, ) -> Result { - let now = cx.time; + let blockscout = cx.blockscout.connection.as_ref(); + let timespan: NaiveDateTime = blocks::Entity::find() + .select_only() + .column_as(Expr::col(blocks::Column::Timestamp).max(), "timestamp") + .filter(blocks::Column::Consensus.eq(true)) + .into_tuple() + .one(blockscout) + .await + .map_err(ChartError::BlockscoutDB)? + .ok_or_else(|| ChartError::Internal("no block timestamps in database".into()))?; + let value = transactions::Entity::find() .select_only() - .count(cx.blockscout.connection.as_ref()) + .count(blockscout) .await .map_err(ChartError::BlockscoutDB)?; let data = DateValue:: { - timespan: now.date_naive(), + timespan: timespan.date(), value: value.to_string(), }; Ok(data) @@ -67,6 +79,8 @@ pub struct TotalTxnsEstimation; impl ValueEstimation for TotalTxnsEstimation { async fn estimate(blockscout: &MarkedDbConnection) -> Result, ChartError> { + // `now()` is more relevant when taken right before the query rather than + // `cx.time` measured a bit earlier. let now = Utc::now(); let value = query_estimated_table_rows( blockscout.connection.as_ref(), From 2fe3f8ca17391995b5d17cdf133a10dbc7eb7b6a Mon Sep 17 00:00:00 2001 From: Kirill Ivanov Date: Wed, 11 Dec 2024 18:20:17 +0900 Subject: [PATCH 9/9] fix test --- stats/stats/src/charts/counters/total_addresses.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stats/stats/src/charts/counters/total_addresses.rs b/stats/stats/src/charts/counters/total_addresses.rs index 7938af05d..713ce9c39 100644 --- a/stats/stats/src/charts/counters/total_addresses.rs +++ b/stats/stats/src/charts/counters/total_addresses.rs @@ -92,10 +92,7 @@ pub type TotalAddresses = DirectPointLocalDbChartSourceWithEstimate< #[cfg(test)] mod tests { use super::*; - use crate::{ - counters::TotalTxns, - tests::simple_test::{simple_test_counter, test_counter_fallback}, - }; + use crate::tests::simple_test::{simple_test_counter, test_counter_fallback}; #[tokio::test] #[ignore = "needs database to run"] @@ -106,6 +103,6 @@ mod tests { #[tokio::test] #[ignore = "needs database to run"] async fn total_addresses_fallback() { - test_counter_fallback::("total_addresses_fallback").await; + test_counter_fallback::("total_addresses_fallback").await; } }