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

refactor/fix(torii-core): correctly queue entity deletions #2428

Merged
merged 7 commits into from
Sep 16, 2024

Conversation

Larkooo
Copy link
Collaborator

@Larkooo Larkooo commented Sep 14, 2024

Summary by CodeRabbit

  • New Features

    • Introduced the ability to delete entities from the database, enhancing the query processing capabilities.
    • Implemented a queuing system for SQL commands, improving performance and modularity of entity updates and deletions.
    • Enhanced the delete_entity method to accept additional parameters for more precise entity handling.
  • Bug Fixes

    • Ensured that entity deletions are processed correctly based on associated models, maintaining data integrity.

Copy link

coderabbitai bot commented Sep 14, 2024

Walkthrough

Ohayo, sensei! This pull request introduces a new struct, DeleteEntityQuery, and a variant, DeleteEntity(DeleteEntityQuery), to the QueryType enum in the QueryQueue struct. It also refactors the SQL handling logic to utilize a query_queue for managing deletions and updates, enhancing the system's ability to process entity deletions efficiently while maintaining messaging integrity.

Changes

Files Change Summary
crates/torii/core/src/query_queue.rs Added struct DeleteEntityQuery and DeleteEntity(DeleteEntityQuery) variant to QueryType enum for handling entity deletions. Removed push_front method from QueryQueue.
crates/torii/core/src/sql.rs Refactored SQL handling to use a query_queue for batching delete and update operations, improving modularity.
crates/torii/core/src/processors/store_del_record.rs Modified delete_entity method to include model.id and selector as additional parameters for enhanced functionality.

Possibly related PRs


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 generate interesting stats about this repository and render them as a table.
    -- @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: 1

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ed2aa83 and a80c181.

Files selected for processing (2)
  • crates/torii/core/src/query_queue.rs (2 hunks)
  • crates/torii/core/src/sql.rs (2 hunks)
Additional comments not posted (5)
crates/torii/core/src/query_queue.rs (2)

43-43: Ohayo, sensei! The new DeleteEntity variant looks good.

Adding the DeleteEntity(Ty) variant to the QueryType enum is a great way to enable the system to process entity deletion requests. This change aligns perfectly with the PR objectives.


101-124: Ohayo! The DeleteEntity implementation is on point, sensei.

The new match arm for the DeleteEntity variant handles the entity deletion flow effectively:

  1. It fetches the entity details and checks if all associated models are deleted by querying the count from the entity_model table.
  2. If the count is zero, indicating that all models are deleted, it proceeds to delete the entity from the entities table.
  3. Finally, it publishes a BrokerMessage::EntityUpdated to maintain the system's messaging integrity.

This implementation ensures that entities are deleted only when all their associated models are removed, maintaining data consistency. Great work!

crates/torii/core/src/sql.rs (3)

328-335: Ohayo sensei! The entity model deletion query looks solid.

The prepared statement correctly deletes rows matching the provided entity_id and computed model_id. Nicely done!


738-742: Nice catch with the enum option tuple check!

Wrapping the tuple emptiness check inside the if let to first confirm the ty is a Tuple variant is a smart move. This will prevent any unexpected panics if the option type doesn't match the assumption.

Good attention to detail sensei!


337-345: The entity update query looks good, but let's double-check one thing.

The query correctly updates the entity's updated_at, executed_at and event_id values. Associating it with QueryType::DeleteEntity is a smart way to track entities queued for deletion.

Just one thing to verify sensei - are there any other places in the codebase that rely on the updated_at timestamp of deleted entities? If so, updating it here might lead to unexpected behavior. Worth a quick check!

Here's a script to search for updated_at usage on entities:

Let me know if you find any concerning usages!

Verification successful

Ohayo, sensei! I've taken a deep dive into the codebase, and I've got some good news for you!

No concerning usages of updated_at for deleted entities were found.

The search results show that updated_at is only being used in UPDATE queries for the entities table, which is exactly what we'd expect. There are no SELECT queries or other operations that seem to rely on the updated_at timestamp for deleted entities.

The current implementation appears to be correct and safe. You can proceed with confidence, knowing that updating updated_at for deleted entities shouldn't lead to any unexpected behavior in other parts of the codebase.

Keep up the great work, sensei!

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash

# Search for SELECT queries on `entities` that reference `updated_at`
rg --type rust 'SELECT(.*)updated_at(.*)FROM(.*)entities' -A 5

# Search for any other usage of `updated_at` on `entities`  
rg --type rust 'entities(.*)updated_at' -A 5

Length of output: 1053

Comment on lines 108 to 112
let count = sqlx::query_scalar::<_, i64>("SELECT count(*) FROM entity_model WHERE entity_id = ?")
.bind(entity_updated.id.clone())
.fetch_one(&mut *tx)
.await?;
entity_updated.deleted = count == 0;
Copy link

Choose a reason for hiding this comment

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

Suggestion: Optimize the query by using a LEFT JOIN.

Ohayo, sensei! While the current implementation of fetching the count of associated models works, it requires an additional database query. To optimize the performance, consider using a LEFT JOIN with the main query to fetch the entity details and the count of associated models in a single query.

Here's an example of how you can modify the query:

SELECT e.*, COUNT(em.entity_id) AS model_count 
FROM entities e
LEFT JOIN entity_model em ON e.id = em.entity_id
WHERE e.id = ?
GROUP BY e.id

This query will return the entity details along with the count of associated models (model_count) in a single row. You can then check the model_count value to determine if the entity can be deleted.

