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

Initial FastNear indexer integration #321

Merged
merged 41 commits into from
Nov 30, 2024

Conversation

Fly-Style
Copy link
Contributor

@Fly-Style Fly-Style commented Nov 22, 2024

  • New Features

    • Integrated FastNear indexer into main NFFL codebase. It works with manual tests, both the integration test and docker-compose test are in progress due to complexities with nearcore setup in docker-compose environment and will be shipped as separate PR (NFFL FastNear indexer: CI test #322)
  • Improvements

    • Enhanced error handling with new error variants for better diagnostics.
    • Updated Docker and workflow configurations for improved efficiency and clarity.
  • Bug Fixes

    • Corrected service name typos in Docker configurations.
    • Adjusted health check parameters for better reliability.

This change is Reviewable

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new FastNearIndexer for enhanced interaction with the NEAR blockchain.
    • Added support for a new configuration option channel_width in command-line arguments.
    • Added a step for Fastnear integration tests in the GitHub Actions workflow.
  • Improvements

    • Updated Docker workflows to streamline testing processes for contracts and documentation.
    • Enhanced error handling and logging capabilities within the indexing logic.
    • Updated the reqwest dependency to version 0.12.9 with the json feature.
    • Modified health check parameters for improved service monitoring.
    • Simplified the configuration by removing unused constants in the test setup.
    • Adjusted the workflow to trigger only on relevant file changes for contract tests and documentation.
  • Bug Fixes

    • Corrected service name from agreator-health to aggregator-health in Docker configurations.
    • Extended sleep duration in integration tests to ensure reliable execution.
  • Documentation

    • Updated README to include instructions for running the indexer in FastNear mode.

Copy link
Contributor

coderabbitai bot commented Nov 22, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request implements multiple updates across various workflow files and configuration settings. Key changes include modifications to GitHub Actions workflows to refine trigger conditions based on file paths, updates to Docker configurations, and enhancements to Rust dependency management. New structs and error types are introduced in the Rust codebase, alongside adjustments to existing functions to improve error handling and logging. The changes aim to streamline the build and testing processes while correcting inconsistencies in naming and configurations.

Changes

File Change Summary
.github/workflows/compose-test.yml Updated Docker Compose workflow; added build arguments, modified sleep duration, and corrected container names for consistency.
.github/workflows/contracts-tests.yml Added paths filter to pull_request trigger to limit workflow execution to specific directories.
.github/workflows/docs-test.yml Added paths filter to pull_request trigger to restrict workflow execution to changes in the docs/** directory.
.github/workflows/unit-tests.yml Added path filters for pull requests; updated rust_test job command to suppress warnings about dead code.
Cargo.toml Updated reqwest dependency version from 0.12.8 to 0.12.9 with json feature; no other dependency changes.
Makefile Added new Docker build targets; modified existing commands for efficiency; commented out a test target.
docker-compose.yml Added new network configuration; corrected service name from agreator-health to aggregator-health; refined health check parameters for rollup1-anvil.
indexer/Cargo.toml Updated multiple dependencies and added a new feature use_fastnear.
indexer/Dockerfile Updated Rust version and introduced build arguments for more flexible compilation.
indexer/FastIndexer.dockerfile Introduced a new Dockerfile for the FastNearIndexer application with a two-stage build process.
indexer/README.md Added a section on "FastNear Mode" with usage instructions.
indexer/src/block_listener.rs Introduced new struct TransactionWithRollupId and enhanced methods for transaction processing and logging.
indexer/src/errors.rs Added new error variants to the Error enum for improved error handling.
indexer/src/fastnear_indexer.rs Introduced FastNearIndexer struct with methods for interacting with the NEAR blockchain.
indexer/src/main.rs Refactored run function to conditionally use FastNearIndexer based on feature flags; updated error handling and logging.
indexer/src/metrics.rs Changed INDEXER_NAMESPACE constant from private to public and updated its value.
indexer/src/types.rs Added multiple new structs and an enum to enhance functionality related to candidate data and block processing.
indexer/test_data/config/example.yaml Updated the comment format for the max_gas_burnt_view parameter.
rust-toolchain.toml Updated Rust toolchain version from 1.81.0 to 1.82.0.
tests/e2e/e2e_tests/tests/containers.rs Removed unused constant declaration for NEAR_KEYS.
tests/e2e/e2e_tests/tests/ctr_availability_test.rs Added #[allow(unused_imports)] directives for clarity regarding unused imports.
tests/integration/integration_test.go Adjusted sleep duration in TestIntegration function from 50 seconds to 60 seconds.

Possibly related PRs

  • Add initial documentation #1: The changes in the main PR involve updates to the Docker Compose workflow configuration, which may relate to the overall deployment and testing processes that could be impacted by the changes in the Cargo.toml file in this PR.
  • Add NEAR DA indexer #8: The modifications in the main PR regarding Docker Compose workflows could be relevant to the basic zk relayer's setup and testing, as both involve containerized environments.
  • Improve and add deployment scripts #70: The changes in the main PR regarding workflow configurations may relate to the integration of the ndkg/idkg functionalities, as both involve adjustments to the deployment and testing processes.
  • Remove labels from images #78: The main PR's updates to the workflow configurations could be relevant to the xvault-send feature, as both involve enhancements to the testing and deployment processes.
  • Install ca-certificates in debian images #85: The changes in the main PR regarding workflow configurations may relate to the router-sdk's integration, as both involve adjustments to the testing and deployment processes.
  • Submit block headers only to NEAR DA #86: The main PR's updates to workflow configurations could be relevant to the remote staking feature, as both involve enhancements to the testing and deployment processes.
  • Add chain info to deployments #87: The changes in the main PR regarding workflow configurations may relate to the tidy-up of PR comments, as both involve improvements to the overall project structure and testing processes.
  • LayerZero: Executor #305: The changes in the main PR regarding workflow configurations could be relevant to the Executor's implementation, as both involve enhancements to the testing and deployment processes.
  • Setup Rust unit tests #308: The main PR's updates to workflow configurations may relate to the setup of Rust unit tests, as both involve improvements to the testing framework.
  • Update unit-tests.yml #311: The changes in the main PR regarding workflow configurations could be relevant to the updates made to the unit-tests.yml file, as both involve adjustments to the testing processes.
  • Wrap basic services with testcontainers-rs for further usage in it tests #318: The main PR's updates to workflow configurations may relate to the introduction of testcontainers for further usage in integration tests, as both involve enhancements to the testing framework.

Suggested labels

enhancement

Suggested reviewers

  • palozano
  • firatsertgoz

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b5ecb80 and 4e711fa.

📒 Files selected for processing (1)
  • .github/workflows/integration-tests.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/integration-tests.yml

🪧 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 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.

@Fly-Style Fly-Style changed the title FastNEAR indexer, by @firatsertgoz Initial FastNear indexer integration Nov 28, 2024
@Fly-Style Fly-Style marked this pull request as ready for review November 28, 2024 13:26
Copy link
Contributor

@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: 45

🧹 Outside diff range and nitpick comments (38)
.github/workflows/docs-test.yml (1)

Line range hint 1-24: Workflow requires essential improvements

Critical deficiencies identified in the workflow configuration:

  1. No explicit error handling or reporting
  2. No validation of generated documentation
  3. No artifact retention for failed builds

Apply these improvements:

 name: Test deployment
 
 on:
   pull_request:
     branches:
       - main
     paths:
       - 'docs/**'
 
 jobs:
   test-deploy:
     name: Test docs deployment
     runs-on: ubuntu-latest
+    continue-on-error: false
     steps:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - uses: actions/setup-node@v4
         with:
             node-version: 18
             cache: npm
             cache-dependency-path: docs
 
       - name: Install dependencies
         run: npm ci 
         working-directory: docs
+
       - name: Test build website
         run: npm run build
         working-directory: docs
+
+      - name: Validate generated documentation
+        run: |
+          if [ ! -f "build/index.html" ]; then
+            echo "Error: Documentation build failed - index.html not found"
+            exit 1
+          fi
+        working-directory: docs
+
+      - name: Upload documentation artifact
+        if: failure()
+        uses: actions/upload-artifact@v3
+        with:
+          name: docs-build
+          path: docs/build/
+          retention-days: 5
.github/workflows/contracts-tests.yml (2)

Line range hint 16-16: 5-minute timeout is dangerously optimistic

A 5-minute timeout for contract tests is inadequate. Complex contracts or large test suites could easily exceed this limit, especially when running with maximum verbosity (-vvv).

Recommend increasing to at least 15 minutes:

-    timeout-minutes: 5
+    timeout-minutes: 15

Line range hint 31-33: Using Foundry nightly is a reliability risk

Nightly builds can introduce unexpected breaking changes. Pin to a specific version for reproducible builds.

-          version: nightly
+          version: 0.2.0 # or another stable version
indexer/FastIndexer.dockerfile (2)

45-45: Entrypoint lacks explicit shell specification

The entrypoint should explicitly specify the shell to ensure consistent behaviour across different environments.

-ENTRYPOINT [ "./entrypoint.sh" ]
+ENTRYPOINT [ "/bin/sh", "./entrypoint.sh" ]

1-45: Missing crucial security configurations

The Dockerfile lacks several security best practices that are essential for production deployments.

Add the following security configurations:

  1. Create and use a non-root user
  2. Set appropriate file permissions
  3. Configure security options
+# In runtime stage after installing dependencies
+RUN groupadd -r indexer && \
+    useradd -r -g indexer -s /bin/false indexer && \
+    chown -R indexer:indexer /indexer-app
+
+USER indexer
+
+# Add security options
+SECURITY_OPTS --security-opt=no-new-privileges:true \
+             --cap-drop=ALL
indexer/README.md (1)

26-36: Consider architectural resilience.

The tight coupling with FastNear service introduces a single point of failure. Consider implementing:

  1. Fallback mechanism to standard NEAR RPC endpoints
  2. Circuit breaker pattern for graceful degradation
  3. Health check endpoints for monitoring FastNear availability

Would you like assistance in implementing these resilience patterns?

🧰 Tools
🪛 LanguageTool

[uncategorized] ~34-~34: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ...fetch NEAR blocks more efficiently. The --features use_fastnear flag enables the FastNEAR...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)

🪛 Markdownlint (0.35.0)

31-31: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)

indexer/Dockerfile (1)

22-24: Remove unprofessional commentary and document the caching strategy properly

The term "hacky" is unprofessional. This is a legitimate Docker layer caching strategy that deserves proper documentation.

Replace with:

-# Hacky approach to cache dependencies
+# Pre-build dependencies for layer caching
+# Create a dummy main.rs to compile dependencies without application code
indexer/Cargo.toml (1)

43-44: Document the feature flag purpose

The use_fastnear feature flag lacks documentation explaining its purpose and impact.

Add a comment explaining when this feature should be enabled:

 [features]
+ # Enable this feature to use the FastNear indexer implementation
 use_fastnear = []
tests/e2e/e2e_tests/tests/ctr_availability_test.rs (5)

Line range hint 18-23: Empty expect messages are unacceptable.

The empty expect message expect("") provides zero context for test failures. This is a critical oversight in error handling.

-    rabbitmq.start().await.expect("");
+    rabbitmq.start().await.expect("Failed to start RabbitMQ container - ensure Docker daemon is running and port is available");

Line range hint 18-85: Missing container health checks.

Starting containers without health checks is insufficient. Each container should verify its readiness before the test proceeds.

Example implementation for RabbitMQ:

async fn check_rabbitmq_available() {
    let rabbitmq = rabbitmq();
    let container = rabbitmq.start().await.expect("Failed to start RabbitMQ container");
    
    // Add health check
    let health_check = async {
        let mut attempts = 0;
        while attempts < 30 {
            if let Ok(_) = container.check_health().await {
                return Ok(());
            }
            tokio::time::sleep(Duration::from_secs(1)).await;
            attempts += 1;
        }
        Err("Container failed health check")
    };
    
    health_check.await.expect("RabbitMQ failed to become healthy");
}

Line range hint 1-85: Missing cleanup verification.

While the file comments mention automatic cleanup, there's no verification that containers are actually removed after tests, especially after failures.

Add a cleanup verification helper:

async fn verify_cleanup(container_name: &str) {
    let docker = bollard::Docker::connect_with_local_defaults()
        .expect("Failed to connect to Docker daemon");
    
    let filters = HashMap::from([
        ("name", vec![container_name])
    ]);
    
    let containers = docker.list_containers(Some(ListContainersOptions {
        filters,
        ..Default::default()
    }))
    .await
    .expect("Failed to list containers");
    
    assert!(containers.is_empty(), "Container {} was not cleaned up", container_name);
}

Hardcoded relative path requires immediate correction

The file exists at config-files/operator1-docker-compose.anvil.yaml, confirming that the current relative path ../../../config-files/operator1-docker-compose.anvil.yaml is unnecessarily complex and brittle. This should be replaced with a path relative to the workspace root or use environment variables/configuration to specify the path.

  • Replace "../../../config-files/operator1-docker-compose.anvil.yaml" with "config-files/operator1-docker-compose.anvil.yaml" or implement a more robust path resolution mechanism.
🔗 Analysis chain

Line range hint 77-82: Hardcoded config path is brittle.

The operator test uses a hardcoded relative path "../../../config-files/operator1-docker-compose.anvil.yaml". This is fragile and will break if the test file moves.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence and usage of the config file
fd operator1-docker-compose.anvil.yaml

Length of output: 89


Port 8546 is used without availability checks, posing a reliability risk.

The codebase directly uses port 8546 for the Anvil rollup node without first verifying its availability. This oversight can lead to silent failures when:

  • Another process is already using port 8546
  • The port is blocked by firewall rules
  • The port is reserved by the system

Required actions:

  • Implement port availability check before starting the rollup node
  • Add fallback logic to find an available port if 8546 is occupied
  • Add proper error handling and user feedback when port binding fails
🔗 Analysis chain

Line range hint 39-44: Hardcoded ports require validation.

Port 8546 is hardcoded without any port availability check. This will fail silently if the port is in use.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if critical ports are defined elsewhere in the codebase
rg -g '!target/' '8546|3030' .

Length of output: 116977


Script:

#!/bin/bash
# Check if port availability is checked before using port 8546
rg -A 2 "8546" . --type rust

Length of output: 810


Script:

#!/bin/bash
# Search for port availability checks in the codebase
rg -B 2 -A 2 "is_available|check.*port|port.*check|TcpListener::bind" .

Length of output: 1307


Script:

#!/bin/bash
# Check the implementation of anvil_rollup_node to see if there's any port availability check
rg -A 10 "fn anvil_rollup_node" .

Length of output: 899

.github/workflows/compose-test.yml (1)

131-131: Add newline at end of file

The file is missing a newline character at the end, which is a YAML best practice.

   run: docker-compose -f ./docker-compose.yml down
+
🧰 Tools
🪛 yamllint (1.35.1)

[error] 131-131: no new line character at the end of file

(new-line-at-end-of-file)

docker-compose.yml (4)

Line range hint 239-350: CRITICAL: Exposed credentials in plain text

Multiple security vulnerabilities detected:

  1. Hard-coded ECDSA private key in aggregator service
  2. Plain text BLS and ECDSA key passwords in operator services
  3. Admin credentials in Grafana configuration

These credentials must be moved to a secure secrets management solution.

Implement one of these solutions:

  1. Docker secrets
  2. Environment file with proper access controls
  3. External secrets management service (HashiCorp Vault, AWS Secrets Manager)

Line range hint 239-350: Standardise service dependency conditions

Inconsistent dependency conditions detected:

  • operator1 depends on operator0-health (health check)
  • operator0 depends on aggregator (service_started)
  • indexer depends on multiple services with different conditions

This inconsistency could lead to race conditions and unreliable service startup.

Standardise to use health checks consistently:

  operator0:
    depends_on:
      aggregator:
-       condition: service_started
+       condition: service_healthy

Line range hint 1-7: Implement network segmentation

Current configuration places all services on a single bridge network, violating the principle of least privilege. Services should be grouped into separate networks based on their communication requirements.

Consider implementing:

  1. Frontend network for Grafana
  2. Metrics network for Prometheus
  3. Backend network for core services
  4. Database network for persistent storage

Health check configurations require standardisation with clear justification for deviations

The verification confirms inconsistent health check configurations across services:

  • Most services: 15s interval, 10s timeout
  • RabbitMQ: 1s interval, 3s timeout
  • One service (port 8547): 2s interval, 30s timeout

These variations lack clear justification and could lead to inconsistent monitoring behaviour. The RabbitMQ configuration might be justified due to its critical message broker role, but the service on port 8547 requires explanation for its extended timeout.

🔗 Analysis chain

Line range hint 239-248: Standardise health check configurations across services

The health check configuration for the aggregator-health service differs from the established pattern seen in other services. Most services use a 15s interval and 10s timeout, while rollup1-anvil inexplicably uses 2s interval and 30s timeout. This inconsistency requires justification.

Run this script to verify health check configurations across services:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Extract and compare health check configurations
rg -A 3 'healthcheck:' docker-compose.yml

Length of output: 839

tests/integration/integration_test.go (1)

Line range hint 1-999: Test structure needs improvement

The test file has several structural issues that make it hard to maintain and understand:

  1. The test is monolithic with multiple responsibilities
  2. Setup code is complex and mixed with test logic
  3. Cleanup is not guaranteed in case of panics
  4. Magic numbers and constants are scattered throughout

Consider these improvements:

  1. Break down the test into smaller, focused test cases
  2. Move setup code to a separate test fixture package
  3. Use defer for cleanup operations
  4. Extract configuration constants to a dedicated constants file
  5. Add proper test documentation explaining the test scenarios

Example structure:

type TestFixture struct {
    mainnetAnvil     *utils.AnvilInstance
    rollupAnvils     []*utils.AnvilInstance
    rabbitMq         *rabbitmq.RabbitMQContainer
    // ... other fields
}

func NewTestFixture(t *testing.T) *TestFixture {
    // Setup code here
}

func (f *TestFixture) Cleanup(t *testing.T) {
    // Cleanup code here
}

func TestOperatorSetUpdate(t *testing.T) {
    fixture := NewTestFixture(t)
    defer fixture.Cleanup(t)
    
    // Test specific logic here
}

func TestStateRootUpdate(t *testing.T) {
    fixture := NewTestFixture(t)
    defer fixture.Cleanup(t)
    
    // Test specific logic here
}
indexer/src/types.rs (3)

16-27: Missing Serialize and Deserialize derivations.

PartialCandidateData and PartialCandidateDataWithBlockTxHash lack serde::Serialize and serde::Deserialize derivations. Add them to ensure consistency and enable serialization.

Apply this diff to add the derivations:

 #[derive(Clone, Debug)]
+#[derive(serde::Serialize, serde::Deserialize)]
 pub(crate) struct PartialCandidateData {
     pub rollup_id: u32,
     pub payloads: Vec<Vec<u8>>,
 }

 #[derive(Clone, Debug)]
+#[derive(serde::Serialize, serde::Deserialize)]
 pub(crate) struct PartialCandidateDataWithBlockTxHash {
     pub rollup_id: u32,
     pub payloads: Vec<Vec<u8>>,
     pub tx_hash: CryptoHash,
     pub block_hash: CryptoHash,
 }

16-27: Inconsistent visibility modifiers among structs.

Some structs are marked pub(crate) while others are pub. Ensure visibility modifiers are consistent and appropriate for your module's design.


16-65: Add documentation comments to public interfaces.

Public structs and enums lack /// documentation comments. Add them to improve code clarity and facilitate maintenance.

indexer/src/main.rs (1)

105-105: Inconsistent logging target usage for startup message.

Previously, the constant INDEXER was used as the logging target. Changing it to INDEXER_NAMESPACE may lead to inconsistencies in log filtering and grouping.

Consider reverting to the original logging target or ensuring that all logging statements use INDEXER_NAMESPACE consistently throughout the codebase.

indexer/src/fastnear_indexer.rs (2)

133-135: Eliminate unnecessary cloning of candidate_data.

Cloning candidate_data is inefficient and consumes extra memory. Iterate over references to the payloads instead to improve performance.

Apply the following modification:

 async fn send(candidate_data: &PartialCandidateDataWithBlockTxHash, sender: &Sender<PublishData>) -> Result<(), Error> {
     trace!(target: "fastnear_indexer", "Sending candidate data: {:?}", candidate_data);
-    for data in candidate_data.clone().payloads {
+    for data in &candidate_data.payloads {
         let publish_data = PublishData {
             publish_options: PublishOptions {
                 routing_key: get_routing_key(candidate_data.rollup_id),
                 ..PublishOptions::default()
             },
             cx: PublisherContext {
                 block_hash: candidate_data.block_hash,
             },
             payload: PublishPayload {
                 transaction_id: candidate_data.tx_hash,
-                data,
+                data: data.clone(),
             },
         };
         sender.send(publish_data).await?
     }
     Ok(())
 }

105-105: Avoid cloning the block before sending over the channel.

Cloning block is unnecessary if ownership can be transferred. This reduces memory usage and improves efficiency.

Modify the send operation to move the block:

-            if block_sender.send(block.clone()).await.is_err() {
+            if block_sender.send(block).await.is_err() {
indexer/src/block_listener.rs (9)

Line range hint 37-44: Make TransactionWithRollupId public for broader accessibility

The struct TransactionWithRollupId is currently private. If it needs to be accessed outside of this module, declare it as pub(crate) or pub to ensure proper visibility.


Line range hint 46-49: Simplify nested transaction field access for clarity

The line:

let actions = &transaction.transaction.transaction.actions;

has multiple levels of transaction, which is confusing. Refactor to reduce nesting or rename fields to enhance readability.


Line range hint 119-139: Incomplete error handling in flush function

In the flush method, when sending candidate data fails, the error is ignored, and the method returns false without proper handling:

// TODO: return TrySendError instead
Err(_) => return false,

Implement comprehensive error handling to address potential issues during data transmission.


Line range hint 164-198: Potential deadlock due to mutex usage in process_stream

Holding the mutex lock on queue_protected while performing I/O operations or awaiting asynchronous tasks can lead to deadlocks. Re-evaluate the lock's scope and limit its usage to only when accessing shared data.


Line range hint 230-255: Inefficient loop in candidate data processing

The manual iteration over candidates_data:

while let Some(candidate) = iter.next() {
    // ...
}

can be replaced with a for-loop or iterators to improve code efficiency and readability.


Line range hint 378-385: Direct comparison of floating-point numbers in tests

Using assert_eq! for floating-point numbers can cause flaky tests due to precision errors. Use approximate equality methods or tolerate a small epsilon value.


Line range hint 400-405: Unnecessary cloning of valid_transaction in tests

Cloning valid_transaction is redundant since it's not modified. Remove the clone to optimize memory usage.


Line range hint 510-515: Use of magic number in test_shutdown

The condition if i == 5 uses a magic number 5. Define a constant or add a comment to explain the significance for better maintainability.


Line range hint 530-550: Inefficient file reading in StreamerMessagesLoader::load_messages

Collecting directory entries into a Vec<PathBuf> before processing is unnecessary. Iterate over the entries directly to streamline file loading.

tests/integration/fastnear_test.go (4)

367-368: Avoid setting environment variables within the code

Modifying environment variables like OPERATOR_BLS_KEY_PASSWORD and OPERATOR_ECDSA_KEY_PASSWORD inside the code can lead to side effects and makes the code less predictable.

Consider removing these lines and setting the environment variables outside the application, such as in the test setup or via a configuration management tool.

- os.Setenv("OPERATOR_BLS_KEY_PASSWORD", "")
- os.Setenv("OPERATOR_ECDSA_KEY_PASSWORD", "")

285-285: Check for potential goroutine leaks

When starting goroutines within tests (go operator.Start(ctx) and go agg.Start(ctx)), ensure they are properly terminated to prevent resource leaks.

  • Confirm that the ctx passed to these functions is adequately cancelled when the test completes.
  • Use defer statements or t.Cleanup to manage goroutine lifecycles.

Also applies to: 323-323


687-710: Consolidate duplicate HTTP request handling code

The functions getStateRootUpdateAggregation and getOperatorSetUpdateAggregation have similar logic for making HTTP GET requests and handling responses.

Abstract the common code into a single helper function to reduce duplication and improve maintainability.

Also applies to: 712-737


178-263: Add error checks after creating the network

There is no check for errors when removing the network in the cleanup function if network creation failed.

Ensure that resources are only cleaned up if they were successfully created:

- if err := net.Remove(containersCtx); err != nil {
+ if net != nil {
+     if err := net.Remove(containersCtx); err != nil {
         t.Fatalf("Error removing network: %s", err.Error())
     }
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5a2c458 and dd9b90c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • .github/workflows/compose-fastnear-test.yml (1 hunks)
  • .github/workflows/compose-test.yml (6 hunks)
  • .github/workflows/contracts-tests.yml (1 hunks)
  • .github/workflows/docs-test.yml (1 hunks)
  • .github/workflows/unit-tests.yml (2 hunks)
  • Cargo.toml (1 hunks)
  • Makefile (3 hunks)
  • docker-compose-fastnear.yml (1 hunks)
  • docker-compose.yml (1 hunks)
  • indexer/Cargo.toml (1 hunks)
  • indexer/Dockerfile (2 hunks)
  • indexer/FastIndexer.dockerfile (1 hunks)
  • indexer/README.md (1 hunks)
  • indexer/src/block_listener.rs (1 hunks)
  • indexer/src/errors.rs (2 hunks)
  • indexer/src/fastnear_indexer.rs (1 hunks)
  • indexer/src/main.rs (4 hunks)
  • indexer/src/metrics.rs (1 hunks)
  • indexer/src/types.rs (3 hunks)
  • indexer/test_data/config/example.yaml (1 hunks)
  • rust-toolchain.toml (1 hunks)
  • tests/e2e/e2e_tests/tests/containers.rs (0 hunks)
  • tests/e2e/e2e_tests/tests/ctr_availability_test.rs (1 hunks)
  • tests/integration/fastnear_test.go (1 hunks)
  • tests/integration/integration_test.go (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/e2e/e2e_tests/tests/containers.rs
✅ Files skipped from review due to trivial changes (2)
  • Cargo.toml
  • rust-toolchain.toml
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/compose-fastnear-test.yml

17-17: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


111-111: shellcheck reported issue in this script: SC2086:info:11:57: Double quote to prevent globbing and word splitting

(shellcheck)


111-111: shellcheck reported issue in this script: SC2086:info:14:58: Double quote to prevent globbing and word splitting

(shellcheck)

🪛 yamllint (1.35.1)
.github/workflows/compose-fastnear-test.yml

[error] 133-133: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/compose-test.yml

[error] 131-131: no new line character at the end of file

(new-line-at-end-of-file)

indexer/test_data/config/example.yaml

[error] 37-37: no new line character at the end of file

(new-line-at-end-of-file)

🪛 Gitleaks (8.21.2)
docker-compose-fastnear.yml

240-240: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


271-271: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


272-272: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

tests/integration/fastnear_test.go

454-454: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


511-511: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


543-543: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 LanguageTool
indexer/README.md

[uncategorized] ~34-~34: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ...fetch NEAR blocks more efficiently. The --features use_fastnear flag enables the FastNEAR...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)

🪛 Markdownlint (0.35.0)
indexer/README.md

31-31: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)

🔇 Additional comments (10)
.github/workflows/docs-test.yml (1)

7-8: Verify comprehensive documentation coverage

The paths filter docs/** assumes all documentation resides in the docs directory. This might miss documentation-related changes in:

  • README files
  • API documentation in source code
  • Markdown files in other directories
.github/workflows/contracts-tests.yml (1)

Line range hint 43-44: Test command excludes FFI contracts without justification

The --no-match-contract FFI flag excludes FFI contracts from testing. This could leave critical functionality untested.

Let's check for FFI contract usage:

indexer/Cargo.toml (1)

30-34: Verify NEAR framework compatibility

All NEAR dependencies are pinned to git commit a83c18490cf4. This is good for consistency, but:

indexer/src/errors.rs (1)

68-68: The Result type alias follows standard Rust conventions.

indexer/src/metrics.rs (2)

6-6: Documentation must be updated to reflect the namespace change

Making INDEXER_NAMESPACE public and changing its value requires documentation updates. This change affects metric collection configuration and dashboards.


6-6: ⚠️ Potential issue

CRITICAL: Verify impact on existing metrics collection

The namespace change from "sffl_indexer" to "nffl_indexer" will affect all metrics collection. This modification requires immediate attention to prevent monitoring disruption.

✅ Verification successful

Let me examine the monitoring configurations to determine if there are any dependencies on the old namespace and assess the potential impact of this change.


Namespace change is safe to proceed

The search results show no references to the old "sffl_indexer" namespace in any of the monitoring configurations or metric endpoints. The metrics configuration is primarily handled through IP:port specifications in docker-compose files and yaml configurations, which are independent of the Rust namespace change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old namespace
rg "sffl_indexer" --type yaml --type rust

# Look for potential monitoring configuration files
fd -e yaml -e yml . | xargs grep -l "prometheus\|metrics\|monitoring"

Length of output: 818


Script:

#!/bin/bash
# Check the content of prometheus configuration files for the old namespace
rg -A 5 -B 5 "sffl_indexer" prometheus/prometheus.yml setup/*/prometheus/prometheus.yml

# Check monitoring configurations in docker compose files
rg -A 5 -B 5 "metrics" docker-compose*.yml setup/*/docker-compose.yml

# Check if there are any metric-related configurations in yaml files
rg -A 5 -B 5 "metrics:" config-files/*.yaml setup/*/config/*.yaml

Length of output: 12632

.github/workflows/compose-test.yml (1)

90-90: Verify consistent container naming across all configurations

The container name has been corrected from "agreator" to "aggregator". Let's ensure this correction is applied consistently across all configuration files.

Also applies to: 113-113

✅ Verification successful

Container naming is consistent across configurations

The search results confirm that there are no remaining instances of the "agreator" typo in any YAML configurations. All references correctly use "aggregator" in container names, configuration parameters, and service definitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining instances of the typo

rg -i "agreator" --type yaml

Length of output: 28


Script:

#!/bin/bash
# Search for both old and new container names in yaml files
rg -i "nffl.*health" --type yaml

# Also check for any variations of aggregator/agreator in docker-compose files
fd -e yml -e yaml | xargs grep -i "aggregator\|agreator"

Length of output: 4556

Makefile (1)

145-147: ⚠️ Potential issue

Disabled test without justification

The registration test has been commented out without explanation. This reduces test coverage and could mask potential issues.

Either:

  1. Restore the test if it's still relevant
  2. Remove it if it's obsolete
  3. Document why it's disabled with a TODO comment

Additionally, the new fastnear test lacks documentation about its purpose and requirements.

indexer/src/main.rs (2)

113-113: Ensure new logging filters are correctly applied.

Adding fastnear_indexer=info to the logging filter is appropriate. Verify that all relevant modules are included and that the logging levels are set as intended.


118-118: Potential issue with default home directory resolution.

Ensure that the change from pattern matching to using unwrap_or_else does not alter the behaviour when home_dir is not provided. Confirm that near_indexer::get_default_home correctly returns the intended default directory.

Run the following script to confirm the default home directory:

.github/workflows/contracts-tests.yml Show resolved Hide resolved
.github/workflows/unit-tests.yml Show resolved Hide resolved
.github/workflows/unit-tests.yml Show resolved Hide resolved
indexer/FastIndexer.dockerfile Show resolved Hide resolved
indexer/FastIndexer.dockerfile Outdated Show resolved Hide resolved
indexer/src/block_listener.rs Show resolved Hide resolved
tests/integration/fastnear_test.go Outdated Show resolved Hide resolved
tests/integration/fastnear_test.go Outdated Show resolved Hide resolved
tests/integration/fastnear_test.go Outdated Show resolved Hide resolved
tests/integration/fastnear_test.go Outdated Show resolved Hide resolved
@serrrfirat serrrfirat self-requested a review November 29, 2024 10:12
Copy link
Collaborator

@serrrfirat serrrfirat left a comment

Choose a reason for hiding this comment

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

Couple of comments -
When you were copying the implementation from the branch did you fix the comments on the PR given by Don? If not please integrate the asked changes.

indexer/src/fastnear_indexer.rs Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
indexer/src/types.rs Show resolved Hide resolved
Copy link
Contributor

@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: 9

🧹 Outside diff range and nitpick comments (5)
indexer/Cargo.toml (1)

43-45: Document feature flags usage

New features use_fastnear and it_tests have been added without documentation. Given that integration tests are mentioned as work in progress in the PR description, we need clarity on these features' usage.

Add feature documentation in the Cargo.toml:

 [features]
+# Enable FastNear indexer integration
 use_fastnear = []
+# Enable integration tests (currently WIP)
 it_tests = []
.github/workflows/integration-tests.yml (1)

80-83: Address integration test dependencies

According to the PR objectives, there are "complexities associated with the nearcore setup". The workflow doesn't explicitly handle these dependencies.

Consider:

  1. Add explicit checks for nearcore dependencies
  2. Include setup verification steps
  3. Document required environment configuration
  4. Add timeout parameters specific to FastNear tests
indexer/src/main.rs (1)

105-113: Logging filter string requires refactoring.

The logging filter string is becoming difficult to maintain. Consider extracting it to a configuration file or constant.

Extract the filter string to a constant:

+const DEFAULT_LOG_FILTER: &str = concat!(
+    "nearcore=info,publisher=info,indexer=info,candidates_validator=info,",
+    "metrics=info,tokio_reactor=info,near=info,stats=info,telemetry=info,",
+    "near-performance-metrics=info,fastnear_indexer=info"
+);

-    let env_filter = near_o11y::tracing_subscriber::EnvFilter::new(
-        "nearcore=info,publisher=info,indexer=info,candidates_validator=info,\
-         metrics=info,tokio_reactor=info,near=info,stats=info,telemetry=info,\
-         near-performance-metrics=info,fastnear_indexer=info",
-    );
+    let env_filter = near_o11y::tracing_subscriber::EnvFilter::new(DEFAULT_LOG_FILTER);
indexer/src/configs.rs (1)

56-57: Fix style inconsistencies

  1. Missing trailing comma after the new field
  2. Inconsistent documentation style compared to other fields

Apply this diff to fix the style issues:

     #[clap(long, default_value = "256")]
-    pub channel_width: usize
+    pub channel_width: usize,
indexer/src/fastnear_indexer.rs (1)

239-239: Eliminate hardcoded channel_width value

Using a magic number (128) for channel_width in the test reduces flexibility and readability. Define channel_width as a constant or pass it as a parameter to allow for easier adjustments and maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 05bda85 and 8d961f4.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • .github/workflows/integration-tests.yml (1 hunks)
  • indexer/Cargo.toml (1 hunks)
  • indexer/src/configs.rs (1 hunks)
  • indexer/src/fastnear_indexer.rs (1 hunks)
  • indexer/src/main.rs (4 hunks)
🧰 Additional context used
📓 Learnings (2)
indexer/Cargo.toml (1)
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/Cargo.toml:37-38
Timestamp: 2024-11-28T13:42:30.249Z
Learning: When reviewing `indexer/Cargo.toml`, note that moving dependencies to the workspace will be handled separately. Do not suggest moving dependencies to the workspace in the current pull request.
indexer/src/main.rs (2)
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:43-50
Timestamp: 2024-11-28T13:49:02.995Z
Learning: In `indexer/src/main.rs`, using `if cfg!(feature = "use_fastnear")` is intended and acceptable; do not suggest replacing it with conditional compilation attributes in future reviews.
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:100-100
Timestamp: 2024-11-28T13:48:31.475Z
Learning: `Error::AnyhowError` requires the `anyhow!` macro as an argument to produce an `anyhow::Error`.
🔇 Additional comments (8)
.github/workflows/integration-tests.yml (1)

80-82: ⚠️ Potential issue

Clarify the distinction between duplicate test features

Both Rust test steps use identical feature flags --features it-tests but run in different directories. This creates ambiguity about test scope and purpose.

Let's verify the feature definitions in both locations:

Consider:

  1. Using distinct feature flags for each test suite
  2. Adding conditional execution based on changed files
  3. Documenting the purpose of each test suite in comments
indexer/src/main.rs (3)

10-11: Module structure is acceptable.

The new fastnear_indexer module and its imports are properly integrated into the existing codebase.

Also applies to: 22-22


39-41: Metrics configuration simplified appropriately.

The change to is_some() is more concise than pattern matching for this use case.


100-100: Error handling implementation is correct.

The use of anyhow! macro with Error::AnyhowError follows the established pattern.

indexer/src/configs.rs (1)

56-57: Verify channel_width usage and performance impact

The addition of channel_width parameter requires verification:

  1. Confirm its usage in FastNear indexer implementation
  2. Verify performance implications with different values
  3. Consider adding metrics for channel utilisation
✅ Verification successful

Let me analyze the channel usage patterns and any performance considerations in the tests before making a final determination.


Channel width parameter implementation is adequate

The channel_width parameter is correctly integrated:

  • Used in FastNearIndexer to configure two tokio mpsc channels for block and publish operations
  • Default value of 256 is reasonable for async message processing
  • No performance metrics needed as tokio channels are self-regulating with back-pressure

The implementation follows standard patterns for async Rust channel usage. Adding metrics would be superfluous as channel capacity issues manifest through back-pressure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for channel_width usage in the codebase
echo "Searching for channel_width usage:"
rg -p "channel_width" --type rust

# Search for potential performance metrics
echo "Checking for related metrics:"
rg -p "metrics|performance|channel" src/

Length of output: 822


Script:

#!/bin/bash
# Search for channel usage in the indexer implementation
ast-grep --pattern 'mpsc::channel($$$)' indexer/src/fastnear_indexer.rs

# Check for any performance-related comments or documentation
rg -p "performance|throughput|channel" indexer/

# Look for any tests that might validate channel behavior
fd -e rs test -x rg -p "channel_width|mpsc::channel" {}

Length of output: 2144

indexer/src/fastnear_indexer.rs (3)

176-183: ⚠️ Potential issue

Incorrect handling of successful execution statuses

The is_successful_execution function only considers SuccessValue with an empty value as successful. This exclusion overlooks successful executions that return non-empty values or SuccessReceiptId. This oversight can lead to missing valid data.

Apply the following diff to correctly handle all success variants:

 fn is_successful_execution(receipt_execution_outcome: &IndexerExecutionOutcomeWithReceiptAndTxHash) -> bool {
     let is_successful = matches!(
         receipt_execution_outcome.execution_outcome.outcome.status,
-        ExecutionStatusView::SuccessValue(ref value) if value.is_empty()
+        ExecutionStatusView::SuccessValue(_) | ExecutionStatusView::SuccessReceiptId(_)
     );
     trace!(FASTNEAR_INDEXER, "Execution successful: {}", is_successful);
     is_successful
 }

93-104: ⚠️ Potential issue

Avoid skipping processing when tx_hash is missing

By requiring tx_hash to be Some, the code disregards cases where tx_hash is None, potentially missing relevant data. This could result in incomplete processing of valid receipts.

Consider adjusting the condition:

-    if let (Some(partial_data), Some(tx_hash)) =
-        (partial_candidate_data, receipt_execution_outcome.tx_hash)
+    if let Some(partial_data) = partial_candidate_data {
+        let tx_hash = receipt_execution_outcome.tx_hash.unwrap_or_default();

Ensure that using a default tx_hash is appropriate and won't introduce inconsistencies.


117-131: 🛠️ Refactor suggestion

Implement exponential backoff to handle fetch failures

Currently, after a fetch failure, the loop waits for a fixed 1-second delay before retrying. This can cause rapid retries during persistent failures, leading to unnecessary load and potential rate limiting. An exponential backoff strategy is essential to mitigate these risks.

Apply the following changes:

 tokio::spawn(async move {
+    let mut failure_count = 0;
     loop {
         match Self::fetch_latest_block(&client).await {
             Ok(block) => {
                 if block_sender.send(block.clone()).await.is_err() {
                     error!(FASTNEAR_INDEXER, "Failed to send block to channel");
                     break;
                 }
                 info!(FASTNEAR_INDEXER, "Successfully fetched and sent latest block with id: {}", block.block.header.height);
+                failure_count = 0; // Reset failure count on success
             }
             Err(e) => {
                 error!(FASTNEAR_INDEXER, "Error fetching latest block: {:?}", e);
+                failure_count += 1;
+                let delay = std::time::Duration::from_secs(1 << std::cmp::min(failure_count, 5));
+                tokio::time::sleep(delay).await;
+                continue;
             }
         }
-        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+        tokio::time::sleep(std::time::Duration::from_secs(1)).await; // Regular interval between fetches
     }
 });

indexer/Cargo.toml Show resolved Hide resolved
indexer/Cargo.toml Show resolved Hide resolved
indexer/Cargo.toml Show resolved Hide resolved
.github/workflows/integration-tests.yml Outdated Show resolved Hide resolved
indexer/src/main.rs Outdated Show resolved Hide resolved
indexer/src/main.rs Outdated Show resolved Hide resolved
indexer/src/configs.rs Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
@Fly-Style Fly-Style requested a review from serrrfirat November 29, 2024 14:22
Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8d961f4 and 36b90e9.

📒 Files selected for processing (1)
  • indexer/src/fastnear_indexer.rs (1 hunks)
🔇 Additional comments (2)
indexer/src/fastnear_indexer.rs (2)

177-184: ⚠️ Potential issue

Broaden success criteria to include all valid success states

The current implementation only considers empty success values as successful executions, potentially missing valid successful states.

This issue was previously identified. The implementation should be updated to include all success variants as suggested in the previous review.


117-132: 🛠️ Refactor suggestion

⚠️ Potential issue

Implement proper error handling with exponential backoff

The current implementation continues to hammer the endpoint even when errors occur. This could lead to rate limiting or service degradation.

Implement exponential backoff:

 tokio::spawn(async move {
+    let mut backoff = 1;
+    let max_backoff = 32;
     loop {
         match Self::fetch_latest_block(&client).await {
             Ok(block) => {
                 let block_height = block.block.header.height;
                 if block_sender.send(block).await.is_err() {
                     error!(FASTNEAR_INDEXER, "Failed to send block to channel");
                     break;
                 }
                 info!(FASTNEAR_INDEXER, "Successfully fetched and sent latest block with id: {}", block_height);
+                backoff = 1;
             }
-            Err(e) => error!(FASTNEAR_INDEXER, "Error fetching latest block: {:?}", e),
+            Err(e) => {
+                error!(FASTNEAR_INDEXER, "Error fetching latest block: {:?}", e);
+                backoff = std::cmp::min(backoff * 2, max_backoff);
+            }
         }
-        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+        tokio::time::sleep(std::time::Duration::from_secs(backoff)).await;
     }
 });

Likely invalid or redundant comment.

indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (2)
indexer/src/main.rs (1)

58-72: High coupling between indexer components.

The implementation tightly couples the IndexerWrapper, CandidatesValidator, and RmqPublisher, making the system less maintainable and harder to test.

Consider implementing a message bus or event-driven architecture to decouple these components. This would allow for:

  • Independent testing of each component
  • Easier maintenance and modifications
  • Better error isolation
indexer/src/fastnear_indexer.rs (1)

241-241: Avoid magic numbers; make channel_width configurable or use a constant

Using a hardcoded value like 128 for channel_width reduces code clarity and flexibility. Define it as a constant or make it configurable to improve maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 36b90e9 and 39555dd.

📒 Files selected for processing (2)
  • indexer/src/fastnear_indexer.rs (1 hunks)
  • indexer/src/main.rs (4 hunks)
🧰 Additional context used
📓 Learnings (1)
indexer/src/main.rs (2)
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:43-50
Timestamp: 2024-11-28T13:49:02.995Z
Learning: In `indexer/src/main.rs`, using `if cfg!(feature = "use_fastnear")` is intended and acceptable; do not suggest replacing it with conditional compilation attributes in future reviews.
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:100-100
Timestamp: 2024-11-28T13:48:31.475Z
Learning: `Error::AnyhowError` requires the `anyhow!` macro as an argument to produce an `anyhow::Error`.
🔇 Additional comments (10)
indexer/src/main.rs (6)

10-11: Module structure and imports are properly organised.

The new module declaration and imports align with the FastNear indexer integration objectives.

Also applies to: 22-22


43-50: Channel width parameter requires validation.

The channel_width parameter is passed directly to FastNearIndexer::new without bounds checking. This remains a potential risk for system stability.


99-99: Error handling implementation is correct.

The use of anyhow::anyhow! macro with Error::AnyhowError follows the expected pattern.


104-104: Logging configuration properly updated.

The logging target and filter changes appropriately accommodate the new FastNear indexer module.

Also applies to: 112-112


117-117: Home directory handling follows best practices.

The use of unwrap_or_else provides a safe fallback mechanism for the home directory.


74-74: ⚠️ Potential issue

Inadequate error handling for block handle.

The block handle's error handling relies solely on await without proper handling of cancellation scenarios.

Implement comprehensive error handling that accounts for both cancellation and panic scenarios:

-            Ok::<_, Error>(block_handle.await?)
+            match block_handle.await {
+                Ok(result) => Ok(result),
+                Err(e) if e.is_cancelled() => {
+                    error!(target: INDEXER, "Block processing cancelled: {}", e);
+                    Err(Error::BlockProcessingCancelled(e))
+                }
+                Err(e) => {
+                    error!(target: INDEXER, "Block processing failed: {}", e);
+                    Err(Error::BlockProcessingFailed(e))
+                }
+            }

Likely invalid or redundant comment.

indexer/src/fastnear_indexer.rs (4)

24-24: Parameterise the endpoint URL instead of hardcoding it

Hardcoding the endpoint URL restricts flexibility and complicates deployment configurations. The endpoint should be configurable through environment variables or configuration files.


130-130: Implement exponential back-off on fetch failures to prevent rapid retries

Currently, the code retries fetching the latest block every second, even after a failure. This can lead to unnecessary load and potential throttling. Introduce exponential back-off to space out retries after failures.


177-184: Consider all execution success variants in is_successful_execution

The function only treats SuccessValue with an empty value as successful, ignoring other success statuses like SuccessValue with data or SuccessReceiptId. This may cause valid successful executions to be overlooked.


93-94: Handle cases where tx_hash is None to avoid missing valid data

By skipping processing when tx_hash is None, you may miss relevant data. Adjust the logic to handle cases where tx_hash is missing.

indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
serrrfirat
serrrfirat previously approved these changes Nov 29, 2024
Copy link
Collaborator

@serrrfirat serrrfirat left a comment

Choose a reason for hiding this comment

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

1 nit - looks good.

indexer/src/fastnear_indexer.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@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: 5

🧹 Outside diff range and nitpick comments (3)
indexer/src/main.rs (2)

Line range hint 10-22: Module organisation requires improvement

The new fastnear_indexer module declaration appears at the end of the module list, breaking alphabetical ordering. This inconsistency hampers code maintainability.

Apply this diff to maintain alphabetical ordering:

 mod block_listener;
 mod candidates_validator;
 mod configs;
 mod errors;
+mod fastnear_indexer;
 mod indexer_wrapper;
 mod metrics;
 mod metrics_server;
 mod rmq_publisher;
-mod types;
-mod fastnear_indexer;
+mod types;

111-113: Logging configuration needs restructuring

The logging filter is a hard-coded string that's difficult to maintain and prone to formatting errors. It should be constructed programmatically.

Consider restructuring:

-    let env_filter = near_o11y::tracing_subscriber::EnvFilter::new(
-        "nearcore=info,publisher=info,indexer=info,candidates_validator=info,\
-         metrics=info,tokio_reactor=info,near=info,stats=info,telemetry=info,\
-         near-performance-metrics=info,fastnear_indexer=info",
-    );
+    let components = vec![
+        "nearcore", "publisher", "indexer", "candidates_validator",
+        "metrics", "tokio_reactor", "near", "stats", "telemetry",
+        "near-performance-metrics", "fastnear_indexer"
+    ];
+    let env_filter = near_o11y::tracing_subscriber::EnvFilter::new(
+        components.iter()
+            .map(|c| format!("{}=info", c))
+            .collect::<Vec<_>>()
+            .join(",")
+    );
indexer/src/configs.rs (1)

56-61: Architectural concern: Configuration coupling

The addition of FastNear-specific configuration directly into the core RunConfigArgs creates tight coupling. Consider extracting FastNear-specific configuration into a separate struct:

+ #[derive(clap::Parser, Deserialize, Debug)]
+ pub struct FastNearConfig {
+     /// Address of fastnear block producer.
+     #[clap(long, default_value = "https://testnet.neardata.xyz/v0/last_block/final")]
+     pub address: String,
+     
+     /// Internal FastIndexer channels width.
+     #[clap(long, default_value = "256")]
+     pub channel_width: usize,
+ }

  #[derive(clap::Parser, Deserialize, Debug)]
  #[group(id = "config_args", conflicts_with = "config_path")]
  pub(crate) struct RunConfigArgs {
      // ... existing fields ...
-     pub fastnear_address: String,    
-     pub channel_width: usize
+     #[clap(flatten)]
+     pub fastnear: FastNearConfig,
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 39555dd and b5ecb80.

📒 Files selected for processing (4)
  • .github/workflows/integration-tests.yml (1 hunks)
  • indexer/src/configs.rs (1 hunks)
  • indexer/src/fastnear_indexer.rs (1 hunks)
  • indexer/src/main.rs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/integration-tests.yml
🧰 Additional context used
📓 Learnings (1)
indexer/src/main.rs (2)
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:43-50
Timestamp: 2024-11-28T13:49:02.995Z
Learning: In `indexer/src/main.rs`, using `if cfg!(feature = "use_fastnear")` is intended and acceptable; do not suggest replacing it with conditional compilation attributes in future reviews.
Learnt from: Fly-Style
PR: Nuffle-Labs/nffl#321
File: indexer/src/main.rs:100-100
Timestamp: 2024-11-28T13:48:31.475Z
Learning: `Error::AnyhowError` requires the `anyhow!` macro as an argument to produce an `anyhow::Error`.
🔇 Additional comments (4)
indexer/src/main.rs (1)

44-50: ⚠️ Potential issue

Potential resource leak in FastNear stream handling

The validated stream is not properly cleaned up if the system encounters an error. This could lead to resource leaks.

Implement proper cleanup:

     if cfg!(feature = "use_fastnear") {
         let fastnear_indexer = FastNearIndexer::new(fastnear_addr, addr_to_rollup_ids, config.channel_width);
-        let validated_stream = fastnear_indexer.run();
+        let validated_stream = fastnear_indexer.run().with_cleanup(|| {
+            info!(target: INDEXER, "Cleaning up FastNear resources");
+        });
         rmq_publisher.run(validated_stream);
         Ok::<_, Error>(())
     } else {

Likely invalid or redundant comment.

indexer/src/configs.rs (1)

59-61: ⚠️ Potential issue

Previous documentation concerns remain unaddressed

The channel_width parameter still lacks proper documentation and validation as highlighted in the previous review.

Additionally, this parameter requires integration testing to validate its impact on system performance:

#!/bin/bash
# Search for performance tests or benchmarks related to channel_width
rg -g '*.rs' -l 'channel_width.*bench|bench.*channel_width'

# Look for any existing performance metrics collection
ast-grep --pattern 'metrics.$$$channel_width$$$'
indexer/src/fastnear_indexer.rs (2)

128-144: ⚠️ Potential issue

Implement exponential backoff for error handling.

The current implementation uses a fixed 1-second delay between retries, which could overwhelm the system during persistent failures.

+    let mut backoff = 1;
     loop {
         match Self::fetch_latest_block(&client, fastnear_address.as_str()).await {
             Ok(block) => {
                 let block_height = block.block.header.height;
                 if block_sender.send(block).await.is_err() {
                     error!(FASTNEAR_INDEXER, "Failed to send block to channel");
                     break;
                 }
                 info!(
                     FASTNEAR_INDEXER,
                     "Successfully fetched and sent latest block with id: {}", block_height
                 );
+                backoff = 1;
             }
-            Err(e) => error!(FASTNEAR_INDEXER, "Error fetching latest block: {:?}", e),
+            Err(e) => {
+                error!(FASTNEAR_INDEXER, "Error fetching latest block: {:?}", e);
+                backoff = std::cmp::min(backoff * 2, 60);
+            }
         }
-        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+        tokio::time::sleep(std::time::Duration::from_secs(backoff)).await;
     }

Likely invalid or redundant comment.


190-197: ⚠️ Potential issue

Broaden successful execution criteria.

The current implementation only considers empty success values as successful executions, potentially missing valid successful executions with non-empty values.

 fn is_successful_execution(receipt_execution_outcome: &IndexerExecutionOutcomeWithReceiptAndTxHash) -> bool {
     let is_successful = matches!(
         receipt_execution_outcome.execution_outcome.outcome.status,
-        ExecutionStatusView::SuccessValue(ref value) if value.is_empty()
+        ExecutionStatusView::SuccessValue(_) | ExecutionStatusView::SuccessReceiptId(_)
     );
     trace!(FASTNEAR_INDEXER, "Execution successful: {}", is_successful);
     is_successful
 }

Likely invalid or redundant comment.

indexer/src/main.rs Show resolved Hide resolved
indexer/src/main.rs Show resolved Hide resolved
indexer/src/configs.rs Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Show resolved Hide resolved
indexer/src/fastnear_indexer.rs Show resolved Hide resolved
@Fly-Style Fly-Style requested a review from serrrfirat November 30, 2024 10:31
@Fly-Style Fly-Style merged commit 2f1defd into Nuffle-Labs:main Nov 30, 2024
4 checks passed
@Fly-Style Fly-Style deleted the fastnear-indexer branch November 30, 2024 13:05
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