Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stats): The Migration of The Backend charts: Total Blocks and Dynamic query dispatch #1137

Merged
merged 41 commits into from
Dec 11, 2024

Conversation

bragov4ik
Copy link
Contributor

@bragov4ik bragov4ik commented Dec 3, 2024

#1080

It is a sequel to #1120 and the third installment in the Migrate Backend Charts franchise.

In this standalone sequel, we introduce reimagination of TotalBlocks counter and dynamic dispatch for chart query behaviour. TotalBlocks counter uses a custom logic with fallback to postgres catalog for preliminary block number estimation (to display when SQL query is not yet calculated), so we can't keep retrieving the data directly from DB. We need to allow dynamic query logic that is configurable for each chart.

While adding usage of dynamic logic for chart query, regular date range was replaced by universal range, because chart requests can include or omit any of the bounds.

Total blocks:

Summary by CodeRabbit

  • New Features

    • Introduced a new module for querying chart data with a unified output format.
    • Added support for estimating values in queries.
    • Enhanced date range handling with the introduction of UniversalRange.
  • Bug Fixes

    • Updated error handling across multiple components, replacing UpdateError with ChartError.
  • Improvements

    • Streamlined database connection handling.
    • Enhanced type safety and clarity in date handling.
    • Refined error management across various data source implementations.
    • Improved handling of cumulative data and batch updates.
    • Expanded functionality in the DataSource trait and its implementations.
  • Tests

    • Updated tests to reflect changes in error handling and data querying logic.

@bragov4ik bragov4ik changed the title feat(stats): Backend charts migration & dynamic query dispatch feat(stats): The Migration of The Backend charts: Total Blocks and Dynamic query dispatch Dec 4, 2024
@bragov4ik bragov4ik changed the base branch from bragov4ik/stats-migrate-backend-charts-3 to main December 4, 2024 10:35
@bragov4ik bragov4ik changed the base branch from main to bragov4ik/stats-migrate-backend-charts-2 December 4, 2024 10:41
@bragov4ik bragov4ik force-pushed the bragov4ik/stats-dynamic-query-dispatch branch from 92ae8e9 to 1f7be14 Compare December 4, 2024 11:05
@bragov4ik
Copy link
Contributor Author

bragov4ik commented Dec 4, 2024

The one thing I didn't port from blockscout - lazy update. In blockscout the counter is not updated if nobody requests the counter value. Need to check how much it is needed.

@bragov4ik bragov4ik changed the base branch from bragov4ik/stats-migrate-backend-charts-2 to bragov4ik/stats-fix-counters-layout-not-applied December 5, 2024 16:50
@bragov4ik bragov4ik changed the base branch from bragov4ik/stats-fix-counters-layout-not-applied to bragov4ik/stats-migrate-backend-charts-3 December 5, 2024 16:53
@bragov4ik bragov4ik force-pushed the bragov4ik/stats-dynamic-query-dispatch branch 2 times, most recently from aa5ca57 to 1ab53b3 Compare December 6, 2024 06:18
@bragov4ik bragov4ik changed the base branch from bragov4ik/stats-migrate-backend-charts-3 to main December 6, 2024 12:23
@bragov4ik bragov4ik changed the base branch from main to bragov4ik/stats-fix-counters-layout-not-applied December 9, 2024 10:58
@bragov4ik bragov4ik force-pushed the bragov4ik/stats-dynamic-query-dispatch branch from d9f20c6 to 5375d8e Compare December 9, 2024 10:59
Base automatically changed from bragov4ik/stats-fix-counters-layout-not-applied to main December 9, 2024 12:10
@bragov4ik bragov4ik force-pushed the bragov4ik/stats-dynamic-query-dispatch branch from 5375d8e to bdd688c Compare December 9, 2024 12:13
@bragov4ik bragov4ik marked this pull request as draft December 9, 2024 12:19
@bragov4ik bragov4ik marked this pull request as ready for review December 9, 2024 12:19
@sevenzing
Copy link
Contributor

@coderabbitai review

Copy link

coderabbitai bot commented Dec 10, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

coderabbitai bot commented Dec 10, 2024

Walkthrough

The recent changes encompass a broad range of modifications across multiple files in the Rust project, primarily focusing on error handling, type adjustments, and data querying enhancements. A significant aspect of these updates is the transition from using UpdateError to ChartError, which reflects a refined error management strategy throughout the codebase. Additionally, many methods have updated their parameter types from Option<Range<DateTimeUtc>> to UniversalRange<DateTime<Utc>>, improving the handling of date ranges in queries.

New dependencies have been introduced, such as trait-variant and stats-proto, enhancing the project's functionality. The ReadService and UpdateService structs have undergone structural changes, including the replacement of DatabaseConnection with MarkedDbConnection. Furthermore, several functions related to data processing, such as query_data and update_values, have been updated to accommodate these new types and improve error handling. The introduction of new modules and traits, such as QuerySerialized, reflects an ongoing effort to modularize and streamline data querying processes.

Poem

🐰 In the code where rabbits play,
New types and errors lead the way.
With ChartError now in sight,
Our data queries take to flight!
From ranges wide to structures neat,
Hopping forward, we can't be beat! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Outside diff range and nitpick comments (30)
stats/stats/src/charts/lines/average_gas_price.rs (1)

142-156: Document the purpose and behavior of StripExt

The introduction of StripExt wrapper types affects multiple time-based aggregations. Please add documentation explaining:

  • The purpose of StripExt
  • How it transforms or filters the data
  • Why it's necessary for each time resolution

Example documentation format:

/// StripExt wraps chart sources to [explain behavior]
/// 
/// # Example
/// ```
/// // Add usage example
/// ```
stats/stats/src/charts/lines/txns_growth.rs (2)

48-48: Add documentation for the StripExt wrapper

The introduction of StripExt wrapper types needs documentation to explain:

  • The purpose of stripping
  • The impact on data processing
  • When to use stripped vs. non-stripped versions

Consider adding doc comments like:

/// Wrapped version of TxnsGrowth that applies stripping functionality.
/// Stripping refers to... [explain the purpose]
type TxnsGrowthS = StripExt<TxnsGrowth>;

/// Monthly transactions growth with stripping functionality applied.
/// Used in yearly resolution calculations.
type TxnsGrowthMonthlyS = StripExt<TxnsGrowthMonthly>;

Also applies to: 59-59


Line range hint 67-124: Consider adding tests for StripExt functionality

While the existing tests cover the basic functionality across different time resolutions, consider adding specific test cases to verify:

  • The stripping behavior
  • Edge cases with the stripped data
  • Performance comparison between stripped and non-stripped versions
stats/stats/src/charts/lines/new_contracts.rs (1)

Line range hint 35-119: Consider adding index hints for query optimization

The SQL queries perform complex operations including UNION and DISTINCT ON across multiple tables. While functionally correct, consider adding index hints to optimize query performance, especially for:

  • block_timestamp and created_contract_address_hash in transactions table
  • timestamp and created_contract_address_hash in blocks and internal_transactions tables

Would you like me to help generate the appropriate index definitions?

stats/stats/src/charts/lines/new_block_rewards.rs (2)

Line range hint 36-56: Consider adding an index for performance optimization.

The SQL query joins block_rewards and blocks tables on block_hash and filters on timestamp and consensus. Consider adding a composite index to optimize this query pattern.

CREATE INDEX idx_blocks_timestamp_consensus ON blocks(timestamp, consensus) WHERE consensus = true;

Line range hint 140-166: Consider adding edge case tests.

While the current test coverage is good, consider adding test cases for:

  • Empty time ranges
  • Ranges with no data
  • Boundary conditions around month transitions
// Example test case
#[tokio::test]
#[ignore = "needs database to run"]
async fn update_new_block_rewards_empty_range() {
    let (db, blockscout) = init_marked_db_all("update_new_block_rewards_empty").await;
    let empty_range = UniversalRange::new(
        DateTime::from_str("2024-01-01T00:00:00Z").unwrap(),
        DateTime::from_str("2024-01-01T00:00:00Z").unwrap(),
    );
    // ... test implementation
}
stats/stats/src/charts/lines/new_native_coin_transfers.rs (1)

81-88: LGTM: Enhanced type safety with QueryAllBlockTimestampRange

The addition of QueryAllBlockTimestampRange as a generic parameter improves type safety and enables dynamic query dispatch. Consider documenting the type parameters in a comment for better maintainability.

Consider adding a type-level documentation comment explaining the role of each generic parameter, especially QueryAllBlockTimestampRange, to help future maintainers understand the type's structure and purpose.

stats/stats/src/data_source/kinds/remote_db/query/each.rs (1)

Line range hint 79-85: Enhance error handling in resolution_from_range function

When res_verify does not equal res, the function logs a warning and continues execution. Consider handling this discrepancy more robustly, such as returning an error or adjusting the logic, to prevent potential inconsistencies in timespan resolution.

stats/stats/src/data_source/kinds/local_db/parameters/query.rs (1)

109-127: Add logging when estimation fallback is used

In QueryLastWithEstimationFallback::query_data, when the primary data retrieval fails and estimation is used, consider adding a log message. This will help monitor how often estimations occur and assist in diagnosing data issues.

stats/stats/src/charts/counters/total_blocks.rs (1)

76-95: Define a constant for the estimation factor

Using the magic number 0.9 directly can reduce code clarity. Define a named constant to explain its purpose and enhance maintainability.

Consider applying this change:

+const ESTIMATION_FACTOR: f64 = 0.9;

impl ValueEstimation for TotalBlocksEstimation {
    async fn estimate(blockscout: &MarkedDbConnection) -> Result<DateValue<String>, ChartError> {
        let now = Utc::now();
        let value =
            query_estimated_table_rows(blockscout.connection.as_ref(), blocks::Entity.table_name())
                .await
                .map_err(ChartError::BlockscoutDB)?
                .map(|b| {
-                   let b = b as f64 * 0.9;
+                   let b = b as f64 * ESTIMATION_FACTOR;
                    b as i64
                })
                .unwrap_or(0);
        Ok(DateValue {
            timespan: now.date_naive(),
            value: value.to_string(),
        })
    }
}
stats/stats-server/src/read_service.rs (1)

223-232: Handle missing resolutions more gracefully

In the get_line_chart method, if the requested resolution is not found, an error is returned to the client. Consider providing available resolutions in the error message to guide the client.

Modify the error message to include available resolutions:

 .ok_or_else(|| {
     Status::not_found(format!(
-        "resolution '{}' for line chart '{}' was not found",
+        "Resolution '{}' for line chart '{}' was not found. Available resolutions are: {:?}",
         String::from(resolution),
         chart_name,
+        chart_entry.resolutions.keys().collect::<Vec<_>>()
     ))
 })?;
stats/stats/src/charts/types/timespans/year.rs (1)

295-317: Expand test cases for checked_add and checked_sub

While the tests cover some cases, consider adding more test cases to cover edge cases, such as zero durations and maximum possible values.

Add test cases to ensure comprehensive coverage of boundary conditions.

stats/stats/src/data_source/kinds/local_db/mod.rs (1)

58-58: Consider keeping PhantomData field private for encapsulation

The PhantomData field is now public, which exposes internal type parameters. If external access is not required, keeping it private maintains encapsulation and prevents unintended usage.

stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs (1)

1-36: Consider adding unit tests

While the implementation looks solid, it would benefit from unit tests to verify:

  1. Vector transformation behavior
  2. Single value transformation behavior
  3. Edge cases (empty vector, null values if applicable)

Would you like me to help generate unit tests for this module?

stats/stats/src/data_source/kinds/remote_db/query/one.rs (1)

48-51: Consider adding error context

While the error handling is improved with ChartError, consider adding more context to the error message for better debugging:

-            .ok_or_else(|| ChartError::Internal("query returned nothing".into()))?;
+            .ok_or_else(|| ChartError::Internal(format!("PullOne query returned no results for statement: {:?}", query)))?;
stats/stats/src/data_source/kinds/data_manipulation/map/mod.rs (1)

17-17: Document the StripExt functionality

The new strip_extension module and StripExt export would benefit from documentation explaining their purpose and usage in the context of chart data manipulation.

Also applies to: 21-21

stats/stats/src/data_source/kinds/data_manipulation/sum_point.rs (1)

59-65: Consider performance optimization for range handling

While the transition to UniversalRange is correct, using UniversalRange::full() means we're always fetching the complete dataset regardless of the input range. This could impact performance for large datasets.

Consider optimizing the implementation to respect the input range:

- let full_data =
-     DS::query_data(cx, UniversalRange::full(), dependency_data_fetch_timer).await?;
+ let data = DS::query_data(cx, _range, dependency_data_fetch_timer).await?;
tracing::debug!(points_len = full_data.len(), "calculating sum");
let zero = Value::zero();
- sum::<Resolution, Value>(&full_data, zero)
+ sum::<Resolution, Value>(&data, zero)
stats/stats/src/charts/counters/total_contracts.rs (1)

Line range hint 64-65: Consider addressing the TODO comment

The TODO comment references issue #845 regarding potential architectural changes to the dependency structure.

Would you like me to help track this TODO by creating a GitHub issue to reconsider the dependency once #845 is resolved?

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/cumulative.rs (1)

Line range hint 46-68: Consider adding unit tests for error cases

The value parsing and cumulative calculation logic looks correct, but it would be beneficial to have unit tests covering error cases, especially for value parsing failures.

Would you like me to help generate unit tests for the error scenarios?

stats/stats/src/data_source/kinds/remote_db/mod.rs (1)

Line range hint 1-17: Consider updating module documentation

While the existing documentation is good, it would be helpful to add information about the new range type and query parameters.

Consider adding:

 //! Remote database source.
 //!
 //! The main application - SQL queries from remote (=blockscout) database.
 //!
 //! ## Details
 //!
+//! Queries support universal range specifications and can be configured with
+//! points limits and date filling options.
+//!
 //! This source does not have any persistency and is only an adapter for representing
 //! a remote DB as a `DataSource`.
stats/stats/src/charts/counters/yesterday_txns.rs (1)

40-42: Consider adding error context for database failures

While the error handling is correct, consider adding more context to database errors to aid in debugging.

-            .map_err(ChartError::BlockscoutDB)?
+            .map_err(|e| ChartError::BlockscoutDB(format!("Failed to query yesterday's transactions: {}", e)))?
stats/stats/src/charts/lines/accounts_growth.rs (1)

49-50: Consider documenting the purpose of intermediate type aliases

The introduction of AccountsGrowthS and AccountsGrowthMonthlyS as intermediate type aliases could benefit from documentation explaining their specific roles in the type hierarchy.