Using a LEFT JOIN eliminates the need for a separate query and improves the efficiency of the deletion process.

Copy link

codecov bot commented Sep 14, 2024

Codecov Report

Attention: Patch coverage is 95.91837% with 2 lines in your changes missing coverage. Please review.

Project coverage is 68.04%. Comparing base (b039f53) to head (e62d59b).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
crates/torii/core/src/query_queue.rs 96.96% 1 Missing ⚠️
crates/torii/core/src/sql.rs 93.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2428      +/-   ##
==========================================
- Coverage   68.05%   68.04%   -0.01%     
==========================================
  Files         364      364              
  Lines       47875    47880       +5     
==========================================
  Hits        32579    32579              
- Misses      15296    15301       +5     

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

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/query_queue.rs (1)

100-138: Ohayo, sensei! The implementation of the DeleteEntity variant looks solid.

The code segment handles the execution of the entity deletion query effectively. It first executes the deletion query and checks if any rows were affected. If no rows were affected, it continues to the next query in the queue, avoiding unnecessary processing.

If rows were affected, it updates the entities table with the current timestamp, event ID, and entity ID. It then retrieves the count of associated models for the entity. If the count is zero, indicating no associated models, the entity is deleted from the database. Finally, it publishes a BrokerMessage::EntityUpdated to reflect the changes.

This implementation ensures that the entity is only deleted if all its associated models are removed, maintaining data integrity.

To improve readability, consider extracting the SQL queries into separate constants or variables with descriptive names. This will make the code more maintainable and easier to understand.

For example:

const UPDATE_ENTITY_QUERY: &str = "UPDATE entities SET updated_at=CURRENT_TIMESTAMP, executed_at=?, event_id=? WHERE id = ? RETURNING *";
const COUNT_ENTITY_MODELS_QUERY: &str = "SELECT count(*) FROM entity_model WHERE entity_id = ?";
const DELETE_ENTITY_QUERY: &str = "DELETE FROM entities WHERE id = ?";

Then, you can use these constants in the corresponding sqlx::query calls.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f35e388 and e62d59b.

Files selected for processing (3)
  • crates/torii/core/src/processors/store_del_record.rs (1 hunks)
  • crates/torii/core/src/query_queue.rs (2 hunks)
  • crates/torii/core/src/sql.rs (8 hunks)
Files skipped from review as they are similar to previous changes (1)
  • crates/torii/core/src/processors/store_del_record.rs
Additional comments not posted (7)
crates/torii/core/src/query_queue.rs (3)

40-46: Ohayo, sensei! The new DeleteEntityQuery struct looks good.

The struct encapsulates the necessary data for handling entity deletion requests, including the entity_id, event_id, block_timestamp, and the entity itself. This provides a clean and structured way to pass the required information to the DeleteEntity variant in the QueryType enum.


51-51: Ohayo, sensei! The new DeleteEntity variant in the QueryType enum is a great addition.

The DeleteEntity variant, which takes the DeleteEntityQuery struct as a parameter, allows the QueryQueue to handle entity deletion requests effectively. By encapsulating the necessary data within the DeleteEntityQuery struct, it ensures that all the required information is available for the deletion process.

This variant expands the capabilities of the QueryType enum and provides a clean way to manage entity deletions within the query queue system.


104-106: Ohayo, sensei! The check for affected rows is a nice optimization.

By checking if the delete_model query affected any rows and continuing to the next query if no rows were affected, you avoid unnecessary processing and improve the efficiency of the deletion process.

If there are no associated models to delete, there is no need to proceed with updating the entities table or checking the count of associated models. This optimization ensures that the code only performs the necessary steps when there are actual changes to be made.

crates/torii/core/src/sql.rs (4)

Line range hint 283-302: Ohayo sensei! The entity deletion logic looks spot on.

The function correctly handles the deletion of an entity and its associated data by:

  • Recursively building delete queries for the entity data
  • Deleting the entity-model association with the appropriate QueryType variant
  • Storing the necessary entity details in the DeleteEntityQuery struct

Line range hint 769-838: The recursive delete query building logic is implemented correctly, sensei!

The function handles various entity types and correctly generates delete queries by:

  • Deleting the current table based on the entity_id
  • Recursively processing nested types for Struct, Tuple, Enum, and Array
  • Skipping empty tuple options for Enum types
  • Handling array elements recursively

Line range hint 769-778: The Ty::Struct match arm looks good, sensei!

It correctly handles the deletion of struct entities by:

  • Generating a delete query for the current table using the table_id and entity_id
  • Enqueueing the query with QueryType::Other
  • Recursively calling build_delete_entity_queries_recursive for each struct member with the updated path

Line range hint 790-808: The Ty::Enum match arm is implemented correctly, sensei!

It handles the deletion of enum entities by:

  • Generating a delete query for the current table using the table_id and entity_id
  • Enqueueing the query with QueryType::Other
  • Skipping enum options with empty tuples
  • Recursively calling build_delete_entity_queries_recursive for non-empty enum options with the updated path

Comment on lines +120 to +125
let count = sqlx::query_scalar::<_, i64>(
"SELECT count(*) FROM entity_model WHERE entity_id = ?",
)
.bind(entity_updated.id.clone())
.fetch_one(&mut *tx)
.await?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

To have the code organized around that we should move (in the future, not this PR) to some functions that could make this less verbose and easier to re-use, especially counting or generic stuff like so.

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.

3 participants