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

fix(torii): handle failed metadata fetch and empty metadata in db #2755

Merged
merged 1 commit into from
Dec 3, 2024

Conversation

lambda-0x
Copy link
Contributor

@lambda-0x lambda-0x commented Dec 3, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced error handling for ERC721 token metadata retrieval, ensuring smoother processing even when metadata fetch fails.
    • Introduced a new asynchronous task for processing ERC721 token registrations, improving efficiency by avoiding redundant blockchain calls.
  • Bug Fixes

    • Updated SQL queries to ensure robust filtering of token balances and transfers based on metadata presence.
  • Refactor

    • Simplified handling of metadata in token balance and transfer processing, removing unnecessary checks and assumptions.

@lambda-0x lambda-0x changed the title fix(torii): handle failed metadata fetch fix(torii): handle failed metadata fetch and empty metadata in db Dec 3, 2024
Copy link

coderabbitai bot commented Dec 3, 2024

Walkthrough

Ohayo, sensei! This pull request introduces several enhancements to the handling of ERC721 tokens within the Executor implementation. Key modifications include improved error handling in the process_register_erc721_token_query method, ensuring graceful management of metadata retrieval failures. Additionally, the Executor struct has been updated to support new asynchronous tasks for ERC721 token registration, refining the control flow and error handling mechanisms. Changes in the GraphQL layer also enforce stricter metadata handling in token balance and transfer queries, ensuring that metadata is treated as always present.

Changes

File Path Change Summary
crates/torii/core/src/executor/erc.rs Modified process_register_erc721_token_query to enhance error handling and control flow for metadata retrieval.
crates/torii/core/src/executor/mod.rs Updated Executor struct to include new async tasks for ERC721 token registration and modified methods to handle new query types and error handling.
crates/torii/graphql/src/object/erc/token_balance.rs Expanded SQL query conditions in fetch_token_balances and changed metadata field handling in BalanceQueryResultRaw from Option<String> to String.
crates/torii/graphql/src/object/erc/token_transfer.rs Updated SQL query in fetch_token_transfers to include metadata checks and changed metadata field handling in TransferQueryResultRaw from Option<String> to String.

Possibly related PRs

  • fix(torii): avoid panic on fetch token URI fail #2750: This PR enhances error handling in the process_register_erc721_token_query method, which is directly related to the changes made in the main PR that also modifies this method to improve error handling and control flow when fetching metadata for ERC721 tokens.

Suggested reviewers

  • glihm

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

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

🧹 Outside diff range and nitpick comments (1)
crates/torii/core/src/executor/erc.rs (1)

245-256: Excellent error handling improvement, sensei!

The new error handling gracefully handles metadata fetch failures by:

  1. Returning an empty string instead of failing
  2. Properly logging warnings for debugging
  3. Allowing token registration to proceed

Consider adding metrics/monitoring for failed metadata fetches to track the health of external metadata services.

Consider adding the following metrics:

  • Counter for failed metadata fetches
  • Histogram for metadata fetch latency
  • Counter for empty metadata fallbacks
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 859c9d9 and 0d7338e.

📒 Files selected for processing (4)
  • crates/torii/core/src/executor/erc.rs (1 hunks)
  • crates/torii/core/src/executor/mod.rs (0 hunks)
  • crates/torii/graphql/src/object/erc/token_balance.rs (3 hunks)
  • crates/torii/graphql/src/object/erc/token_transfer.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/torii/core/src/executor/mod.rs
🔇 Additional comments (5)
crates/torii/graphql/src/object/erc/token_balance.rs (3)

106-110: Ohayo! LGTM - SQL conditions for metadata validation

The added SQL conditions properly ensure that only tokens with valid metadata are returned.


303-303: LGTM - Struct update aligns with SQL changes

The metadata field type change from Option<String> to String correctly reflects that metadata will always be present due to the SQL conditions.


241-243: Metadata parsing looks good, sensei!

The assumption that metadata is always JSON is now safe due to the SQL conditions. However, let's verify that all existing metadata in the database is valid JSON.

✅ Verification successful

Metadata parsing is safe, sensei!