+/// Stripped version of AccountsGrowth for use in higher resolution charts
 type AccountsGrowthS = StripExt<AccountsGrowth>;

+/// Stripped version of AccountsGrowthMonthly for use in yearly resolution
 type AccountsGrowthMonthlyS = StripExt<AccountsGrowthMonthly>;

Also applies to: 61-61

stats/stats/src/data_source/kinds/data_manipulation/delta.rs (1)

Line range hint 73-89: Consider adding debug assertions for value consistency

The cumulative data processing logic could benefit from debug assertions to verify value consistency during development, especially for the prev_value handling.

 let (prev_value, cum_data) = if start_is_bounded {
     let mut cum_data = cum_data.into_iter();
     let Some(range_start) = cum_data.next() else {
         tracing::warn!("Value before the range was not found, finishing update");
         return Ok(vec![]);
     };
+    debug_assert!(
+        !range_start.value.is_zero(),
+        "Initial cumulative value should not be zero"
+    );
     tracing::debug!(
         range_start_value = %range_start.value,
         cumulative_points_len = cum_data.len(),
         "calculating deltas from cumulative"
     );
     (range_start.value, cum_data.collect())
 } else {
     (Value::zero(), cum_data)
 };
stats/stats/src/charts/lines/contracts_growth.rs (1)

47-58: Consider documenting the StripExt transformation chain

The introduction of StripExt wrapper types creates a transformation chain from daily to yearly resolutions. While the implementation looks correct, adding documentation would help explain the purpose and behavior of these transformations.

Consider adding documentation like:

+/// Strips implementation details from ContractsGrowth for resolution transformations
 type ContractsGrowthS = StripExt<ContractsGrowth>;
stats/stats/src/data_source/kinds/data_manipulation/resolutions/last_value.rs (1)

115-117: Consider extracting the database URL to a constant or configuration

The hardcoded SQLite connection string could be moved to a constant or test configuration for better maintainability.

+const TEST_DB_URL: &str = "sqlite::memory:";
+
 let empty_db = MarkedDbConnection::in_memory(Arc::new(
-    sea_orm::Database::connect("sqlite::memory:").await.unwrap(),
+    sea_orm::Database::connect(TEST_DB_URL).await.unwrap(),
 ));
stats/stats/src/charts/lines/average_block_rewards.rs (1)

92-92: Consider documenting the purpose of StripExt wrapper

The introduction of StripExt wrapper types suggests performance optimization, but their purpose should be documented for maintainability.

Also applies to: 107-107

stats/stats/src/charts/lines/new_txns.rs (1)

Line range hint 35-76: Consider adding indexes for query optimization.

The SQL queries look correct and handle both denormalized and normalized data structures well. However, for optimal performance, ensure indexes exist on:

  • transactions(block_timestamp) where block_consensus = true
  • blocks(timestamp) where consensus = true
stats/stats/src/charts/lines/native_coin_holders_growth.rs (3)

121-134: Consider enhancing error messages for better debugging.

While the error handling is correct, the error messages could be more descriptive. Consider adding context about what operation failed.

Example improvement:

-                .map_err(ChartError::BlockscoutDB)?;
+                .map_err(|e| ChartError::BlockscoutDB(e))
+                .map_err(|e| {
+                    tracing::error!("Failed to clear support table: {}", e);
+                    e
+                })?;

398-414: Add documentation for type definitions and hierarchy.

The type definitions using StripExt and resolution types would benefit from documentation explaining:

  1. The purpose and behavior of StripExt
  2. The relationship between different resolution types
  3. The rationale behind the type hierarchy

Consider adding documentation like:

/// Represents the integer version of NativeCoinHoldersGrowth
/// Uses StripExt to handle type conversion and MapParseTo for parsing
pub type NativeCoinHoldersGrowthInt = MapParseTo<StripExt<NativeCoinHoldersGrowth>, i64>;

/// Weekly resolution of NativeCoinHoldersGrowth
/// Uses LastValueLowerResolution for downsampling data to weekly intervals
pub type NativeCoinHoldersGrowthWeekly = DirectVecLocalDbChartSource<
    LastValueLowerResolution<NativeCoinHoldersGrowthS, Week>,
    Batch30Weeks,
    WeeklyProperties,
>;

Line range hint 275-293: Add input validation and rate limiting for security.

Consider implementing the following security measures:

  1. Validate balance values before insertion
  2. Add rate limiting for bulk operations to prevent DoS
  3. Consider adding logging for suspicious activities

Example implementation:

fn validate_balance(balance: Decimal) -> Result<(), ChartError> {
    if balance < Decimal::ZERO || balance > Decimal::MAX / 2 {
        return Err(ChartError::Internal("Invalid balance value".into()));
    }
    Ok(())
}

