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

Rpc failures #58

Merged
merged 5 commits into from
Dec 5, 2024
Merged

Rpc failures #58

merged 5 commits into from
Dec 5, 2024

Conversation

Krishn1412
Copy link
Contributor

@Krishn1412 Krishn1412 commented Nov 26, 2024

Summary

Related Issue

Technical details

Topics for Discussion

PR Checklist

  • Added Tests
  • Cargo Tests Passing
  • Added Documentation
  • Breaking changes

Screenshots (if applicable)

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling in account queries to prevent application crashes due to failed asynchronous calls.
    • Enhanced robustness by setting account fields to None when errors occur, ensuring smoother operation.
    • Improved logging for better visibility into errors during account resolution.

These changes ensure a more stable user experience by allowing the application to continue functioning smoothly even when individual account queries encounter issues.

Copy link
Contributor

coderabbitai bot commented Nov 26, 2024

Walkthrough

The changes in this pull request focus on enhancing error handling within the get_account function of the resolve_account_query process. The previous implementation, which directly unwrapped results from asynchronous provider calls, is replaced with if let Ok(...) constructs to manage potential errors more gracefully. If errors occur, the relevant account fields are set to None, while the address and chain fields remain unchanged.

Changes

File Path Change Summary
crates/core/src/interpreter/backend/resolve_account.rs Improved error handling in get_account function; replaced unwraps with if let Ok(...) constructs for balance, nonce, and code retrieval; updated function signatures without changing parameters or return types.

Possibly related PRs

  • Feat/user configurable rpcs #47: Enhances error handling in the rpc_url method, relevant to the improvements in asynchronous error management seen in the get_account function.

🐇 In the meadow where rabbits play,
Error handling brightens the day.
With logs to catch what goes awry,
We hop along, no need to cry.
For every call, we now take heed,
A safer path is what we need! 🌼


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 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
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: 0

🧹 Outside diff range and nitpick comments (3)
crates/core/src/interpreter/backend/resolve_account.rs (3)

74-80: LGTM: Robust error handling for balance fetch

The error handling is well-implemented, logging the error while allowing the operation to continue by setting balance to None.

Consider enhancing the error message to include the chain information:

-error!("Failed to fetch balance for address {}: {:?}", address, e);
+error!("Failed to fetch balance for address {} on chain {:?}: {:?}", address, chain, e);

83-89: Consider more granular error handling for different RPC failure types

While the current error handling is good, consider distinguishing between different types of RPC failures (e.g., network timeouts vs contract errors) for more targeted error handling and potential retries.

Example enhancement:

 match provider.get_transaction_count(*address).await {
     Ok(nonce) => account.nonce = Some(nonce),
     Err(e) => {
-        error!("Failed to fetch nonce for address {}: {:?}", address, e);
+        match e {
+            ProviderError::RpcError(rpc_err) => {
+                error!("RPC error fetching nonce for {}: {:?}", address, rpc_err);
+                // Potentially retry for certain RPC errors
+            }
+            ProviderError::NetworkError(net_err) => {
+                error!("Network error fetching nonce for {}: {:?}", address, net_err);
+                // Potentially retry for network errors
+            }
+            _ => error!("Unknown error fetching nonce for {}: {:?}", address, e),
+        }
         account.nonce = None;
     }
 }

Also applies to: 95-101


74-104: Consider adding structured error reporting for partial failures

While the current implementation gracefully handles failures by setting fields to None, it might be helpful to provide more detailed error information to the caller.

Consider adding an errors field to AccountQueryRes to track which fields failed and why:

pub struct AccountQueryRes {
    // ... existing fields ...
    pub field_errors: HashMap<AccountField, String>, // Track errors per field
}

This would allow callers to:

  1. Distinguish between missing data (None) and failed fetches
  2. Make informed decisions about retrying specific fields
  3. Provide better error reporting to end users
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1579a39 and 404cf1a.

📒 Files selected for processing (1)
  • crates/core/src/interpreter/backend/resolve_account.rs (2 hunks)
🔇 Additional comments (2)
crates/core/src/interpreter/backend/resolve_account.rs (2)

60-61: LGTM: Appropriate logging import added

The addition of log::error is appropriate for the new error handling functionality.


74-104: Verify consistent error handling across other RPC calls

Let's ensure this error handling pattern is consistently applied across all RPC calls in the codebase.

✅ Verification successful

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

Error handling is consistently implemented across RPC calls

The codebase shows consistent error handling patterns across all RPC calls:

  • All provider RPC calls use proper error handling with match or ? operator
  • No instances of .unwrap() were found on RPC results
  • Other modules (resolve_block.rs, resolve_logs.rs, chain.rs) properly propagate errors using the ? operator
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other direct RPC calls that might need similar error handling
rg -A 2 "provider\.(get_|call|send)" --type rust

# Search for potential unwrap calls on RPC results
ast-grep --pattern 'provider.$_($$$).await.unwrap()'

Length of output: 2282

@iankressin
Copy link
Owner

Hey @Krishn1412, will review this first thing tomorrow. Thanks!

Copy link
Owner

@iankressin iankressin left a comment

Choose a reason for hiding this comment

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

Overall looks good and does exactly what needs to do :)
Just small tweaks and we'll be able to include this in the next release

crates/core/src/interpreter/backend/resolve_account.rs Outdated Show resolved Hide resolved
crates/core/src/interpreter/backend/resolve_account.rs Outdated Show resolved Hide resolved
@Krishn1412
Copy link
Contributor Author

I have made the changes, @iankressin can you take a look again?

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 (1)
crates/core/src/interpreter/backend/resolve_account.rs (1)

74-95: Consider batching RPC calls for better performance

The current implementation makes separate RPC calls for each field. While this provides good isolation (a failure in one field doesn't affect others), it might not be optimal for performance, especially when fetching multiple fields.

Consider:

  1. Using batch RPC calls where the provider supports it
  2. Implementing concurrent requests for providers that don't support batching
  3. Adding a configuration option to trade off between performance (batched) and reliability (separate calls)

Would you like help implementing any of these suggestions?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 404cf1a and 97fa23f.

📒 Files selected for processing (1)
  • crates/core/src/interpreter/backend/resolve_account.rs (2 hunks)
🔇 Additional comments (1)
crates/core/src/interpreter/backend/resolve_account.rs (1)

60-60: Remove unused import

The log::error import is not used in the current changes. Additionally, as per previous feedback, we should avoid console output as it affects REPL formatting. Consider removing this import until we implement the suggested --debug flag feature.

-use log::error;

Copy link
Owner

@iankressin iankressin left a comment

Choose a reason for hiding this comment

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

@Krishn1412 just remove the unused import, everything else looks good

crates/core/src/interpreter/backend/resolve_account.rs Outdated Show resolved Hide resolved
@Krishn1412
Copy link
Contributor Author

@iankressin I have removed the unused imports.

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: 0

🧹 Outside diff range and nitpick comments (2)
crates/core/src/interpreter/backend/resolve_account.rs (2)

72-93: Consider implementing robust RPC failure handling strategy

While the current changes prevent panics, a production-ready RPC interaction strategy should consider:

  1. Retries with exponential backoff for transient failures
  2. Timeouts to prevent hanging on slow responses
  3. Circuit breakers for failing nodes
  4. Fallback providers for critical operations

Consider implementing a wrapper around the provider that handles these concerns:

pub struct RobustProvider {
    provider: RootProvider<Http<Client>>,
    retry_config: RetryConfig,
    timeout: Duration,
}

impl RobustProvider {
    async fn with_retry<T, F>(&self, operation: F) -> Result<T>
    where
        F: Fn() -> Future<Output = Result<T>>,
    {
        // Implementation with retry logic, timeouts, etc.
    }
}

Would you like me to create an issue to track this enhancement?


72-93: Add documentation for RPC failure handling behavior

The changes improve RPC failure handling, but the behavior should be documented:

  1. Update function documentation to describe error handling behavior
  2. Add examples of how RPC failures are handled
  3. Consider adding integration tests that simulate RPC failures

Add documentation above the get_account function:

/// Fetches account data from the provider, handling RPC failures gracefully.
/// 
/// # Error Handling
/// - If an RPC call fails, the corresponding field will be set to None
/// - The function will continue to fetch other requested fields even if some calls fail
/// 
/// # Examples
/// ```rust
/// // Example of handling RPC failure for balance
/// let account = get_account(&address, vec![AccountField::Balance], &failing_provider, &chain).await?;
/// assert!(account.balance.is_none()); // Balance is None when RPC fails
/// ```
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 97fa23f and 5989c25.

📒 Files selected for processing (1)
  • crates/core/src/interpreter/backend/resolve_account.rs (1 hunks)
🔇 Additional comments (2)
crates/core/src/interpreter/backend/resolve_account.rs (2)

72-76: Consider using helper function for error handling pattern

This error handling pattern is duplicated across multiple fields. Previous review suggestions for using a helper function and adding debug logging capability still apply.


89-93: 🛠️ Refactor suggestion

Distinguish between empty code and RPC failures

The current implementation treats RPC failures the same as accounts with no code (EOAs). Consider distinguishing between these cases, as they have different semantic meanings:

  • RPC failure: temporary infrastructure issue
  • Empty code (0x): confirms this is an EOA (Externally Owned Account)

Consider this approach:

-if let Ok(code) = provider.get_code_at(*address).await {
-    account.code = Some(code);
-} else {
-    account.code = None;
-}
+match provider.get_code_at(*address).await {
+    Ok(code) => {
+        // Only set Some if there's actual code
+        account.code = if code.is_empty() { None } else { Some(code) };
+    }
+    Err(_) => {
+        // Indicate RPC failure differently than empty code
+        account.code = None;
+        // TODO: Once we have the --debug flag:
+        // log::debug!("Failed to fetch code: {}", e);
+    }
+}

Likely invalid or redundant comment.

@iankressin iankressin merged commit 9b791a8 into iankressin:main Dec 5, 2024
2 checks passed
@iankressin
Copy link
Owner

Thanks @Krishn1412

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