Based on the codebase analysis, the assumption that metadata is always JSON is valid because:

  1. The metadata is properly handled across the codebase with proper JSON parsing and error handling
  2. The SQL schema shows metadata is stored in a dedicated column with proper constraints
  3. The token metadata is fetched and validated before storage, with special handling for edge cases (e.g., control characters filtering in Loot Survivor NFT)

The expect("metadata is always json") is justified as the codebase ensures JSON validity before storage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify all metadata in the database is valid JSON
echo "SELECT metadata FROM tokens WHERE metadata IS NOT NULL AND metadata != ''" | sqlite3 -json . | \
jq -r '.[] | .metadata' | \
while read -r metadata; do
    if ! echo "$metadata" | jq . >/dev/null 2>&1; then
        echo "Invalid JSON found: $metadata"
    fi
done

Length of output: 249


Script:

#!/bin/bash
# Let's check how metadata is handled in the codebase
rg -A 5 "metadata.*json" --type rust

# Also check for any SQL schema definitions or migrations related to metadata
fd -e sql | xargs cat

# Check for any test cases handling metadata
rg -A 5 "metadata.*test" --type rust

Length of output: 21803

crates/torii/graphql/src/object/erc/token_transfer.rs (2)

122-126: Ohayo! Consistent metadata validation across token types

The SQL conditions mirror those in token_balance.rs, maintaining a consistent approach to metadata validation.


270-272: Consistent metadata handling, sensei!

The metadata handling changes align with those in token_balance.rs, maintaining consistency across the codebase.

Copy link

codecov bot commented Dec 3, 2024

Codecov Report

Attention: Patch coverage is 0% with 20 lines in your changes missing coverage. Please review.

Project coverage is 56.03%. Comparing base (859c9d9) to head (266c8cc).
Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
crates/torii/core/src/executor/erc.rs 0.00% 8 Missing ⚠️
...ates/torii/graphql/src/object/erc/token_balance.rs 0.00% 6 Missing ⚠️
...tes/torii/graphql/src/object/erc/token_transfer.rs 0.00% 6 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2755   +/-   ##
=======================================
  Coverage   56.02%   56.03%           
=======================================
  Files         427      427           
  Lines       54589    54591    +2     
=======================================
+ Hits        30586    30588    +2     
  Misses      24003    24003           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 108 to 109
"t.metadata IS NOT NULL".to_string(),
"t.metadata != ''".to_string(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we want to ignore the tokens without metadata? We may return them and the front will see that they are missing, or do we have an other reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

there are few cases like nft got burned in which case the metadata would no longer be present, but we still need them in db since the token id is foreign key in other tables.

and also in some cases contracts don't follow the spec properly or the json metadata is broken, etc... even in those cases we still want indexing to happen normally and we would just ignore those tokens

Copy link
Collaborator

Choose a reason for hiding this comment

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

But only metadata is ignored, or the whole token? The whole token, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah whole token, because without metadata there is no attributes, images, etc... so i dont think UI can do much with the token anyways

@lambda-0x lambda-0x marked this pull request as draft December 3, 2024 14:54
@lambda-0x lambda-0x marked this pull request as ready for review December 3, 2024 15:15
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

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0d7338e and 266c8cc.

📒 Files selected for processing (4)
  • crates/torii/core/src/executor/erc.rs (1 hunks)
  • crates/torii/core/src/executor/mod.rs (0 hunks)
  • crates/torii/graphql/src/object/erc/token_balance.rs (3 hunks)
  • crates/torii/graphql/src/object/erc/token_transfer.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • crates/torii/core/src/executor/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/torii/core/src/executor/erc.rs
🔇 Additional comments (4)
crates/torii/graphql/src/object/erc/token_balance.rs (2)

106-109: ⚠️ Potential issue

Ohayo sensei! Consider revising the metadata condition.

The SQL condition allows NULL metadata, but the struct BalanceQueryResultRaw expects metadata to always be present. This could lead to runtime errors if a NULL value is encountered.

Consider either:

  1. Updating the SQL condition to ensure metadata is always present:
-        "(t.metadata IS NULL OR length(t.metadata) > 0)".to_string(),
+        "(t.metadata IS NOT NULL AND length(t.metadata) > 0)".to_string(),
  1. Or keeping metadata as Option<String> in the struct if NULL values are expected.

Likely invalid or redundant comment.


302-302: Verify metadata handling consistency.

The change from Option<String> to String requires that metadata is always present and valid. This needs to be enforced consistently across:

  1. SQL queries
  2. JSON parsing
  3. Data insertion logic
✅ Verification successful

Ohayo sensei! Based on the findings, I can now provide a final response:

Metadata field change is safe and consistent with implementation

The change from Option<String> to String for metadata is properly enforced by the system:

  • The SQL schema shows metadata is handled at insertion time in crates/torii/core/src/executor/erc.rs
  • The token insertion query includes metadata as a required field
  • No UPDATE queries were found that could leave metadata in an invalid state

The change aligns with the system's design where metadata is always provided during token creation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential NULL metadata in the database
echo "Checking for NULL metadata in tokens table..."
sqlite3 .torii/db.sqlite3 "SELECT COUNT(*) FROM tokens WHERE metadata IS NULL;"

# Check for invalid JSON in metadata
echo "Checking for invalid JSON in metadata..."
sqlite3 .torii/db.sqlite3 "SELECT id, metadata FROM tokens WHERE json_valid(metadata) = 0;"

Length of output: 563


Script:

#!/bin/bash
# Let's check the SQL schema and queries in the codebase
rg -A 5 "CREATE TABLE.*tokens" 

# Check how metadata is handled in SQL queries
rg "metadata.*tokens" 

# Check metadata handling in the code
ast-grep --pattern 'metadata: $_'

# Check for Option<String> patterns
rg "Option<String>"

Length of output: 8412


Script:

#!/bin/bash
# Let's check how metadata is handled in token_balance.rs and related files
rg -A 5 "metadata.*tokens" crates/torii/graphql/src/object/erc/

# Check SQL queries that insert or update metadata
rg "INSERT INTO tokens.*metadata" 
rg "UPDATE tokens.*metadata"

# Check the token balance implementation
ast-grep --pattern 'impl $_ for TokenBalance'

Length of output: 1179

crates/torii/graphql/src/object/erc/token_transfer.rs (2)

122-125: ⚠️ Potential issue

Ohayo sensei! Similar metadata condition issue as in token_balance.rs.

The SQL condition allows NULL metadata, but the struct TransferQueryResultRaw expects metadata to always be present.

Apply the same fix as suggested for token_balance.rs:

-        "(t.metadata IS NULL OR length(t.metadata) > 0)".to_string(),
+        "(t.metadata IS NOT NULL AND length(t.metadata) > 0)".to_string(),

269-271: ⚠️ Potential issue

Same JSON parsing issue as in token_balance.rs.

Using .expect() for JSON parsing could cause runtime panics.

Apply the same error handling fix as suggested for token_balance.rs.

Comment on lines +240 to +242
let metadata_str = row.metadata;
let metadata: serde_json::Value =
serde_json::from_str(metadata_str).expect("metadata is always json");
serde_json::from_str(&metadata_str).expect("metadata is always json");
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider using proper error handling for JSON parsing.

Using .expect() could cause runtime panics if the metadata is not valid JSON. Even if metadata is present, it might not be well-formed JSON.

Consider handling the JSON parsing error gracefully:

-                let metadata: serde_json::Value =
-                    serde_json::from_str(&metadata_str).expect("metadata is always json");
+                let metadata: serde_json::Value = match serde_json::from_str(&metadata_str) {
+                    Ok(value) => value,
+                    Err(e) => {
+                        warn!("Failed to parse metadata JSON: {}", e);
+                        continue;
+                    }
+                };

Committable suggestion skipped: line range outside the PR's diff.

@@ -339,7 +337,7 @@ struct TransferQueryResultRaw {
pub symbol: String,
pub decimals: u8,
pub contract_type: String,
pub metadata: Option<String>,
pub metadata: String,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add tests for metadata handling.

The change to non-optional metadata field requires comprehensive testing to ensure robustness.

Consider adding tests for:

  1. Valid metadata handling
  2. Invalid JSON metadata handling
  3. Edge cases (empty strings, very large metadata)

Would you like me to help create a test suite for these scenarios?

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