async fn update_current_holders<C>(
    db: &C,
    holders: impl IntoIterator<Item = db_address_balances::ActiveModel>,
) -> Result<(), DbErr>
where
    C: ConnectionTrait,
{
    let mut data = holders.into_iter().peekable();
    let take = Properties::max_rows_insert_per_iteration();
    while data.peek().is_some() {
        let chunk: Vec<_> = data.by_ref()
            .take(take)
            .map(|model| {
                validate_balance(model.balance.unwrap())?;
                Ok(model)
            })
            .collect::<Result<Vec<_>, _>>()?;
        
        // Add rate limiting
        tokio::time::sleep(Duration::from_millis(100)).await;
        
        db_address_balances::Entity::insert_many(chunk)
            .on_conflict(
                OnConflict::column(db_address_balances::Column::Address)
                    .update_column(db_address_balances::Column::Balance)
                    .to_owned(),
            )
            .exec(db)
            .await?;
    }
    Ok(())
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 66d40c8 and bdd688c.

⛔ Files ignored due to path filters (1)
  • stats/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (82)
  • stats/Cargo.toml (1 hunks)
  • stats/config/update_groups.json (1 hunks)
  • stats/stats-server/src/read_service.rs (6 hunks)
  • stats/stats-server/src/runtime_setup.rs (12 hunks)
  • stats/stats-server/src/serializers.rs (0 hunks)
  • stats/stats-server/src/server.rs (5 hunks)
  • stats/stats-server/src/update_service.rs (3 hunks)
  • stats/stats-server/tests/it/indexing_status.rs (1 hunks)
  • stats/stats/Cargo.toml (1 hunks)
  • stats/stats/src/charts/chart.rs (3 hunks)
  • stats/stats/src/charts/counters/average_block_time.rs (7 hunks)
  • stats/stats/src/charts/counters/last_new_contracts.rs (2 hunks)
  • stats/stats/src/charts/counters/last_new_verified_contracts.rs (2 hunks)
  • stats/stats/src/charts/counters/mock.rs (3 hunks)
  • stats/stats/src/charts/counters/total_accounts.rs (2 hunks)
  • stats/stats/src/charts/counters/total_blocks.rs (8 hunks)
  • stats/stats/src/charts/counters/total_contracts.rs (2 hunks)
  • stats/stats/src/charts/counters/total_native_coin_holders.rs (2 hunks)
  • stats/stats/src/charts/counters/total_verified_contracts.rs (2 hunks)
  • stats/stats/src/charts/counters/yesterday_txns.rs (3 hunks)
  • stats/stats/src/charts/db_interaction/read.rs (11 hunks)
  • stats/stats/src/charts/db_interaction/write.rs (1 hunks)
  • stats/stats/src/charts/lines/accounts_growth.rs (2 hunks)
  • stats/stats/src/charts/lines/active_accounts.rs (3 hunks)
  • stats/stats/src/charts/lines/average_block_rewards.rs (5 hunks)
  • stats/stats/src/charts/lines/average_block_size.rs (4 hunks)
  • stats/stats/src/charts/lines/average_gas_limit.rs (4 hunks)
  • stats/stats/src/charts/lines/average_gas_price.rs (5 hunks)
  • stats/stats/src/charts/lines/average_txn_fee.rs (5 hunks)
  • stats/stats/src/charts/lines/contracts_growth.rs (2 hunks)
  • stats/stats/src/charts/lines/gas_used_growth.rs (4 hunks)
  • stats/stats/src/charts/lines/mock.rs (4 hunks)
  • stats/stats/src/charts/lines/native_coin_holders_growth.rs (8 hunks)
  • stats/stats/src/charts/lines/native_coin_supply.rs (4 hunks)
  • stats/stats/src/charts/lines/new_accounts.rs (5 hunks)
  • stats/stats/src/charts/lines/new_block_rewards.rs (7 hunks)
  • stats/stats/src/charts/lines/new_blocks.rs (18 hunks)
  • stats/stats/src/charts/lines/new_contracts.rs (5 hunks)
  • stats/stats/src/charts/lines/new_native_coin_holders.rs (3 hunks)
  • stats/stats/src/charts/lines/new_native_coin_transfers.rs (5 hunks)
  • stats/stats/src/charts/lines/new_txns.rs (5 hunks)
  • stats/stats/src/charts/lines/new_verified_contracts.rs (5 hunks)
  • stats/stats/src/charts/lines/txns_fee.rs (5 hunks)
  • stats/stats/src/charts/lines/txns_growth.rs (2 hunks)
  • stats/stats/src/charts/lines/txns_success_rate.rs (4 hunks)
  • stats/stats/src/charts/lines/verified_contracts_growth.rs (2 hunks)
  • stats/stats/src/charts/mod.rs (1 hunks)
  • stats/stats/src/charts/query_dispatch.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/day.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/month.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/week.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/year.rs (3 hunks)
  • stats/stats/src/charts/types/traits.rs (1 hunks)
  • stats/stats/src/data_processing.rs (4 hunks)
  • stats/stats/src/data_source/kinds/auxiliary/cumulative.rs (3 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/delta.rs (2 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/filter_deducible.rs (7 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/last_point.rs (3 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/map/mod.rs (3 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/map/parse.rs (3 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs (1 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/map/to_string.rs (3 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/resolutions/average.rs (12 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/resolutions/last_value.rs (7 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/resolutions/mod.rs (2 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/resolutions/sum.rs (7 hunks)
  • stats/stats/src/data_source/kinds/data_manipulation/sum_point.rs (2 hunks)
  • stats/stats/src/data_source/kinds/local_db/mod.rs (14 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameter_traits.rs (3 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/mod.rs (1 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/query.rs (5 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/batching/mod.rs (12 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameter_traits.rs (2 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/cumulative.rs (2 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/mock.rs (2 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/mod.rs (3 hunks)
  • stats/stats/src/data_source/kinds/local_db/parameters/update/point.rs (2 hunks)
  • stats/stats/src/data_source/kinds/remote_db/mod.rs (3 hunks)
  • stats/stats/src/data_source/kinds/remote_db/query/all.rs (2 hunks)
  • stats/stats/src/data_source/kinds/remote_db/query/each.rs (3 hunks)
  • stats/stats/src/data_source/kinds/remote_db/query/one.rs (2 hunks)
  • stats/stats/src/data_source/source.rs (6 hunks)
⛔ Files not processed due to max files limit (8)
  • stats/stats/src/data_source/tests.rs
  • stats/stats/src/data_source/types.rs
  • stats/stats/src/lib.rs
  • stats/stats/src/range.rs
  • stats/stats/src/tests/init_db.rs
  • stats/stats/src/tests/simple_test.rs
  • stats/stats/src/update_group.rs
  • stats/stats/src/utils.rs
💤 Files with no reviewable changes (1)
  • stats/stats-server/src/serializers.rs
🔇 Additional comments (185)
stats/stats/src/charts/db_interaction/write.rs (3)

Line range hint 9-32: LGTM! Well-structured database creation logic.

The create_chart function implements proper error handling and idempotency with conflict resolution, following database best practices.


Line range hint 34-52: LGTM! Efficient bulk insert implementation.

The insert_data_many function efficiently handles bulk inserts with:

  • Proper generic constraints
  • Peekable iterator to avoid unnecessary database operations
  • Conflict resolution for concurrent operations

Line range hint 54-74: LGTM! Proper timezone handling in updates.

The set_last_updated_at function correctly handles timezone conversion and uses partial updates efficiently.

stats/stats/src/charts/counters/total_native_coin_holders.rs (2)

3-3: LGTM! Clean import addition

The addition of StripExt follows Rust's import conventions and properly groups related types from the data manipulation module.


33-33: Verify the impact of StripExt transformation

The addition of StripExt wrapper introduces an additional transformation layer to the native coin holders data. Please ensure this transformation aligns with the expected chart behavior.

✅ Verification successful

Based on the search results, I can now generate the final response since I have enough context about the StripExt usage in the codebase:

StripExt transformation is consistently used across chart data sources

The StripExt wrapper is a standard transformation layer used consistently across multiple chart data sources in the codebase. It's implemented in data_source/kinds/data_manipulation/map/strip_extension.rs and is used to transform ExtendedTimespanValue into TimespanValue by stripping extension data. This pattern is applied uniformly across various chart types including accounts, transactions, blocks, and other metrics, making this usage in total_native_coin_holders.rs consistent with the established pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for other usages of StripExt to verify consistent pattern
# and potential impact on data transformation

# Check for other StripExt implementations
ast-grep --pattern 'DirectPointLocalDbChartSource<LastPoint<StripExt<$_>>, $_>'

# Look for StripExt documentation or tests
rg -A 5 'StripExt' --type rust

Length of output: 48363

stats/stats/src/charts/counters/total_verified_contracts.rs (2)

3-4: Verify the necessity of StripExt import

The addition of StripExt suggests a new data transformation capability. This aligns with the PR's objective of implementing dynamic query dispatch, but we should verify its necessity.

✅ Verification successful

Based on the search results, I can now generate the final response since I have enough information about the usage of StripExt across the codebase:

StripExt import is consistent with codebase patterns

The StripExt import is a necessary and consistent part of the data transformation pipeline used across multiple chart implementations in the codebase. It's used to strip extension information from ExtendedTimespanValue types, which is a common pattern seen in:

  • All counter implementations (e.g., total accounts, total verified contracts)
  • Line chart implementations (e.g., accounts growth, contracts growth)
  • Data processing chains combined with other transformations like MapParseTo, LastPoint, etc.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if StripExt is consistently used across other counter implementations
# and verify its purpose in the codebase

# Check for other counter implementations using StripExt
ast-grep --pattern 'DirectPointLocalDbChartSource<LastPoint<StripExt<$_>>, $_>'

# Look for StripExt usage documentation or tests
rg -A 5 'StripExt' --type rust

Length of output: 48363


33-33: Verify behavior changes with StripExt wrapper

The addition of StripExt wrapper around VerifiedContractsGrowth modifies the data processing pipeline. Please ensure:

  1. The transformation maintains data integrity
  2. The change is backward compatible
  3. The behavior aligns with the counter's requirements
✅ Verification successful

Let me gather more information about the StripExt and ExtendedTimespanValue types to better understand their behavior.


Based on the gathered information, I can now provide a final response:

StripExt wrapper is a safe data transformation

The StripExt wrapper is a simple transformation that removes the is_approximate flag from ExtendedTimespanValue, converting it to TimespanValue. This operation:

  1. Maintains data integrity by preserving both the timespan and value fields
  2. Is backward compatible as it's a simple field removal operation
  3. Aligns with counter requirements as it only strips metadata while keeping the core data intact
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Look for tests and documentation related to StripExt behavior
# and its impact on VerifiedContractsGrowth

# Check for related tests
rg -A 10 'VerifiedContractsGrowth.*StripExt' --type rust

# Look for documentation about StripExt behavior
rg -A 5 'struct StripExt' --type rust

Length of output: 2758


Script:

#!/bin/bash
# Look for the implementation and usage of ExtendedTimespanValue
rg -A 10 'ExtendedTimespanValue' --type rust

# Look for the actual implementation of StripExt type
ast-grep --pattern 'type StripExt'

# Look for any tests involving StripExt
rg -A 10 'test.*StripExt' --type rust

Length of output: 38871

stats/stats/src/charts/lines/txns_fee.rs (4)

6-6: LGTM: Import changes align with type system updates

The new imports support the transition to dynamic query dispatch and enhanced type safety through QueryAllBlockTimestampRange and StripExt.

Also applies to: 10-10, 29-29, 31-31


39-39: LGTM: Type signature update for better timezone handling

The change from DateTimeUtc to DateTime<Utc> improves type safety and aligns with Rust's standard datetime handling.


110-112: LGTM: Enhanced type definitions for better data handling

The changes improve the type system in two ways:

  1. Addition of QueryAllBlockTimestampRange enables dynamic query dispatch
  2. StripExt wrapper provides better data transformation capabilities

These changes align well with the PR objectives of implementing dynamic query dispatch.

Also applies to: 142-142, 153-153


Line range hint 39-109: Consider optimizing the SQL query performance

The SQL query handles complex fee calculations including EIP-1559 fee mechanics. Consider these optimizations:

  1. Add indexes on block_timestamp and timestamp columns if not already present
  2. Consider materializing the complex fee calculation for frequently accessed data

Let's verify the existing indexes:

✅ Verification successful

Indexes are already in place for timestamp-based queries

The codebase already has appropriate indexes for optimizing the timestamp-based queries:

  • blocks_timestamp_index on blocks.timestamp
  • transactions_block_timestamp_index on transactions.block_timestamp
  • Additional composite index blocks_date on DATE(timestamp) which directly supports the GROUP BY clause

These indexes cover all the timestamp-based filtering and grouping operations in the query. The complex fee calculation itself is a runtime computation that cannot be further optimized through indexing.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing indexes on timestamp columns
rg -A 5 'CREATE.*INDEX.*timestamp|ALTER.*INDEX.*timestamp' 

Length of output: 1491

stats/stats/src/charts/lines/average_gas_price.rs (3)

4-4: LGTM: Import changes align with type adjustments

The added imports support the implementation of dynamic query dispatch and enhanced type safety through QueryAllBlockTimestampRange and StripExt.

Also applies to: 8-8, 27-27, 29-29


109-111: LGTM: Enhanced query flexibility with QueryAllBlockTimestampRange

The addition of QueryAllBlockTimestampRange as a generic parameter enables dynamic query dispatch, aligning with the PR objectives.


Line range hint 39-107: Consider adding an index for performance optimization

The query performs complex joins and aggregations on the blocks and transactions tables. Consider adding an index on (timestamp, consensus) for the blocks table and (block_consensus, block_timestamp) for the transactions table to optimize query performance.

Let's verify the existing indexes:

stats/stats/src/charts/lines/native_coin_supply.rs (4)

4-4: LGTM: Import changes are well-organized and necessary.

The new imports support the type system changes and are properly organized.

Also applies to: 8-9, 26-26, 28-28


Line range hint 44-89: LGTM: SQL queries are properly secured.

The implementation uses parameterized queries and proper parameter binding, following SQL injection prevention best practices.


93-95: LGTM: Type system changes are well-structured.

The introduction of StripExt and the modifications to type parameters maintain type safety while enhancing functionality. The type hierarchy is logically organized with proper resolution handling.

Let's verify the test coverage for these changes:

Also applies to: 126-126, 128-135, 137-140


Line range hint 35-40: Clarify the accuracy implications of timezone conversion.

The conversion from DateTime<Utc> to NaiveDate drops timezone information. The comment "chart is off anyway" suggests known accuracy issues. Please:

  1. Document the potential impact of timezone conversion
  2. Clarify what "chart is off anyway" means - are there known accuracy issues that need addressing?

Let's check for other timezone-sensitive queries in the codebase:

stats/stats/src/charts/lines/txns_growth.rs (2)

4-4: LGTM: Import statement is correctly organized

The StripExt import is properly placed within the data manipulation module imports.


50-52: Verify the impact of StripExt on data processing

The change from direct types to stripped versions might affect data processing behavior. Let's verify the implementation and usage.

The type modifications maintain proper type safety and follow a consistent pattern across different time resolutions.

Also applies to: 55-57, 61-63

✅ Verification successful

StripExt is safely used for data transformation across time resolutions

The verification shows that StripExt is a well-established data transformation type used consistently across the codebase for handling time-series data. From the implementation in strip_extension.rs, we can see that:

  1. It's a type-safe transformation that converts ExtendedTimespanValue to TimespanValue
  2. It's used consistently with LastValueLowerResolution for time resolution conversions (Week, Month, Year)
  3. The pattern is applied uniformly across multiple chart types (txns, contracts, accounts, etc.)

The change maintains type safety and follows the established pattern for data processing across different time resolutions in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for StripExt implementation and usage patterns
echo "Searching for StripExt implementation..."
rg -A 10 "impl.*StripExt"

echo "Searching for other uses of StripExt in the codebase..."
rg "StripExt\<.*\>"

echo "Searching for related tests..."
rg -l "test.*strip"

Length of output: 2713


Script:

#!/bin/bash
# Let's search for StripExt without regex escape sequences
echo "Searching for StripExt usage..."
rg "StripExt"

# Let's also look for the specific types mentioned in the code
echo -e "\nSearching for TxnsGrowthS usage..."
rg "TxnsGrowthS"

# Let's check the implementation of LastValueLowerResolution
echo -e "\nSearching for LastValueLowerResolution..."
rg "LastValueLowerResolution"

# Let's also check for any strip-related functions or types
echo -e "\nSearching for strip-related implementations..."
rg "strip|Strip" -g "*.rs"

Length of output: 27252

stats/stats/src/charts/lines/new_contracts.rs (3)

4-4: LGTM: Import changes align with type updates

The import changes appropriately support the transition to more explicit datetime types and enhanced query capabilities.

Also applies to: 8-8, 27-27, 29-29


120-122: LGTM: Enhanced query capabilities with QueryAllBlockTimestampRange

The addition of QueryAllBlockTimestampRange aligns with the PR objective of implementing dynamic query dispatch for chart behavior.


150-150: Verify consistent usage of StripExt across the codebase

The introduction of StripExt in the type definitions suggests a change in data transformation strategy.

Also applies to: 161-161

✅ Verification successful

Let me try a different approach to search for potential inconsistencies.


StripExt usage is consistent across chart implementations

The analysis shows that StripExt is consistently used across all chart implementations in the codebase:

  • All MapParseTo type definitions consistently use StripExt wrapper
  • The pattern is uniformly applied across different chart types (accounts, blocks, transactions, contracts, etc.)
  • Both daily and monthly data types follow the same pattern
  • No inconsistencies or missing StripExt usage were found in any chart implementations

The introduction of StripExt in the type definition is part of a consistent data transformation strategy across the entire codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of StripExt across similar chart implementations

# Search for other chart implementations using StripExt
echo "Checking StripExt usage patterns:"
rg "MapParseTo<StripExt<" -A 2

# Search for potential inconsistencies where StripExt might be missing
echo "\nChecking for potential missing StripExt usage:"
rg "MapParseTo<(?!StripExt)" -A 2

Length of output: 7009


Script:

#!/bin/bash
# Search for all MapParseTo type definitions to ensure we don't miss any cases
echo "Checking all MapParseTo usage patterns:"
rg "pub type.*= MapParseTo<" -A 2

# Search for StripExt usage to understand the pattern
echo -e "\nChecking all StripExt usage:"
rg "StripExt<" --type rust

Length of output: 12915

stats/stats/src/charts/lines/new_accounts.rs (5)

4-8: Correct and Necessary Import Updates

The added imports (QueryAllBlockTimestampRange, UniversalRange, StripExt, ChartError, etc.) are appropriate for the updated functionalities and improve the readability and maintainability of the code.

Also applies to: 24-27, 30-30, 32-32


38-38: Consistent Use of DateTime<Utc>

Updating the parameter type to Option<Range<DateTime<Utc>>> in the get_statement method ensures consistent time representation across the codebase. This is a good practice that enhances code clarity.


42-42: Verify the Impact of Using DateTime::<Utc>::UNIX_EPOCH

Changing min_timestamp to DateTime::<Utc>::UNIX_EPOCH sets the minimum timestamp to the Unix epoch (1970-01-01). Please verify that this change does not exclude any historical data prior to the Unix epoch, especially if the blockchain contains blocks with earlier timestamps.


103-107: Improved Range Handling and Error Management

The use of UniversalRange<DateTime<Utc>> and data_source_query_range_to_db_statement_range in the query_data method enhances the flexibility and correctness of date range handling. Additionally, updating error handling to use ChartError promotes consistent error management throughout the codebase.

Also applies to: 118-118


159-159: Type Definitions Updated with StripExt

Incorporating StripExt into NewAccountsInt and NewAccountsMonthlyInt aligns with recent changes and simplifies type definitions. This adjustment ensures that the chart sources work correctly with the modified data types.

Also applies to: 170-170

stats/stats/src/charts/lines/new_verified_contracts.rs (4)

Line range hint 34-47: LGTM! Type-safe datetime handling implemented correctly.

The transition to DateTime<Utc> improves type safety while maintaining the existing query functionality. The SQL query properly handles the date filtering with the optional range parameter.


52-59: LGTM! Enhanced type definition supports dynamic query dispatch.

The addition of QueryAllBlockTimestampRange to the type signature properly implements the dynamic query dispatch feature mentioned in the PR objectives.


4-4: LGTM! Verify StripExt usage across the codebase.

The import changes align well with the PR objectives. The transition to more precise datetime types and the addition of QueryAllBlockTimestampRange support the dynamic query dispatch feature.

Let's verify the consistent usage of StripExt across the codebase:

Also applies to: 8-8, 27-27, 29-29

✅ Verification successful

StripExt usage is consistent across the codebase

The verification shows that StripExt is consistently used across all chart implementations in the stats module, following the same pattern:

  • Used with MapParseTo for integer/float conversions
  • Applied uniformly in weekly/monthly/yearly aggregations
  • Properly integrated with DirectVecLocalDbChartSource and DirectPointLocalDbChartSource
  • Follows the same pattern as other similar chart implementations (new_contracts, new_txns, etc.)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent StripExt usage patterns
# Look for any potential inconsistencies in StripExt usage

# Search for StripExt usage patterns
rg "StripExt\s*<" -A 2

# Check if there are any direct uses of the types without StripExt
rg "NewVerifiedContracts\s*[,>]" --type rust

Length of output: 18748


88-88: Verify the impact of StripExt transformation.

The addition of StripExt wrapper to both types introduces a new data transformation step. Please ensure that this transformation:

  1. Doesn't affect the existing data processing pipeline
  2. Maintains backward compatibility with existing chart data

Let's verify the transformation's impact:

Also applies to: 99-99

✅ Verification successful

StripExt transformation is a safe data conversion operation

The implementation shows that StripExt is a simple transformation that converts ExtendedTimespanValue into TimespanValue using a safe .into() conversion. This is a backward-compatible change that:

  1. Preserves the underlying data structure (TimespanValue)
  2. Only strips extended metadata through a standard conversion
  3. Is consistently applied across all chart types using the same pattern

The transformation maintains data integrity while standardizing the value types used in the chart processing pipeline.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for StripExt implementation and its usage patterns
# Look for any test cases or documentation about StripExt behavior

# Search for StripExt implementation
ast-grep --pattern 'impl$_<$_> for StripExt<$_> {
  $$$
}'

# Search for test cases involving StripExt
rg "test.*StripExt" --type rust

Length of output: 94


Script:

#!/bin/bash
# Let's try a different approach to understand StripExt usage and implementation

# Find the StripExt definition
rg "struct StripExt" --type rust -A 5

# Find where StripExt is used
rg "StripExt" --type rust -A 2

# Look for any type definitions using StripExt
rg "type.*StripExt" --type rust

# Search for any files containing StripExt to understand its context
fd -e rs | xargs grep -l "StripExt"

Length of output: 35296


Script:

#!/bin/bash
# Let's check the StripExtensionFunction implementation to understand its behavior
rg -A 10 "impl.*MapFunction.*for StripExtensionFunction" --type rust

# Look for the actual implementation of the strip extension functionality
rg "fn apply" stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs -A 10

Length of output: 2437

stats/stats/src/charts/lines/new_block_rewards.rs (2)

9-9: LGTM: Import changes are well-organized and necessary.

The new imports support the enhanced functionality for timestamp handling and data manipulation.

Also applies to: 12-15, 29-29, 31-31


57-59: Verify StripExt transformation behavior.

The addition of StripExt wrapper in NewBlockRewardsInt suggests data transformation before parsing to i64. Please ensure this doesn't affect existing data integrity.

Also applies to: 88-88

✅ Verification successful

Based on the search results, I can now generate the final response since we have enough context about the StripExt usage. The implementation shows it's a safe transformation that simply converts ExtendedTimespanValue to TimespanValue through a standard into() implementation, with no data manipulation that could affect integrity.

StripExt wrapper is a safe data transformation.

The StripExt wrapper is a type-safe transformation that only removes the extended metadata wrapper while preserving the underlying data through a standard into() implementation. This is a common pattern used across multiple chart types in the codebase and does not affect data integrity.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other StripExt usage patterns to verify consistency
ast-grep --pattern 'type $_ = MapParseTo<StripExt<$_>, $_>'

Length of output: 61


Script:

#!/bin/bash
# Let's try a broader search for StripExt usage
rg "StripExt" -A 2 -B 2

# Also search for NewBlockRewardsInt definition
ast-grep --pattern 'type NewBlockRewardsInt = $_'

Length of output: 57129


Script:

#!/bin/bash
# Let's look at the StripExtensionFunction implementation
rg -A 10 "impl.*StripExtensionFunction" 

# Also search for the definition of ExtendedTimespanValue
ast-grep --pattern 'struct ExtendedTimespanValue'

Length of output: 2363

stats/stats/src/charts/lines/new_native_coin_transfers.rs (3)

4-4: LGTM: Import changes align with type adjustments

The new imports support the transition to dynamic query dispatch and enhanced type safety with explicit DateTime handling.

Also applies to: 8-8, 27-27, 29-29


35-35: LGTM: Improved DateTime handling

The change to DateTime<Utc> is more idiomatic and type-safe. However, let's verify the SQL query performance with both schemas.

✅ Verification successful

Based on the search results, I can now generate the final response as we have sufficient information about the SQL query patterns and denormalization usage across the codebase:

SQL queries are consistent with established patterns

The timestamp-based GROUP BY queries follow the same pattern across all chart implementations, with proper handling of both denormalized (t.block_timestamp) and normalized (b.timestamp) schemas. The change to DateTime<Utc> maintains compatibility with these existing query patterns.

  • All chart implementations consistently use the denormalization flag to switch between schemas
  • The timestamp columns are used consistently in GROUP BY clauses across both schemas
  • The range parameter type change doesn't impact the query structure or performance
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential performance issues in SQL queries
# Look for similar queries that might provide insights into performance patterns

# Search for similar timestamp-based GROUP BY queries
rg -A 5 "GROUP BY date" --type rust

# Look for other uses of denormalization flag
rg "completed_migrations\.denormalization" --type rust

Length of output: 8764


117-117: Verify the purpose and impact of StripExt wrapper

The addition of StripExt wrapper to both types suggests a data transformation step. Let's verify its implementation and usage pattern.

Also applies to: 128-129

✅ Verification successful

StripExt wrapper is a necessary data transformation component

The StripExt wrapper is correctly used in the type definition. It's a data transformation component that:

  • Removes the Extended part from ExtendedTimespanValue, converting it to TimespanValue
  • Preserves the core timespan and value data while removing the is_approximate flag
  • Is consistently applied across all chart data sources that need to handle extended timespan values

This pattern is used throughout the codebase for chart data processing and is working as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Investigate StripExt implementation and usage

# Look for StripExt implementation
ast-grep --pattern 'struct StripExt$$$'

# Find other uses of StripExt
rg "StripExt\<" --type rust

# Look for related tests
rg "test.*StripExt" --type rust

Length of output: 190


Script:

#!/bin/bash
# Let's try different search patterns to find StripExt implementation and usage

# Look for StripExt implementation
rg "struct StripExt"

# Find StripExt usage without escape characters
rg "StripExt" --type rust

# Look for impl blocks for StripExt
ast-grep --pattern 'impl$_ StripExt$_'

# Search for type definitions using StripExt
rg "type.*StripExt.*=" --type rust

Length of output: 10839


Script:

#!/bin/bash
# Let's look at the implementation details of StripExtensionFunction to understand what it does

# Get the full implementation file content
cat stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs

# Look for ExtendedTimespanValue definition as it's used in the implementation
rg "struct ExtendedTimespanValue" --type rust -A 5

Length of output: 1523

stats/stats/src/charts/lines/average_txn_fee.rs (3)

6-6: LGTM: Import changes are well-aligned with type modifications

The new imports support the enhanced type system changes and timestamp handling modifications.

Also applies to: 10-10, 29-29, 31-31


Line range hint 41-111: Consider query performance optimization opportunities

The SQL queries, especially in the denormalized case, involve complex calculations and multiple joins. Consider:

  1. Adding appropriate indexes on block_timestamp, timestamp, and block_hash columns
  2. Materializing commonly accessed calculations

Verify timestamp handling in queries

The queries use multiple timestamp comparisons (timestamp != to_timestamp(0)). Ensure this approach handles all edge cases correctly.

✅ Verification successful

The search results show consistent usage of to_timestamp(0) across the codebase, particularly in chart-related queries. There's even a migration file m20230814_105206_drop_zero_timestamp.rs that specifically handles zero timestamps. Let me check this migration file to understand the rationale better.


Timestamp handling is correctly implemented

The timestamp handling in the queries is consistent with the codebase's established pattern. The to_timestamp(0) check is a deliberate filtering mechanism across all chart-related queries, with a dedicated migration that removes such records. This approach is systematically used alongside consensus checks to ensure data quality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential timestamp edge cases in the codebase
rg -A 2 "to_timestamp\(0\)" 

Length of output: 13240


Script:

#!/bin/bash
# Check the migration file content
cat stats/stats/migration/src/m20230814_105206_drop_zero_timestamp.rs

Length of output: 517


112-114: Document the purpose and implications of StripExt

The introduction of StripExt wrapper types affects multiple type definitions. Please add documentation explaining:

  1. The purpose of StripExt
  2. What functionality it strips
  3. When it should be used

Verify type consistency across time resolutions

The type modifications maintain a consistent pattern across daily, weekly, monthly, and yearly resolutions. Ensure this consistency is maintained in related chart implementations.

Also applies to: 145-159

stats/stats/src/charts/lines/gas_used_growth.rs (6)

56-58: Update of GasUsedPartialRemote to include QueryAllBlockTimestampRange

The type alias GasUsedPartialRemote now includes QueryAllBlockTimestampRange in PullAllWithAndSort. This enhancement allows for more precise querying over specified timestamp ranges, improving the flexibility and efficiency of data retrieval.


108-110: Simplify type definitions using StripExt

The introduction of GasUsedGrowthS as StripExt<GasUsedGrowth> and its use in GasUsedGrowthWeekly simplifies the type definitions and removes unnecessary extensions. This enhances code readability and maintainability by reducing complexity in type hierarchies.


115-115: Apply StripExt to monthly growth type

Similarly, defining GasUsedGrowthMonthly with GasUsedGrowthS and using StripExt maintains consistency across weekly and monthly growth types, further simplifying the codebase.


119-121: Introduce GasUsedGrowthMonthlyS for yearly aggregation

The creation of GasUsedGrowthMonthlyS as StripExt<GasUsedGrowthMonthly> and its use in GasUsedGrowthYearly provides a clean and consistent approach to aggregating monthly data into yearly statistics.


35-35: Confirm the consistent use of DateTime<Utc>

The get_statement function now uses Option<Range<DateTime<Utc>>> for the range parameter instead of Option<Range<DateTimeUtc>>. Ensure that this change is consistently applied throughout the codebase and that all references to DateTimeUtc have been updated to DateTime<Utc> to prevent any type mismatches or compilation errors.

Run the following script to verify that no instances of DateTimeUtc remain:

✅ Verification successful

Change from DateTimeUtc to DateTime<Utc> is consistent

Based on the comprehensive search results, there are no occurrences of DateTimeUtc in the codebase, while DateTime<Utc> is consistently used throughout. The change in the function signature is aligned with the rest of the codebase's usage of chrono's datetime types.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of 'DateTimeUtc' in the codebase.

# Test: Search for 'DateTimeUtc'. Expectation: No matches found.
rg 'DateTimeUtc'

Length of output: 16


Script:

#!/bin/bash
# Let's verify the usage of DateTime<Utc> in the codebase to ensure consistency

# Search for DateTime<Utc> usage
rg "DateTime<Utc>" -A 2

# Also check for any other potential datetime type imports or usages
rg "use chrono::" -A 2

Length of output: 65925


64-64: Change error type to ChartError for enhanced error handling

The function now returns Result<Self::Output, ChartError> instead of UpdateError. Ensure that ChartError appropriately captures all error scenarios previously handled by UpdateError and that any error-handling logic is updated accordingly in the codebase.

Run the following script to check for any remaining usages of UpdateError:

✅ Verification successful

Based on the search results, I can see that:

  1. ChartError is a well-defined error type in the codebase (defined in stats/stats/src/charts/chart.rs) that includes various error variants like BlockscoutDB, StatsDB, ChartNotFound, IntervalTooLarge, etc.

  2. The change from UpdateError to ChartError is consistent with the codebase as:

    • No occurrences of UpdateError were found in the codebase
    • ChartError is widely used across the codebase for error handling in chart-related operations
    • The function's error type change aligns with other similar functions in the codebase that return Result<T, ChartError>
  3. The error handling logic in the codebase consistently uses ChartError for all chart-related operations, suggesting this is the standard error type for chart functionality.

No issues found with the change to ChartError

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'UpdateError' is no longer used in the codebase.

# Test: Search for 'UpdateError'. Expectation: No matches found.
rg 'UpdateError'

Length of output: 16


Script:

#!/bin/bash
# Let's verify the error types more thoroughly

# Check for any error types in the current file
rg -A 3 'Error' stats/stats/src/charts/lines/gas_used_growth.rs

# Check for ChartError definition and its variants
rg -A 5 'ChartError'

# Look for any error type definitions or usages in the charts module
fd . stats/stats/src/charts -t f -e rs --exec rg -l 'Error'

Length of output: 65977

stats/stats/src/charts/lines/new_blocks.rs (17)

4-4: Import QueryAllBlockTimestampRange is correctly added

The addition of QueryAllBlockTimestampRange to the imports ensures that the type is available for use in the updated type definitions below.


34-34: Updated function parameter to use DateTime<Utc>

Changing the range parameter to Option<Range<DateTime<Utc>>> aligns with standard chrono types and improves consistency in time representations throughout the code.


54-56: Include QueryAllBlockTimestampRange in NewBlocksRemote type definition

Adding QueryAllBlockTimestampRange as a type parameter enhances the querying capabilities of NewBlocksRemote, allowing for more precise data retrieval based on timestamp ranges.


84-84: Apply StripExt to NewBlocksInt for data consistency

Incorporating StripExt ensures that extraneous data is stripped from NewBlocks, resulting in consistent and expected data types for further processing.


95-95: Apply StripExt to NewBlocksMonthlyInt for consistency

Similarly, adding StripExt to NewBlocksMonthlyInt aligns it with NewBlocksInt, maintaining consistency across different time resolutions.


108-109: Import necessary modules for serialization and range handling

The added imports for serialize_line_points, QuerySerialized, and UniversalRange are essential for the updated data querying and serialization logic in the tests.


111-111: Update test initialization functions

Using init_marked_db_all and fill_mock_blockscout_data improves the test setup by providing a more comprehensive initialization of the mocked databases.


127-132: Initialize test databases and data accurately

The updates ensure that the test environment is properly prepared with initialized databases and mock data, which is crucial for reliable test results.


136-138: Fetch minimum block number from Blockscout

Retrieving min_blockscout_block ensures that tests are working with the correct block references, enhancing the accuracy of the test scenarios.


179-181: Use UniversalRange::full() for querying complete data

Applying UniversalRange::full() in query_data_static allows for querying the entire range of data, which is appropriate for comprehensive tests.


206-208: Ensure full data query after forced full update

After setting force_full to true, querying the full data range verifies that the complete dataset is accurately retrieved and updated.


238-243: Initialize and update data for fresh tests

In the update_new_blocks_fresh test, initializing and updating data ensures that fresh states are tested correctly, validating the initialization logic.


255-257: Verify data after full update

Retrieving and asserting the data post-update confirms that the full update logic is functioning as intended.


287-292: Test updating with existing incorrect data

The update_new_blocks_last test checks how the system handles and corrects preexisting incorrect data, which is important for data integrity.


296-298: Retrieve minimum block number for accurate data correction

Fetching min_blockscout_block aids in ensuring that corrections are based on accurate block references within the test.


352-354: Query and validate data after partial update

Verifying the data post-partial update helps ensure that only the necessary data is updated and that existing correct data remains unchanged.


377-377: Assert final data correctness

The final assertion confirms that the data matches expected results, validating the cumulative changes and updates applied throughout the tests.

stats/stats/src/data_source/kinds/remote_db/query/all.rs (6)

22-22: Update parameter type to DateTime<Utc>

Changing the range parameter's type to Option<Range<DateTime<Utc>>> in the get_statement method ensures consistency with the chrono crate's DateTime<Utc> type throughout the codebase.


33-35: Addition of AllRangeSource generic parameter

Introducing the AllRangeSource generic parameter in PullAllWithAndSort enhances flexibility by allowing different range sources for data queries, improving the modularity of the data retrieval mechanism.


43-50: Implementation of RemoteQueryBehaviour with new generic parameter

Updating the implementation to include AllRangeSource ensures that the PullAllWithAndSort struct conforms to the RemoteQueryBehaviour trait, leveraging the new generic parameter for more dynamic query behaviors.


56-57: Refinement of query_data method signature

The query_data method now accepts a UniversalRange<DateTime<Utc>> for the range parameter and returns a Result with ChartError. This improves date range handling and provides more specific error information.


60-60: Usage of data_source_query_range_to_db_statement_range

Utilizing data_source_query_range_to_db_statement_range with the AllRangeSource generic parameter enhances the adaptability of query range conversion, aligning with the updated range handling strategy.


63-63: Update database connection reference

Changing to cx.blockscout.connection.as_ref() for the database connection improves code clarity and aligns with the connection handling conventions used elsewhere in the codebase.

stats/stats/src/charts/lines/mock.rs (4)

57-58: Update mock_trim_lines function signature

The query_range parameter is now a UniversalRange<DateTime<Utc>>, enhancing the function's capability to handle various range bounds and improving consistency in date range representations.


65-74: Enhanced date range end calculation

The revised logic for determining date_range_end using query_range.end with proper handling of Bound variants ensures accurate trimming of data within the specified date range, preventing off-by-one errors.


102-103: Refinement of query_data method in PseudoRandomMockLineRetrieve

Accepting a UniversalRange<DateTime<Utc>> for the range parameter and returning a Result with ChartError enhances date handling and provides more precise error reporting in the mock data retrieval.


148-149: Adjustment of query_data method in PredefinedMockRetrieve

Updating the range parameter to UniversalRange<DateTime<Utc>> aligns with the new date range handling approach, ensuring consistency across different mock data retrieval implementations.

stats/stats/src/charts/types/traits.rs (3)

47-54: Introduction of checked_add and checked_sub methods

Adding checked_add and checked_sub methods to the Timespan trait allows for safer arithmetic operations that can handle potential overflows or underflows by returning an Option<Self>.


55-66: Refactoring saturating_add and saturating_sub methods

Redefining saturating_add and saturating_sub to utilize checked_add and checked_sub provides a fallback to max or min values when overflow or underflow occurs, ensuring the operations do not panic and maintain predictable behavior.


53-54: Addition of max and min methods

Introducing the max and min methods to the Timespan trait establishes clear boundaries for timespan values, facilitating safe arithmetic operations and consistent handling of edge cases.

stats/stats/src/charts/lines/average_gas_limit.rs (6)

4-8: Importing QueryAllBlockTimestampRange

Adding the import for QueryAllBlockTimestampRange enables querying block timestamp ranges, enhancing data sourcing capabilities for average gas limit calculations.


27-29: Consistent usage of DateTime<Utc>

Updating imports to use DateTime<Utc> from the chrono crate ensures consistency in time representations across the module.


Line range hint 36-46: Adjusting get_statement method parameter type

Changing the range parameter in AverageGasLimitStatement::get_statement to Option<Range<DateTime<Utc>>> standardizes date range handling and aligns with the updated types used throughout the codebase.


56-58: Enhancement of AverageGasLimitRemote type definition

Including QueryAllBlockTimestampRange in the PullAllWithAndSort type enhances the remote data source's ability to handle dynamic block timestamp ranges, improving data accuracy for the average gas limit chart.


87-87: Introduction of AverageGasLimitS type alias

Defining AverageGasLimitS as StripExt<AverageGasLimit> simplifies type definitions and promotes code readability by abstracting away the extended type details.


89-101: Refactoring chart types to use simplified aliases

Updating AverageGasLimitWeekly, AverageGasLimitMonthly, and AverageGasLimitYearly to utilize the new AverageGasLimitS alias streamlines type definitions and maintains consistency across different resolution implementations.

stats/stats/src/data_source/kinds/data_manipulation/resolutions/mod.rs (3)

14-18: Refactored date range functions improve flexibility and correctness

The changes to date_range_to_timespan function correctly utilize UniversalRange, enhancing the flexibility in handling date ranges. The mapping of optional start and end dates to timespans is appropriately handled.


21-33: extend_to_timespan_boundaries function updates are appropriate

The modifications in extend_to_timespan_boundaries function align with the new UniversalRange type and correctly calculate the extended date ranges.


91-143: Tests are properly updated to reflect function changes

The test cases have been updated to match the new function signatures and cover various scenarios effectively.

stats/stats/src/charts/query_dispatch.rs (3)

25-56: QuerySerialized trait is well-defined for unified data querying

The QuerySerialized trait provides a clean and flexible interface for querying chart data with dynamic dispatch. The method signatures and type constraints are appropriately designed.


64-100: ChartTypeSpecifics enum effectively encapsulates chart-specific queries

The implementation of ChartTypeSpecifics and its methods enhances code structure by neatly handling different chart types and their associated query handles.


137-173: Correct implementation of QuerySerialized for LocalDbChartSource

The implementation correctly handles querying and serialization of chart data, ensuring compatibility with the QuerySerialized trait.

stats/stats/src/charts/types/timespans/week.rs (1)

109-114: Implementation of max and min methods is correct

The max and min methods correctly return Week instances from NaiveDate::MAX and NaiveDate::MIN, ensuring proper boundary handling.

stats/stats/src/charts/types/timespans/month.rs (1)

98-103: Implementation of max and min methods is correct

The max and min methods properly create Month instances from NaiveDate::MAX and NaiveDate::MIN, ensuring correct maximum and minimum bounds.

stats/stats/src/charts/chart.rs (2)

Line range hint 21-39: Renaming UpdateError to ChartError enhances clarity

Replacing UpdateError with ChartError throughout the codebase improves error handling clarity and better reflects the context of errors.


238-265: ChartObject and construct_from_chart are well-implemented

The introduction of ChartObject and its construct_from_chart method effectively supports dynamic chart representations.

stats/stats-server/src/read_service.rs (4)

30-31: Update to MarkedDbConnection improves type safety

Changing the db and blockscout fields to MarkedDbConnection enhances type safety and ensures that the correct database connections are used.


66-70: Rename map_read_error to map_update_error for clarity

Renaming the function to map_update_error and updating it to process ChartError improves consistency in error handling across the codebase.


100-120: Asynchronous query handling is implemented correctly

The new query_with_handle method appropriately handles asynchronous queries with proper error handling and context setup.


166-204: Error handling in get_counters could miss critical failures

In the get_counters method, errors during querying counters are logged but the counter is skipped silently. This may lead to missing counters without the client being aware.

Consider whether it is acceptable for counters to be silently omitted. If not, you might want to aggregate and report errors to the client or handle errors differently to ensure critical counters are not missed.

stats/stats/src/data_source/kinds/data_manipulation/resolutions/average.rs (3)

38-38: Addition of Ord constraint enhances type safety

Adding the Ord trait bound to LowerRes in the type constraints ensures that timespans can be ordered, which is necessary for correct operation in functions like zip_same_timespan.


68-68: Update to use UniversalRange<DateTime<Utc>>

Changing the range type to UniversalRange<DateTime<Utc>> standardizes range handling across the codebase and improves flexibility.


323-325: Use of MarkedDbConnection::in_memory in tests

Updating the test setup to use MarkedDbConnection::in_memory ensures consistency with the updated connection types and provides a cleaner test setup.

stats/stats-server/src/runtime_setup.rs (7)

35-39: Renaming enabled_resolutions to resolutions improves clarity

Updating the field name to resolutions in EnabledChartEntry makes the code clearer and more consistent with the rest of the codebase.


67-67: Addition of type_specifics field enhances chart configuration

Adding the type_specifics field to EnabledResolutionEntry allows for more detailed chart type configurations, improving flexibility.


70-80: Transition to ChartObject in From implementation

Updating the From implementation to use ChartObject reflects the changes in the underlying data structures and ensures correct data mapping.


119-122: Introduction of AllChartsInfo struct refines data organization

Defining AllChartsInfo to separate counters and line charts enhances the organization of chart data and simplifies processing.


Line range hint 152-189: Ensure proper error handling in charts_info_from_settings

In the charts_info_from_settings function, when matching entries, ensure that all cases are appropriately handled and that unknown charts are correctly collected for error reporting.


Line range hint 202-234: Refactoring to all_charts_info_from_settings improves maintainability

Refactoring the method to process both counters and line charts together simplifies the logic and reduces code duplication.


373-375: Potential inconsistency in chart key mapping

In the warn_non_member_charts function, the assertion checks for property equality when encountering duplicate member keys. This could cause a panic if properties differ unintentionally.

Ensure that chart keys and properties are consistent across all members. It might be helpful to log a warning instead of panicking if duplicates with differing properties are found.

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/mod.rs (1)

Line range hint 20-75: Code changes are well-structured and improve error handling

The updates to use ExtendedTimespanValue and ChartError enhance error management and data handling within the batch update process. The changes are coherent and correctly implemented, aligning with the broader error handling strategy.

Also applies to: 110-115, 132-172, 174-238, 329-333

stats/stats/src/data_source/kinds/local_db/parameters/mod.rs (1)

6-8: New exports are appropriate

Adding QueryLastWithEstimationFallback and ValueEstimation to the public exports is appropriate, as it extends the module's functionality without impacting existing code.

stats/stats/src/charts/mod.rs (2)

5-5: LGTM: New module aligns with PR objectives

The addition of query_dispatch module supports the implementation of dynamic query dispatch for chart behavior as outlined in the PR objectives.


8-9: LGTM: Consistent error handling transition

The transition from UpdateError to ChartError in the exports aligns with the broader error handling improvements across the codebase.

stats/Cargo.toml (1)

16-16: Verify trait-variant version for potential updates

The trait-variant dependency is pinned to version 0.1.2. Let's verify if this is the latest stable version and check for any security advisories.

✅ Verification successful

Version 0.1.2 of trait-variant is up to date and secure

The dependency is using the latest available version (0.1.2) from crates.io and there are no security advisories reported for this package.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check latest version and any security advisories for trait-variant

# Get latest version from crates.io
curl -s https://crates.io/api/v1/crates/trait-variant | jq -r '.crate.max_version'

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: RUST, package: "trait-variant") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 436

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameter_traits.rs (1)

8-8: LGTM: Consistent error handling transition

The transition from UpdateError to ChartError in the batch_update_values_step_with method is consistent with the broader error handling improvements. The method signature maintains its async behavior and Send marker appropriately.

Also applies to: 28-28

✅ Verification successful

Based on the search results, I can now generate the final response. The code shows that the trait BatchStepBehaviour and its implementations consistently use ChartError as the error type, and there are no remaining usages of UpdateError in the file. The change is part of a systematic error handling transition.

LGTM: Error type transition is consistent

The change from UpdateError to ChartError in the batch_update_values_step_with method is consistent with the trait definition and its implementations across the codebase. All implementations of BatchStepBehaviour use ChartError as their error type, maintaining consistency in error handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent error type usage across the codebase

# Check for any remaining UpdateError usage
rg "UpdateError" --type rust

# Check for consistent ChartError usage in batch_update methods
ast-grep --pattern 'fn batch_update_values_step_with($$$) -> impl Future<Output = Result<$_, ChartError>>'

Length of output: 137


Script:

#!/bin/bash
# Let's try a broader search for error types and batch update methods

# Search for UpdateError with more context
rg "UpdateError" --type rust -B 2 -A 2

# Search for ChartError usage
rg "ChartError" --type rust -B 2 -A 2

# Search for batch_update_values_step_with with more context
rg "batch_update_values_step_with" --type rust -B 2 -A 2

# Look for trait definitions containing this method
ast-grep --pattern 'trait $_ {
  $$$
  fn batch_update_values_step_with
  $$$
}'

Length of output: 65752


Script:

#!/bin/bash
# Let's search for the specific trait and implementation details

# Search for trait definition containing batch_update_values_step_with
ast-grep --pattern 'trait BatchStepBehaviour {
  $$$
  fn batch_update_values_step_with
  $$$
}'

# Search for implementations of batch_update_values_step_with
ast-grep --pattern 'impl $_ {
  $$$
  async fn batch_update_values_step_with($$$) -> Result<usize, $_>
  $$$
}'

# Search for any remaining UpdateError usages in the specific file
rg "UpdateError" stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameter_traits.rs

Length of output: 319


Script:

#!/bin/bash
# Let's try a more specific search for the trait and its implementations

# Look for the trait definition with more context
rg "trait BatchStepBehaviour" --type rust -B 2 -A 10

# Look for the specific method signature in the file
rg "batch_update_values_step_with" stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameter_traits.rs -B 2 -A 2

# Look for any implementations
rg "impl.*BatchStepBehaviour" --type rust -B 2 -A 10

Length of output: 6021

stats/stats/src/data_source/kinds/data_manipulation/map/to_string.rs (1)

15-15: LGTM: Error type migration looks correct

The change from UpdateError to ChartError aligns with the broader error handling refactor. The implementation remains functionally equivalent.

Let's verify the error type migration is consistent across the codebase:

Also applies to: 26-26

✅ Verification successful

The previous search for UpdateError returned no results, which is good as it suggests the migration is complete. However, let's verify the ChartError integration and check the file history to ensure the transition was done properly.


Based on the search results, I can now generate the final response. The results show that:

  1. No instances of UpdateError were found in the codebase
  2. ChartError is properly defined and used throughout the codebase
  3. The error type migration appears complete and consistent

LGTM: Error type migration is complete and consistent

The change from UpdateError to ChartError is verified to be complete across the codebase. The search results confirm that ChartError is properly integrated into the error handling system and there are no remaining instances of UpdateError, indicating a successful migration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining UpdateError usage
rg "UpdateError" --type rust

Length of output: 28


Script:

#!/bin/bash
# Let's check the error types in the codebase more thoroughly
# First, let's find ChartError definition and usage
rg "ChartError" --type rust -A 2

# Also check the file history to see the error type transition
git log -p -- stats/stats/src/data_source/kinds/data_manipulation/map/to_string.rs

Length of output: 53675

stats/stats/src/charts/counters/total_accounts.rs (2)

3-4: LGTM: Import changes are appropriate

The addition of StripExt import is necessary for the type modification below.


32-33: Verify data flow with StripExt transformation

The addition of StripExt wrapper introduces a new data transformation step. Please ensure:

  1. The transformation order (StripExt -> LastPoint) is correct
  2. No data loss occurs during the Extended part removal

Let's check the data flow:

✅ Verification successful

Let me gather more information about the StripExt transformation and LastPoint to verify the data flow:


Let me check one more aspect to understand the transformation implementation:


Based on the code analysis, I can now provide the final response:

StripExt transformation is correctly implemented and safe to use

The transformation order (StripExt -> LastPoint) is correct and safe because:

  • StripExt simply converts ExtendedTimespanValue to TimespanValue through a clean .into() transformation
  • No data loss occurs as it's just removing the extended wrapper while preserving the core timespan value
  • LastPoint correctly operates on the stripped TimespanValue type, as evidenced by its DataSource implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check AccountsGrowth implementation and usage
ast-grep --pattern 'impl $_ for AccountsGrowth {
  $$$
}'

# Check for other StripExt usage patterns
rg "StripExt<" --type rust

Length of output: 6643


Script:

#!/bin/bash
# Check StripExt implementation
ast-grep --pattern 'struct StripExtensionFunction {
  $$$
}'

# Check LastPoint implementation
ast-grep --pattern 'struct LastPoint<$_> {
  $$$
}'

# Check Map implementation to understand transformation order
ast-grep --pattern 'impl<$_, $_> $_ for Map<$_, $_> {
  $$$
}'

Length of output: 181


Script:

#!/bin/bash
# Let's try different patterns to find implementations
rg "impl.*StripExtensionFunction" -A 5 --type rust
rg "impl.*LastPoint" -A 5 --type rust
rg "struct StripExtensionFunction" -A 5 --type rust
rg "struct LastPoint" -A 5 --type rust

# Look for the actual transformation functions
rg "fn transform" -A 5 --type rust

Length of output: 3223


Script:

#!/bin/bash
# Look for the actual transformation logic in StripExtensionFunction
rg -A 15 "impl.*MapFunction.*StripExtensionFunction" --type rust

# Check the actual implementation of transform method
rg -A 15 "fn transform.*StripExtensionFunction" --type rust

Length of output: 2663

stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs (3)

8-11: LGTM: Clear documentation of purpose

The documentation clearly explains the rationale for this new functionality.


13-22: LGTM: Vector implementation looks correct

The implementation properly handles the vector case using iterator transformation.


24-33: LGTM: Single value implementation looks correct

The implementation properly handles the single value case.

stats/stats/src/data_source/kinds/local_db/parameters/update/point.rs (3)

27-27: LGTM: Error handling standardization

The transition from UpdateError to ChartError aligns with the codebase-wide standardization of error handling.

Also applies to: 33-33


31-31: LGTM: More precise database connection access

The change to use cx.db.connection.as_ref() provides more precise access to the database connection.


29-29: Verify the impact of using UniversalRange::full()

The change from None to UniversalRange::full() makes the range handling more explicit, but we should verify the performance implications.

✅ Verification successful

Using UniversalRange::full() is the correct approach here

Based on the code analysis:

  • UniversalRange::full() is a standard way to represent an unbounded range in this codebase, with start: None and end: Bound::Unbounded
  • The comment in the file explicitly states "range doesn't make sense there; thus is not used", indicating that the range parameter is not actually used for filtering in this context
  • This is consistent with other similar usages across the codebase, particularly in update operations and tests
  • There are no performance-related comments or concerns around its usage in the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of UniversalRange::full() to understand the pattern
rg -A 3 "UniversalRange::full\(\)" 

# Look for any performance-related comments or tests
rg -l "performance|benchmark" --type rust

Length of output: 9881


Script:

#!/bin/bash
# Let's look for the implementation of UniversalRange::full() to understand its behavior
ast-grep --pattern 'impl $_ for UniversalRange {
  $$$
  fn full() -> Self {
    $$$
  }
  $$$
}'

# Let's also check for any performance-related comments near UniversalRange usage
rg -B 2 -A 2 "UniversalRange::full\(\)" --type rust | grep -B 2 -A 2 -i "perf\|slow\|cost\|heavy"

# Let's check the implementation of query_data to see how it handles the range
ast-grep --pattern 'fn query_data($_) {
  $$$
}'

Length of output: 250


Script:

#!/bin/bash
# Let's look for the UniversalRange struct and its implementation
rg -A 10 "struct UniversalRange" --type rust

# Let's also check the file where UniversalRange is defined to understand its purpose
fd -e rs UniversalRange --exec head -n 50 {}

# Let's check how the range is used in the query context
rg -B 3 -A 3 "query_data.*UniversalRange" --type rust

Length of output: 10189

stats/stats/src/charts/types/timespans/day.rs (2)

40-46: LGTM: Safe arithmetic operations

The implementation of checked_add and checked_sub using Option return types follows Rust best practices for safe arithmetic operations.

Also applies to: 47-52


54-59: LGTM: Bounds implementation

The addition of max and min methods provides clear bounds for the timespan operations.

stats/stats/src/charts/counters/last_new_contracts.rs (2)

3-4: LGTM: Clean import organization

The imports are well-organized and clearly show the new dependency on StripExt.


29-30: Verify StripExt transformation behavior

The addition of StripExt wrapper suggests a change in data transformation strategy. Let's verify its usage pattern.

✅ Verification successful

StripExt transformation is a safe data mapping operation

The StripExt wrapper is a type-safe transformation that converts ExtendedTimespanValue to TimespanValue by dropping the is_approximate field. This is a common pattern used throughout the codebase for various chart data sources, and its implementation is straightforward and well-tested.

  • The transformation is implemented via MapFunction trait which simply maps ExtendedTimespanValue to TimespanValue using .into()
  • It's consistently used across multiple chart types including counters and time series
  • The pattern is applied uniformly for both single values and vectors of values
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of StripExt to understand the pattern
rg -A 3 "StripExt\<" --type rust

# Look for any related tests or documentation
ast-grep --pattern 'impl $_ for StripExt<$_> {
  $$$
}'

Length of output: 177


Script:

#!/bin/bash
# Search for StripExt usage without escape characters
rg "StripExt<" --type rust -A 3

# Look for StripExt definition and implementation
rg "struct StripExt" --type rust -A 5
rg "impl.*StripExt" --type rust -A 5

# Search for test files containing StripExt
fd "test.*\.rs" --type f --exec rg "StripExt" {}

Length of output: 23792


Script:

#!/bin/bash
# Let's look at the StripExtensionFunction implementation to understand its behavior
rg -A 10 "impl.*MapFunction.*StripExtensionFunction" --type rust

# Also check for the ExtendedTimespanValue definition
rg "struct ExtendedTimespanValue" --type rust -A 5

Length of output: 2748

stats/stats/src/data_source/kinds/remote_db/query/one.rs (1)

44-45: LGTM: Improved type safety with UniversalRange

The change from Option<Range<DateTimeUtc>> to UniversalRange<DateTime<Utc>> improves type safety and aligns with the PR's objective of implementing dynamic query dispatch.

stats/stats/src/data_source/kinds/data_manipulation/map/mod.rs (1)

32-32: LGTM: Consistent error and range handling

The changes maintain consistency across the codebase:

  • Unified error handling with ChartError
  • Standardized date range handling with UniversalRange
  • Clean implementation of the mapping functionality

Also applies to: 55-55, 62-64

stats/stats/src/charts/counters/mock.rs (2)

12-14: LGTM: Import changes align with new type system

The addition of UniversalRange and ChartError imports reflects the transition to a more unified error handling and range management system.


34-35: Verify error handling migration completeness

The signature change from Option<Range<DateTimeUtc>> to UniversalRange<DateTime<Utc>> and UpdateError to ChartError is part of a broader refactoring.

✅ Verification successful

Based on the search results, I can now provide a final response:

Migration from Option to UniversalRange and UpdateError to ChartError is complete

The codebase shows a consistent usage of:

  • UniversalRange<DateTime<Utc>> for range parameters
  • ChartError for error handling
  • No remaining instances of UpdateError
  • No remaining instances of Option<Range<DateTimeUtc>>

The migration appears to have been fully completed across all chart implementations and data sources.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify complete migration of error types and range types
# Check for any remaining UpdateError usage
rg "UpdateError" -l

# Check for any inconsistent Range usage
rg "Option<Range<DateTimeUtc>>" -l

Length of output: 56


Script:

#!/bin/bash
# Let's try a broader search for error types and range types
# Search for UpdateError with word boundaries
rg '\bUpdateError\b' -A 2

# Search for different range type patterns
rg 'Range<DateTime' -A 2

# Search for UniversalRange usage
rg 'UniversalRange' -A 2

# Search for ChartError
rg '\bChartError\b' -A 2

Length of output: 68734

stats/stats/src/charts/counters/last_new_verified_contracts.rs (2)

3-4: LGTM: Enhanced data manipulation capabilities

The addition of StripExt from the map module indicates improved data transformation capabilities while maintaining clean architecture.


30-30: Verify StripExt integration impact

The type definition change to use StripExt wrapper is consistent with the broader refactoring pattern.

✅ Verification successful

StripExt integration is consistently used across counter implementations

The search results confirm that StripExt wrapper is consistently used in all counter implementations with LastPoint and DirectPointLocalDbChartSource. This pattern is used in:

  • TotalVerifiedContracts
  • TotalAccounts
  • TotalNativeCoinHolders
  • LastNewContracts
  • LastNewVerifiedContracts

The type definition change is consistent with the broader codebase patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent StripExt usage across counter implementations
# Check for StripExt usage patterns
ast-grep --pattern 'DirectPointLocalDbChartSource<LastPoint<StripExt<$_>>, $_>'

Length of output: 81


Script:

#!/bin/bash
# Let's try a broader search for StripExt usage patterns
rg "StripExt" -A 2 -B 2

# Also search for other LastPoint implementations to compare
rg "LastPoint<" -A 2 -B 2

Length of output: 44424

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/mock.rs (2)

8-8: LGTM: Consistent error handling update

The import change to use ChartError aligns with the project-wide error handling refactoring.


43-43: Verify error propagation in batch operations

The return type change to Result<usize, ChartError> maintains consistent error handling across the batching system.

✅ Verification successful

Error handling is consistent across batch operations

Based on the search results, the return type Result<usize, ChartError> is consistently used across all batch-related operations in the codebase, specifically in:

  • Batch parameter traits (parameter_traits.rs)
  • Batch update implementations (mock.rs, cumulative.rs, mod.rs)
  • Test implementations (tests.rs)

This confirms that the error handling is properly propagated and maintains consistency throughout the batching system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent error handling in batch operations
# Check for consistent Result type usage in batch operations
ast-grep --pattern 'async fn batch_update_values_step_with($_) -> Result<$_, ChartError>'

Length of output: 91


Script:

#!/bin/bash
# Let's try a broader search for batch operations and their error handling
rg "batch.*Result.*ChartError" -A 2

# Also search for similar function signatures
ast-grep --pattern 'fn batch_update_values$_($$$) -> Result<$_, ChartError>'

# Look for any batch-related functions with Result types
rg "fn batch.*-> Result<" -A 2

Length of output: 1609


Script:

#!/bin/bash
# Let's look specifically in the stats directory for batch operations and error handling
rg "batch.*Result" --type rust ./stats -A 2

# Search for ChartError usage in the stats directory
rg "ChartError" --type rust ./stats -A 2

# Look for similar error handling patterns in the same directory
rg "Result<usize, ChartError>" --type rust ./stats

Length of output: 53975

stats/stats/src/data_source/kinds/auxiliary/cumulative.rs (2)

46-48: LGTM: Error handling transition looks correct

The change from UpdateError to ChartError aligns with the project-wide standardization of error handling.


52-55: Verify range handling behavior

The transition to UniversalRange looks good, but we should verify that the cumulative calculation behavior remains consistent with this change.

✅ Verification successful

Based on the code review and the implementation shown, I can now generate the final response:

Range handling behavior verified successfully

The transition to UniversalRange is safe and maintains consistent cumulative calculation behavior. The PartialCumulative data source correctly:

  1. Passes the range unchanged to the underlying delta data source
  2. Applies cumulative calculation using cumsum with a zero initial value
  3. Preserves the temporal ordering of data points
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other cumulative calculations to ensure consistent range handling
ast-grep --pattern 'fn query_data($$$) -> Result<$_, $_> {
  $$$
  cumsum<$_>($_, $_)
  $$$
}'

Length of output: 96


Script:

#!/bin/bash
# Let's try a broader search for cumulative calculations and range handling
rg -U "cumsum|cumulative.*range" -A 5 -B 5

# Also search for the specific file's implementation
cat stats/stats/src/data_source/kinds/auxiliary/cumulative.rs

Length of output: 65674


Script:

#!/bin/bash
# Let's search for the cumulative data source implementation and its tests
fd cumulative -t f -x cat {}

Length of output: 4274

stats/stats/src/data_source/kinds/data_manipulation/map/parse.rs (2)

22-34: LGTM: Error handling transition maintains parsing behavior

The change to ChartError is correctly implemented while preserving the existing error message format and parsing logic.


Line range hint 46-53: LGTM: Consistent error handling implementation

The error handling changes are consistent with the vector implementation above.

stats/stats/src/data_source/kinds/data_manipulation/sum_point.rs (1)

52-55: LGTM: Error handling transition is correct

The change from UpdateError to ChartError is properly implemented.

stats/stats/src/data_source/kinds/data_manipulation/last_point.rs (2)

45-45: LGTM: Error handling transition looks good

The change from UpdateError to ChartError aligns with the project-wide error handling improvements.

Also applies to: 54-54


52-52: Verify range conversion compatibility

The implementation converts the universal range to a specific range using day_start. Please ensure this conversion maintains the intended behavior across all possible range inputs.

Also applies to: 57-57

✅ Verification successful

Let me gather more context about the range conversion implementation.


Let me check the implementation of the range conversion and day_start function.


Range conversion is correctly implemented and safe

The implementation is verified to be correct because:

  1. The day_start function correctly converts a date to UTC midnight timestamp
  2. The range conversion (day_start(&cx.time.date_naive())..cx.time).into() creates a well-defined exclusive range from start of the day to current time
  3. The UniversalRange implementations handle both exclusive and inclusive ranges properly, maintaining range bounds during conversion
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other instances of range conversion to verify consistency
rg -A 2 "day_start.*date_naive.*into" 

Length of output: 352


Script:

#!/bin/bash
# Search for the day_start function implementation
ast-grep --pattern 'fn day_start($_) $_'

# Search for other range conversions in the codebase
rg -A 3 "UniversalRange.*into"

Length of output: 13126


Script:

#!/bin/bash
# Search for the implementation of day_start and range conversion
rg -A 5 "fn day_start|impl.*UniversalRange|impl.*Into.*UniversalRange"

# Look for the specific file's implementation
cat stats/stats/src/data_source/kinds/data_manipulation/last_point.rs

Length of output: 6203

stats/stats/src/charts/counters/total_contracts.rs (1)

26-33: LGTM: Query implementation updated correctly

The error handling transition and range type update have been implemented correctly while maintaining the existing query logic.

stats/config/update_groups.json (1)

7-7: Verify impact of increased update frequency

The update frequency for total_blocks_group has been increased from every 3 hours to every 2 hours. While this provides more frequent updates, please ensure the database can handle the increased load.

Consider implementing monitoring for:

  • Database load during updates
  • Query execution times
  • Resource utilization patterns
✅ Verification successful

Let me gather more specific information about the total blocks metrics and database load handling.


Based on the code analysis, I can now provide a final response:

Schedule change for total_blocks_group is safe to proceed

The codebase implements batch processing with built-in safeguards:

  • Updates are performed in batches with configurable size limits
  • The system includes rate limiting and performance monitoring
  • Database operations are optimized through batching mechanisms

The change from 3 hours to 2 hours is reasonable given these protections are in place.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related performance configurations or metrics
rg -l "total_blocks.*performance|metrics|load"

Length of output: 12135


Script:

#!/bin/bash
# Check metrics and database configurations related to total blocks
rg -A 5 "total_blocks" stats/stats/src/metrics.rs stats/stats/src/data_source/kinds/local_db/mod.rs stats/stats-server/src/settings.rs

# Check if there are any rate limiting or performance configurations
rg -A 5 "rate_limit|batch|performance" stats/stats/src/data_source/kinds/local_db/parameters/update/batching/mod.rs stats/stats-server/src/settings.rs

Length of output: 12317

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/cumulative.rs (1)

40-45: LGTM: Error handling migration looks good

The migration from UpdateError to ChartError is implemented correctly and maintains proper error context in the message construction.

stats/stats/src/data_source/kinds/local_db/parameter_traits.rs (2)

65-68: LGTM: Enhanced query control with new parameters

The addition of points_limit and fill_missing_dates parameters provides better control over query behavior. The change to UniversalRange type is appropriate for standardizing range handling.


48-53: Verify error mapping in update_metadata

The error mapping from DbErr to ChartError looks correct, but we should verify that all possible database errors are properly handled.

✅ Verification successful

The previous search might have failed because the error mapping pattern was too specific. These new searches will help us understand:

  1. All error mappings to ChartError
  2. Where DbErr is used in the codebase
  3. The definition of ChartError to verify the error variants available

I want to verify:

  1. The definition of ChartError to see all possible variants
  2. The context around the error mapping in the specific file to understand what kind of database operations are being performed

Error mapping in update_metadata is correctly implemented

The error mapping from DbErr to ChartError::StatsDB is appropriate and consistent with the codebase for the following reasons:

  1. The ChartError enum has two database-related variants:

    • StatsDB(DbErr) - for stats database errors
    • BlockscoutDB(DbErr) - for blockscout database errors
  2. The update_metadata function is operating on the stats database (as evidenced by the function set_last_updated_at), so mapping to ChartError::StatsDB is the correct choice.

  3. The error mapping pattern is consistent with other similar operations throughout the codebase, where database errors are mapped to the appropriate variant based on which database they originate from.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other DbErr to ChartError mappings to ensure consistency
rg -A 2 "DbErr.*ChartError" 

Length of output: 29


Script:

#!/bin/bash
# Let's try a broader search for error mappings in the same file and related files
rg -A 2 "map_err.*ChartError" 

# Also search for DbErr usage
rg "DbErr" 

# Let's also check the ChartError definition
fd "chart_error" --type f --exec cat {}

Length of output: 41021


Script:

#!/bin/bash
# Let's check the ChartError definition specifically in the stats module
rg -A 5 "pub enum ChartError" stats/

# Let's also check the specific file for context around the error mapping
cat stats/stats/src/data_source/kinds/local_db/parameter_traits.rs

Length of output: 2825

stats/stats/src/data_source/kinds/remote_db/mod.rs (1)

72-76: LGTM: Clean implementation of remote data fetching

The migration to UniversalRange and ChartError is implemented cleanly. The timer usage for performance tracking is maintained appropriately.

stats/stats/src/data_source/kinds/local_db/parameters/update/batching/parameters/mod.rs (1)

11-11: LGTM: Error type migration looks correct

The change from UpdateError to ChartError is consistent with the broader error handling improvements mentioned in the PR objectives. The implementation logic remains unchanged.

Also applies to: 45-45, 59-59

stats/stats/src/charts/counters/yesterday_txns.rs (2)

10-10: LGTM: Import changes align with new type system

The addition of UniversalRange and ChartError imports supports the transition to the new error handling and range parameter system.

Also applies to: 13-13


26-27: LGTM: Error handling improvement

The error message for date validation is now more descriptive and uses the new ChartError type appropriately.

Also applies to: 31-33

stats/stats/src/charts/lines/accounts_growth.rs (2)

6-6: LGTM: Added data manipulation import

The addition of StripExt to the imports is consistent with the new type system for data manipulation.


52-54: Verify the impact of StripExt wrapper on chart resolution conversions

The change to use StripExt in the resolution type hierarchy warrants verification of the data conversion behavior.

Also applies to: 57-59, 63-65

✅ Verification successful

Let me gather more specific information about the resolution conversion implementations.


Let me check the actual implementation of TimespanValue and ExtendedTimespanValue to understand the conversion behavior.


Based on the implementation details found, I can now provide the final response:

StripExt wrapper safely preserves value conversion behavior

The StripExt implementation is a safe transformation that simply drops the is_approximate flag while preserving the core timespan and value data through a straightforward From implementation. The conversion behavior is consistent across all chart resolutions, as it only affects the metadata structure and not the actual data values.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other usages of StripExt to understand the pattern
# and verify consistent implementation

# Find other files using StripExt
echo "Files using StripExt:"
rg "StripExt\s*<" -l

# Look for resolution conversion implementations
echo -e "\nResolution conversion implementations:"
ast-grep --pattern 'impl$_<$_> for $_<$_> {
  $$$
  fn convert($_) -> $_ {
    $$$
  }
}'

Length of output: 1864


Script:

#!/bin/bash
# Check the StripExt implementation and its usage in resolution conversions
echo "StripExt implementation:"
rg -A 10 "impl.*StripExt" 

echo -e "\nResolution conversion related code in data_source:"
rg -A 10 "impl.*Resolution" stats/stats/src/data_source/

echo -e "\nChecking specific file for resolution types:"
cat stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs

Length of output: 32245


Script:

#!/bin/bash
# Check TimespanValue and ExtendedTimespanValue implementations
echo "TimespanValue and ExtendedTimespanValue implementations:"
rg -A 10 "struct (Extended)?TimespanValue"

echo -e "\nConversion implementations between TimespanValue and ExtendedTimespanValue:"
rg -A 10 "impl.*From<Extended.*Value.*>.*for.*Value"

Length of output: 2350

stats/stats/src/charts/lines/verified_contracts_growth.rs (1)

49-51: Verify the impact of StripExt wrapper on data processing

The introduction of StripExt wrapper and intermediate types changes how data is processed through the resolution chain. While this aligns with the PR's objective of implementing dynamic query dispatch, we should ensure the transformation doesn't affect data accuracy.

Also applies to: 56-56, 60-64

✅ Verification successful

StripExt wrapper safely transforms extended timespan values

The StripExt wrapper is a type-safe transformation that simply removes the is_approximate flag from ExtendedTimespanValue, converting it to TimespanValue while preserving the core timespan and value data. This is a safe transformation that doesn't affect data accuracy, as it only drops additional metadata while maintaining the essential time series information.

The implementation shows:

  • Clean conversion from ExtendedTimespanValue<T, V> to TimespanValue<T, V>
  • Preserves both single value and vector transformations
  • No data manipulation of the actual values
  • Type-safe implementation with proper error handling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any potential data transformation issues in the resolution chain

# Look for other StripExt implementations to understand the transformation
ast-grep --pattern 'impl $_ for StripExt<$_> {
    $$$
}'

# Check for any error handling related to StripExt transformations
rg -A 3 'StripExt.*Error'

Length of output: 87


Script:

#!/bin/bash
# Let's try a broader search to understand StripExt usage and implementation

# Find StripExt definition and usage
rg -A 5 "struct StripExt"

# Find where StripExt is imported or used
rg "StripExt"

# Look for any type implementations involving StripExt
rg -A 5 "impl.*StripExt"

# Search for test cases involving StripExt
rg -A 5 "test.*StripExt"

Length of output: 12387


Script:

#!/bin/bash
# Let's examine the StripExtensionFunction implementation and related types

# Look at the full implementation file
cat stats/stats/src/data_source/kinds/data_manipulation/map/strip_extension.rs

# Check TimespanValue and ExtendedTimespanValue definitions
rg -A 10 "struct TimespanValue"
rg -A 10 "struct ExtendedTimespanValue"

Length of output: 2594

stats/stats/src/charts/lines/new_native_coin_holders.rs (1)

55-55: Verify integer parsing behavior with StripExt wrapper

The addition of StripExt wrapper between MapParseTo and the source types could affect how integer values are parsed from the raw data. We should ensure that the parsing chain maintains data integrity.

Also applies to: 66-66

✅ Verification successful

StripExt and MapParseTo integration is safe for integer parsing

Based on the code analysis, the integration is safe and maintains data integrity:

  1. StripExt only removes extension data from ExtendedTimespanValue and converts it to TimespanValue, without modifying the actual value
  2. MapParseTo uses ParseToFunction which safely handles the string-to-integer conversion:
    • Implements proper error handling for parsing failures
    • Uses Rust's built-in FromStr trait for type-safe parsing
    • Maintains the original error context in case of parsing failures

The wrapping of StripExt between MapParseTo and the source types is a safe transformation that won't affect the integer parsing behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the parsing behavior in the codebase

# Look for MapParseTo implementations with StripExt
ast-grep --pattern 'impl $_ for MapParseTo<StripExt<$_>, $_> {
    $$$
}'

# Check for any parsing error handling
rg -A 3 'MapParseTo.*parse'

Length of output: 105


Script:

#!/bin/bash
# Let's try a different approach to verify the parsing behavior

# First, let's find the MapParseTo type definition and implementation
ast-grep --pattern 'struct MapParseTo'

# Look for any direct usage of MapParseTo
rg "MapParseTo"

# Check for StripExt implementation
ast-grep --pattern 'impl $_ for StripExt'

# Look for any parse related functions in the codebase that might be relevant
rg "fn parse.*->.*MapParseTo" -A 3

Length of output: 7908


Script:

#!/bin/bash
# Let's check the implementation details of MapParseTo and StripExt

# Look for the ParseToFunction implementation which is used by MapParseTo
rg -A 10 "ParseToFunction"

# Check the StripExt type and its implementation
rg -A 10 "struct StripExt"
rg -A 10 "impl.*StripExt"

# Look for any tests related to these types
rg -A 5 "test.*MapParseTo"
rg -A 5 "test.*StripExt"

Length of output: 6322

stats/stats/src/data_source/kinds/data_manipulation/delta.rs (2)

55-55: LGTM: Error type alignment with ChartError

The transition from UpdateError to ChartError aligns with the broader error handling strategy across the codebase.


62-71: Verify range adjustment logic for edge cases

The new range handling logic includes a day subtraction and boundary checks. While this improves the handling of cumulative data, we should verify:

  1. The behavior when DateTime::MAX_UTC is used as fallback
  2. Potential edge cases in range boundaries
✅ Verification successful

Let me gather more information about the range handling patterns and edge cases.


Let me search for more context about the error handling and test cases.


Let me search for more specific information about the range handling and MAX_UTC usage.


Based on the code analysis, I can now generate the final response:

Range adjustment logic is safe and well-implemented

The range handling implementation is correct and safe because:

  1. The checked_sub_signed safely handles potential underflow when subtracting one day
  2. Using DateTime::MAX_UTC as fallback is appropriate as it effectively maintains the original range when underflow occurs
  3. The UniversalRange implementation properly handles all range boundary cases including unbounded ranges

The code follows established patterns for range manipulation in the codebase and properly tracks range boundaries through start_is_bounded.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for similar range adjustment patterns and potential issues

# Look for other TimeDelta adjustments
rg -A 3 'checked_sub_signed.*TimeDelta'

# Check for MAX_UTC usage patterns
rg -A 3 'DateTime::MAX_UTC'

# Look for range boundary handling patterns
ast-grep --pattern 'let $_ = $_.start.map(|$_| {
    $$$
})'

Length of output: 556


Script:

#!/bin/bash
# Search for range handling patterns in the delta.rs file
rg -A 10 'UniversalRange.*DateTime' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Look for other instances where range boundaries are modified
rg -A 5 'request_range.start' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Check for error handling related to range boundaries
rg -A 5 'ChartError.*range' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Look for tests related to range handling
rg -A 5 '#\[test\].*range' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

Length of output: 1406


Script:

#!/bin/bash
# Look for the ChartError definition and range-related variants
rg -A 10 'ChartError' --type rust

# Search for test modules in delta.rs
rg -B 5 -A 15 'mod tests' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Check for any range validation or boundary checks
ast-grep --pattern 'if $_.is_some() {
    $$$
}'

# Look for any MAX_UTC or similar constant definitions
rg -A 3 'const.*MAX' --type rust

Length of output: 71020


Script:

#!/bin/bash
# Look for the implementation of UniversalRange and its usage
rg -A 10 'impl.*UniversalRange' stats/stats/src/range.rs

# Search for DateTime::MAX_UTC usage and related constants
rg -A 5 'MAX_UTC' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Check for tests related to range handling in delta.rs
rg -B 5 -A 10 '#\[test\]' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

# Look for other range boundary adjustments
rg -A 5 'request_range.start.*map' stats/stats/src/data_source/kinds/data_manipulation/delta.rs

Length of output: 3944

stats/stats/src/charts/lines/active_accounts.rs (2)

6-6: LGTM: Import and type changes align with best practices

The changes to use DateTime<Utc> from chrono and the addition of QueryAllBlockTimestampRange improve type safety and timestamp handling.

Also applies to: 20-21


70-72: Verify QueryAllBlockTimestampRange integration

The addition of QueryAllBlockTimestampRange to ActiveAccountsRemote type suggests a change in query behavior. Please ensure that all consumers of this type are updated accordingly.

stats/stats-server/tests/it/indexing_status.rs (1)

88-91: LGTM: Improved test assertions for TotalBlocks counter

The test now properly verifies the fallback behavior of the TotalBlocks counter, ensuring it's the only counter present when indexing is not complete. This aligns well with the PR's objective of implementing a fallback mechanism for preliminary block number estimation.

stats/stats/src/data_source/kinds/data_manipulation/resolutions/last_value.rs (3)

26-26: LGTM: Addition of Ord trait constraint is appropriate

The addition of the Ord trait constraint for LowerRes is well-justified as it ensures proper ordering when selecting the last value within a timespan.


48-48: LGTM: Error type change aligns with codebase-wide refactor

The transition from UpdateError to ChartError is part of a consistent error handling strategy across the codebase.


55-60: LGTM: Enhanced range handling with UniversalRange

The transition to UniversalRange and the updated range handling logic improves the flexibility of the query system while maintaining proper timespan boundary handling.

stats/stats-server/src/update_service.rs (1)

15-16: LGTM: Consistent use of MarkedDbConnection

The transition to MarkedDbConnection improves the connection handling architecture and maintains proper error handling for blockscout migrations detection.

Also applies to: 32-33, 110-115

stats/stats/src/charts/lines/average_block_size.rs (2)

36-36: LGTM: Improved DateTime handling and type safety

The explicit use of DateTime<Utc> and the updated remote database source type improve type safety and clarity.

Also applies to: 56-58


87-106: LGTM: Well-structured type definitions with StripExt

The introduction of StripExt and the reorganized type definitions for different time resolutions provide a clean and type-safe approach to handling block size calculations.

stats/stats/src/data_source/kinds/data_manipulation/resolutions/sum.rs (3)

27-27: LGTM: Addition of Ord trait bound is appropriate

The addition of the Ord trait bound to LowerRes enhances type safety by ensuring that timespan values can be properly ordered.


135-137: LGTM: Test database connection setup updated correctly

The test setup has been properly updated to use MarkedDbConnection with in-memory SQLite, which is appropriate for testing.


49-49: Verify the impact of error type and range parameter changes

The changes to error handling and range parameter types look good, but let's verify there are no unhandled edge cases in the range conversion.

Also applies to: 56-61

✅ Verification successful

Based on the search results, I can see that the UniversalRange type is a core abstraction for handling date ranges in the codebase, with robust error handling through ChartError. The implementation shows proper handling of range conversions with backup bounds, inclusive/exclusive range handling, and appropriate error propagation.

Looking at the update_itself implementations across various data sources, they all follow a consistent pattern of proper error handling using Result<(), ChartError>. The function in question is part of this pattern, and the changes to error type and range parameter appear to be consistent with the rest of the codebase.

No issues found with error handling or range parameter changes

The changes align with the established patterns in the codebase for handling ranges and errors. The error type ChartError is consistently used across all data sources, and UniversalRange provides robust range conversion capabilities with proper error handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential error handling patterns that might need updating
rg -A 3 "UniversalRange::.*into\(\)" 
rg -A 3 "ChartError::from\("

Length of output: 69


Script:

#!/bin/bash
# Let's search for error handling patterns and range conversions more broadly
rg -A 3 "UniversalRange"
rg -A 3 "ChartError"

# Also search for the update_itself implementation
ast-grep --pattern 'async fn update_itself($_) -> Result<$_, $_> { $$$ }'

Length of output: 66792

stats/stats/src/charts/lines/average_block_rewards.rs (2)

59-61: LGTM: Type alias updates maintain consistency

The updates to type aliases correctly implement the new type system changes while maintaining backward compatibility.

Also applies to: 95-96, 102-103, 111-114


Line range hint 38-57: Verify SQL query performance with new range type

The SQL query implementation looks correct with the new range type. However, let's verify the index usage for the timestamp filtering.

✅ Verification successful

SQL query performance is well-supported by existing indexes

The query's timestamp filtering is properly supported by the blocks_timestamp_index on blocks.timestamp column, and there's also a composite index blocks_date on date(timestamp) which helps with the GROUP BY clause. The query should perform efficiently with these indexes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for index definitions on timestamp column
rg -A 5 "CREATE.*INDEX.*timestamp" 
# Check if there are any other queries using similar timestamp filtering
ast-grep --pattern 'sql_with_range_filter_opt!($_, $_, $body, $_, "blocks.timestamp", $_)'

Length of output: 1560

stats/stats-server/src/server.rs (2)

82-84: LGTM: Database connections properly initialized with markers

The use of MarkedDbConnection::main_connection improves connection tracking and type safety.

Also applies to: 94-96


142-143: Verify service initialization with both connections

The ReadService now correctly uses both database connections. Let's verify the connection usage patterns.

✅ Verification successful

Let me gather more information about the ReadService implementation to verify the connection usage patterns.


Both database connections are properly initialized and used in ReadService

The verification shows that:

  • ReadService correctly accepts and stores both db and blockscout connections in its constructor
  • Both connections are properly used in the service implementation, particularly in the query_with_handle method where:
    • blockscout connection is used to query migrations
    • Both connections are passed to the UpdateContext for data querying
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential connection usage patterns
ast-grep --pattern 'ReadService::new($_, $_, $_, $_)'
rg -A 3 "MarkedDbConnection::main_connection"

Length of output: 763


Script:

#!/bin/bash
# Check ReadService implementation and its database usage
ast-grep --pattern 'impl ReadService'
rg -A 5 "struct ReadService"

Length of output: 6075

stats/stats/src/charts/lines/new_txns.rs (2)

Line range hint 4-29: LGTM! Import changes align with the PR objectives.

The additions of QueryAllBlockTimestampRange and StripExt support the dynamic query dispatch feature, while the explicit DateTime<Utc> improves type safety.


Line range hint 107-118: LGTM! Type definitions and test coverage are well-structured.

The addition of StripExt wrapper improves type safety while maintaining comprehensive test coverage across different time resolutions.

stats/stats/src/charts/lines/txns_success_rate.rs (2)

118-134: LGTM! Type hierarchy maintains proper relationships.

The addition of StripExt and the type hierarchy for different time resolutions (daily, weekly, monthly, yearly) is well-structured and maintains proper relationships for average calculations.


Line range hint 37-83: Verify handling of edge case: zero transactions.

The SQL query performs float division without checking for zero denominator. While PostgreSQL handles this gracefully by returning NULL, consider adding explicit handling:

-COUNT(CASE WHEN t.error IS NULL THEN 1 END)::FLOAT / COUNT(*)::FLOAT as value
+CASE 
+  WHEN COUNT(*) = 0 THEN 0
+  ELSE COUNT(CASE WHEN t.error IS NULL THEN 1 END)::FLOAT / COUNT(*)::FLOAT 
+END as value
stats/stats/src/data_source/kinds/data_manipulation/filter_deducible.rs (2)

48-57: LGTM! Error handling improvements align with project standards.

The transition from UpdateError to ChartError and the use of UniversalRange improve error handling and range management while maintaining proper error propagation.


Line range hint 159-195: LGTM! Test improvements enhance reliability.

The changes to use MarkedDbConnection and UniversalRange::full() improve test isolation while maintaining comprehensive coverage of different fill policies.

stats/stats/src/charts/counters/average_block_time.rs (3)

55-55: LGTM: Error handling improvements

The transition from UpdateError to ChartError enhances error specificity and aligns with the broader error handling refactoring.

Also applies to: 60-60


71-72: LGTM: Improved date range handling and error reporting

The transition to UniversalRange provides more flexible date range handling, and the error message is clear and descriptive.

Also applies to: 77-79


201-202: LGTM: Test adaptations

Test changes correctly reflect the new database connection handling approach using MarkedDbConnection.

stats/stats/src/data_processing.rs (1)

20-20: LGTM: Consistent error handling updates

The transition to ChartError in data processing functions maintains consistency with the codebase-wide error handling improvements.

Also applies to: 43-43, 64-64

stats/stats/src/data_source/source.rs (3)

119-119: LGTM: DataSource trait improvements

The updates to error handling and date range types in the DataSource trait are consistent with the project's migration goals.

Also applies to: 149-150, 165-167


199-199: LGTM: Base case implementation updates

The base case implementation for the unit type correctly reflects the trait changes while maintaining the same behavior.

Also applies to: 204-204, 210-212


236-236: LGTM: Tuple implementation adaptations

The tuple implementation correctly adapts to the trait changes while preserving the original functionality.

Also applies to: 243-243, 251-253

stats/stats/src/charts/lines/native_coin_holders_growth.rs (1)

Line range hint 8-24: LGTM! Import changes align with the new error handling strategy.

The addition of StripExt and reorganization of imports properly support the transition to the new error handling approach using ChartError.

stats/stats/src/charts/types/timespans/week.rs Outdated Show resolved Hide resolved
stats/stats/src/charts/types/timespans/week.rs Outdated Show resolved Hide resolved
stats/stats/src/charts/types/timespans/month.rs Outdated Show resolved Hide resolved
stats/stats/src/charts/types/timespans/month.rs Outdated Show resolved Hide resolved
stats/stats-server/src/read_service.rs Show resolved Hide resolved
stats/stats/src/charts/types/timespans/year.rs Outdated Show resolved Hide resolved
stats/stats/src/charts/types/timespans/year.rs Outdated Show resolved Hide resolved
stats/stats/src/charts/db_interaction/read.rs Show resolved Hide resolved
stats/stats/Cargo.toml Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
stats/stats/src/charts/types/timespans/year.rs (2)

106-130: Consider extracting common logic to reduce duplication.

Both checked_add and checked_sub share similar validation and result construction logic. Consider extracting this into a private helper method.

+ fn checked_year_operation(
+     current: i32,
+     duration: TimespanDuration<Self>,
+     op: impl FnOnce(i32, i32) -> Option<i32>,
+ ) -> Option<Self> {
+     let years: i32 = duration.repeats().try_into().ok()?;
+     let new_year_num = op(current, years)?;
+     if Self::year_number_within_naive_date(new_year_num) {
+         Some(Self(new_year_num))
+     } else {
+         None
+     }
+ }

  fn checked_add(&self, duration: TimespanDuration<Self>) -> Option<Self>
  where
      Self: Sized,
  {
-     let add_years = duration.repeats().try_into().ok()?;
-     let new_year_num = self.number_within_naive_date().checked_add(add_years)?;
-     if Self::year_number_within_naive_date(new_year_num) {
-         Some(Self(new_year_num))
-     } else {
-         None
-     }
+     Self::checked_year_operation(
+         self.number_within_naive_date(),
+         duration,
+         |a, b| a.checked_add(b),
+     )
  }

  fn checked_sub(&self, duration: TimespanDuration<Self>) -> Option<Self>
  where
      Self: Sized,
  {
-     let sub_years: i32 = duration.repeats().try_into().ok()?;
-     let new_year_num = self.number_within_naive_date().checked_sub(sub_years)?;
-     if Self::year_number_within_naive_date(new_year_num) {
-         Some(Self(new_year_num))
-     } else {
-         None
-     }
+     Self::checked_year_operation(
+         self.number_within_naive_date(),
+         duration,
+         |a, b| a.checked_sub(b),
+     )
  }

295-341: Consider adding tests for negative duration values.

The test coverage is good, but could be enhanced by adding test cases for negative duration values to ensure proper handling of these edge cases.

#[test]
fn year_checked_operations_with_negative_values() {
    // These should compile-fail as TimespanDuration is unsigned
    // but good to document this behavior
    assert_eq!(
        Year(2016).checked_add(TimespanDuration::from_timespan_repeats(-1)),
        None
    );
    assert_eq!(
        Year(2016).checked_sub(TimespanDuration::from_timespan_repeats(-1)),
        None
    );
}
stats/stats/src/charts/types/timespans/week.rs (1)

111-116: Consider adding documentation for max/min methods

While the implementation is correct, these methods would benefit from documentation explaining their purpose and relationship to NaiveDate bounds, especially since they're used in saturating operations.

Consider adding documentation like this:

+    /// Returns the maximum possible week, corresponding to the week containing NaiveDate::MAX
     fn max() -> Self {
         Self::from_date(NaiveDate::MAX)
     }

+    /// Returns the minimum possible week, corresponding to the week containing NaiveDate::MIN
     fn min() -> Self {
         Self::from_date(NaiveDate::MIN)
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bdd688c and ea2aab0.

📒 Files selected for processing (3)
  • stats/stats/src/charts/types/timespans/month.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/week.rs (1 hunks)
  • stats/stats/src/charts/types/timespans/year.rs (3 hunks)
🔇 Additional comments (7)
stats/stats/src/charts/types/timespans/year.rs (3)

58-60: LGTM! Well-designed helper method.

The method provides a clean and efficient way to validate year numbers within the NaiveDate range.


63-69: LGTM! Clean implementation of clamping logic.

The method effectively uses the new helper to validate and clamp year values to valid ranges.


132-138: LGTM! Clear and correct boundary implementations.

The max and min methods correctly define the boundaries using NaiveDate constants.

stats/stats/src/charts/types/timespans/month.rs (2)

80-83: LGTM! Safer duration conversion handling

The duration conversion now properly handles potential overflow using try_into().ok()? instead of unwrap_or(u32::MAX).


96-101: LGTM! Well-implemented boundary methods

The max and min methods provide a clean and consistent way to obtain boundary values for the Month type.

stats/stats/src/charts/types/timespans/week.rs (2)

101-109: LGTM! Consistent overflow protection implementation

The implementation mirrors the safety improvements in checked_add, using checked_mul for overflow protection and properly chaining Option results.


91-98: LGTM! Overflow protection properly implemented

The implementation correctly handles potential integer overflow using checked_mul and properly chains Option results. This addresses the previous overflow concerns raised in past reviews.

Let's verify the overflow handling:

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
stats/stats/src/charts/types/timespans/month.rs (1)

Line range hint 223-287: Consider reorganizing arithmetic tests for clarity.

The test function month_arithmetics_works combines tests for both saturating and checked operations. Consider splitting these into separate test functions for better organization and clarity:

  • test_month_saturating_arithmetic
  • test_month_checked_arithmetic
-#[test]
-fn month_arithmetics_works() {
+#[test]
+fn test_month_saturating_arithmetic() {
     assert_eq!(
         Month::from_date(d("2015-06-01"))
             .saturating_add(TimespanDuration::from_timespan_repeats(3)),
         Month::from_date(d("2015-09-01"))
     );
     // ... other saturating tests
+}
+
+#[test]
+fn test_month_checked_arithmetic() {
     assert_eq!(
         Month::from_date(d("2015-06-01"))
             .checked_add(TimespanDuration::from_timespan_repeats(3)),
         Some(Month::from_date(d("2015-09-01")))
     );
     // ... other checked tests
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ea2aab0 and 1ee211c.

📒 Files selected for processing (1)
  • stats/stats/src/charts/types/timespans/month.rs (5 hunks)
🔇 Additional comments (3)
stats/stats/src/charts/types/timespans/month.rs (3)

86-94: LGTM! Safe implementation of checked subtraction.

The implementation mirrors checked_add and properly addresses the previous data loss concern by safely handling the duration conversion.


96-101: LGTM! Clear and consistent implementation of bounds.

The max and min implementations properly utilize NaiveDate bounds and maintain consistency with the Month type's semantics.


76-83: LGTM! Safe implementation of checked addition.

The implementation correctly handles:

  • Safe conversion from u64 to u32 using try_into().ok()?
  • Proper overflow handling using checked_add_months
  • Type-safe result mapping

Let's verify the behavior with edge cases:

✅ Verification successful

Let me analyze the findings from the rg search:

  1. The trait definition in charts/types/traits.rs shows checked_add is part of a trait interface
  2. There's a usage in traits.rs where checked_add is used within saturating_add with proper unwrap_or_else(|| Self::max())
  3. The implementation exists in multiple timespan types (month.rs, week.rs, day.rs, year.rs)
  4. Test cases in month.rs and year.rs show proper handling of edge cases including overflow scenarios
  5. Usage in range.rs shows direct calls to checked_add

Let me verify the range.rs usage to ensure it properly handles the None case:


Implementation of checked_add is safe and properly used throughout the codebase

The verification confirms:

  • The trait implementation in Month correctly handles overflow cases
  • All callers properly handle the None case:
    • Used within saturating_add with fallback to max()
    • Used in checked_inc which propagates the Option
    • Test cases verify edge cases including overflow scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any direct usage of checked_add to ensure callers handle None case
rg -A 2 "checked_add\(" --type rust

Length of output: 4235


Script:

#!/bin/bash
# Check the context of checked_add usage in range.rs
rg -B 5 -A 5 "checked_add\(" stats/stats/src/range.rs

Length of output: 516

@bragov4ik bragov4ik merged commit 2be4467 into main Dec 11, 2024
6 checks passed
@bragov4ik bragov4ik deleted the bragov4ik/stats-dynamic-query-dispatch branch December 11, 2024 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants