Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: batch entities #2633

Merged
merged 5 commits into from
Nov 5, 2024
Merged

feat: batch entities #2633

merged 5 commits into from
Nov 5, 2024

Conversation

glihm
Copy link
Collaborator

@glihm glihm commented Nov 5, 2024

Add to the world the capabilities to batch entities, which reduce the overhead of permissions check when several entities are set/delete at once.

Ensure the event structure is in the ABI.

Historical is removed from the chain and will be implemented in Torii configuration.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced batch processing methods for reading, writing, and deleting multiple models and values.
    • Added support for emitting multiple events in a single call, improving efficiency.
    • New error handling function for length mismatches in byte arrays.
  • Improvements

    • Enhanced event handling by simplifying the event structure and removing unnecessary parameters.
    • Improved logging for event processing errors.
  • Bug Fixes

    • Updated target addresses in the policies configuration for various methods.
  • Refactor

    • Streamlined event processing logic by removing historical parameters and simplifying related structures.
    • Removed testing-related components to simplify the codebase.
  • Chores

    • Updated configuration files to reflect new world addresses.

Copy link

coderabbitai bot commented Nov 5, 2024

Walkthrough

Ohayo, sensei! This pull request includes significant updates across various files, primarily focusing on dependency management in Cargo.toml, enhancements to event processing and storage functionalities, and the introduction of new testing capabilities. Notably, several methods have been added to facilitate batch operations for models and values, while existing structures have been streamlined by removing outdated parameters. The changes aim to improve the clarity and efficiency of the codebase, particularly in handling events and managing dependencies.

Changes

File Path Change Summary
Cargo.toml Updated workspace resolver to version "2", modified dependencies for scarb and scarb-ui to a new Git repository and branch, removed commented-out lines, and maintained existing dependency versions.
bin/sozo/src/commands/events.rs Enhanced error handling in run method of EventsArgs, updated output format for EventEmitted variant in match_event function.
bin/sozo/tests/test_data/policies.json Updated target addresses for multiple methods, consolidating many to a new central address.
crates/dojo/core-cairo-test/src/lib.cairo Added new module storage under world module for testing purposes.
crates/dojo/core-cairo-test/src/tests/event/event.cairo Introduced new struct FooEvent for event handling, modified test function to remove event version assertion.
crates/dojo/core-cairo-test/src/tests/helpers.cairo Added new struct NotCopiable, updated deploy_world_and_foo function to include this model in resource list.
crates/dojo/core-cairo-test/src/tests/world/storage.cairo Introduced unit tests for ModelStorage functionality, including methods for writing, reading, and erasing models.
crates/dojo/core/cairo-test/src/tests/world/world.cairo Removed assertion for historical field in test_emit, expanded upgradeable world tests, and refined contract initialization tests.
crates/dojo/core/src/event/event.cairo Removed version field from EventDefinition struct and corresponding methods from Event trait.
crates/dojo/core/src/event/interface.cairo Removed version method from IEvent trait.
crates/dojo/core/src/lib.cairo Removed conditional compilation exports for test-related entities in model module.
crates/dojo/core/src/model/model.cairo Removed ModelTest trait and its implementation, eliminating test-related functionality.
crates/dojo/core/src/model/model_value.cairo Removed ModelValueTest trait and its implementation, focusing on core model value operations.
crates/dojo/core/src/model/storage.cairo Added methods for batch operations in ModelStorage and ModelValueStorage traits, enhancing functionality for handling multiple models and values.
crates/dojo/core/src/world/errors.cairo Added new function lengths_mismatch for error handling related to byte arrays.
crates/dojo/core/src/world/iworld.cairo Added methods for batch event and entity management, modified emit_event method to remove historical argument.
crates/dojo/core/src/world/storage.cairo Enhanced WorldStorage implementation with new methods for batch operations on models and values.
crates/dojo/core/src/world/world_contract.cairo Added methods for batch entity management and modified existing methods to streamline event handling.
crates/dojo/lang/src/attribute_macros/event.rs Removed EventParameters struct and associated logic, simplifying event processing.
crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo Removed version and historical functions from DojoEventImpl, added ensure_abi method.
crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo Introduced new public struct and implementations for model handling, removed conditional compilation blocks for test implementations.
crates/dojo/world/src/contracts/abigen/world.rs Added methods for managing entities and events in WorldContract and WorldContractReader, modified EventEmitted struct to remove historical field.
crates/torii/core/src/processors/event_message.rs Modified process method to set historical parameter to a hardcoded value of false.
crates/torii/types-test/src/contracts.cairo Updated RecordLogged struct to derive Serde, added delete method for record removal.
examples/spawn-and-move/dojo_dev.toml Updated world_address in configuration file.

Possibly related PRs

Suggested reviewers

  • kariy

🪧 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: 15

🧹 Outside diff range and nitpick comments (32)
crates/dojo/core-cairo-test/src/tests/event/event.cairo (2)

Line range hint 1-8: Ohayo! The event structure looks solid, sensei!

The FooEvent structure is well-designed with appropriate key fields and type choices. However, consider adding documentation to explain the purpose of each field for better maintainability.

Add documentation like this:

 #[derive(Drop, Serde)]
 #[dojo::event]
+/// Event emitted when foo operations occur
 struct FooEvent {
+    /// Primary key identifier (0-255)
     #[key]
     k1: u8,
+    /// Secondary key identifier
     #[key]
     k2: felt252,
+    /// First value parameter
     v1: u128,
+    /// Second value parameter
     v2: u32
 }

Line range hint 10-16: The test coverage looks good but could be enhanced, sensei!

While the basic event definition verification is solid, consider adding more test cases to ensure robust event handling:

  • Test serialization/deserialization
  • Verify key field handling
  • Test with edge case values

Here's a suggested addition:

#[test]
fn test_event_serialization() {
    let event = FooEvent { k1: 255_u8, k2: 'max', v1: 340282366920938463463374607431768211455_u128, v2: 4294967295_u32 };
    let serialized = dojo::event::Event::<FooEvent>::serialize(@event);
    // Add assertions for serialized data
}
crates/dojo/core-cairo-test/src/lib.cairo (1)

Ohayo sensei!

The commented-out modules actually exist and should be uncommented

The fd command shows that all the commented-out modules (model, benchmarks, entities, resources) have corresponding test files in the repository:

  • crates/dojo/core-cairo-test/src/tests/benchmarks.cairo
  • crates/dojo/core-cairo-test/src/tests/model/model.cairo
  • crates/dojo/core-cairo-test/src/tests/world/entities.cairo
  • crates/dojo/core-cairo-test/src/tests/world/resources.cairo

Since these test modules exist and there's no evidence of their intentional removal (no deletion commits found), they should be uncommented in lib.cairo to ensure all tests are properly included in the test suite.

🔗 Analysis chain

Line range hint 19-21: Verify status of commented-out modules

There are several commented-out modules (model, benchmarks, entities, resources). Let's verify if these are intentionally disabled or if they should be addressed as part of this PR.

Also applies to: 47-48


Let me gather more information about these commented modules to make a proper assessment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if these modules exist in the main source code and if they're actively used

# Search for corresponding source files
echo "Searching for corresponding source files..."
fd -e cairo "model|benchmarks|entities|resources" "crates/dojo/core/src"

# Check if there are any references to these modules in recent commits
echo "Checking recent commit history for these modules..."
git log --grep="model\|benchmarks\|entities\|resources" --since="1 month ago" --pretty=format:"%h - %s" --

Length of output: 576


Script:

#!/bin/bash
# Check the content of the test file to see the commented modules
echo "Checking the test file content..."
cat "crates/dojo/core-cairo-test/src/lib.cairo"

# Check if these modules exist in the test directory
echo -e "\nSearching for test modules..."
fd -e cairo "model|benchmarks|entities|resources" "crates/dojo/core-cairo-test/src"

# Check for any recent removals of these modules
echo -e "\nChecking for recent file deletions..."
git log --diff-filter=D --summary --since="3 months ago" | grep -E "model|benchmarks|entities|resources"

Length of output: 1739

crates/torii/core/src/processors/event_message.rs (2)

74-74: Ohayo! Consider enhancing the TODO comment.

The TODO comment could be more descriptive about the expected configuration implementation. This would help future developers understand the planned changes better.

-        // TODO: this must come from some torii's configuration.
+        // TODO: The historical flag should be configurable through Torii's configuration,
+        // allowing different retention policies for different environments.

75-76: Consider extracting the hardcoded value to a constant, sensei!

The hardcoded false value could be moved to a module-level constant for better maintainability and documentation.

 pub(crate) const LOG_TARGET: &str = "torii_core::processors::event_message";
+// Default historical flag value until Torii configuration is implemented
+pub(crate) const DEFAULT_HISTORICAL_FLAG: bool = false;

 #[derive(Default, Debug)]
 pub struct EventMessageProcessor;

Then use it in the code:

-        let historical = false;
+        let historical = DEFAULT_HISTORICAL_FLAG;
         db.set_event_message(entity, event_id, block_timestamp, historical).await?;
crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo (2)

71-81: Ohayo! Clean implementation for ABI inclusion.

The implementation effectively ensures the Event struct is included in the ABI. However, we could make the intention even clearer with a more descriptive variable name.

Consider this minor improvement:

-        fn ensure_abi(self: @ContractState, event: $type_name$) {
-            let _event = event;
+        fn ensure_abi(self: @ContractState, event: $type_name$) {
+            let _unused_event = event;

71-81: Ohayo sensei! Good architectural direction.

The removal of historical functionality from the event system and its delegation to Torii configuration, combined with this ABI enhancement, creates a cleaner separation of concerns. This aligns well with the PR's objective of optimizing batch operations.

crates/dojo/core/src/world/errors.cairo (1)

Line range hint 1-100: Ohayo sensei! Excellent error handling patterns throughout the file!

The error handling implementation demonstrates consistent patterns, clear messaging, and proper use of string formatting. The new lengths_mismatch function integrates seamlessly with the existing error handling approach.

Consider documenting these error patterns in a developer guide to maintain consistency as more batch operations are added.

crates/dojo/core-cairo-test/src/tests/world/storage.cairo (3)

5-30: Consider adding edge case tests, sensei!

While the basic CRUD operations are well-tested, consider adding test cases for:

  • Invalid addresses
  • Boundary values for a and b fields

81-128: Similar improvements needed here too, sensei!

The test provides good coverage for non-copiable types, but has the same opportunities for improvement as the previous test:

  1. Remove redundant if/else branches
  2. Remove unnecessary comment about desnapping
  3. Consider extracting magic numbers

Additionally, great job testing both empty array and empty string as default values!


1-128: Ohayo! Overall excellent test coverage, sensei!

The tests thoroughly validate the ModelStorage functionality, particularly the new batch operations capability mentioned in the PR objectives. They cover both copiable and non-copiable models, and verify the complete lifecycle of models including writing, reading, and erasing.

While there are some minor opportunities for improvement in code structure, the tests are robust and well-designed.

Consider adding performance tests to measure the efficiency gains from batch operations compared to individual operations, as this was one of the key objectives of the PR.

bin/sozo/tests/test_data/policies.json (1)

47-93: Ohayo sensei! New batch operations align well with PR objectives.

The introduction of batch operations (emit_events, set_entities, delete_entities) aligns perfectly with the PR's goal of reducing permission check overhead. These methods will help optimize performance when dealing with multiple entities simultaneously.

Consider implementing rate limiting or size constraints for these batch operations to prevent potential DoS vectors from extremely large batches.

Also applies to: 99-109

crates/torii/types-test/src/contracts.cairo (2)

Line range hint 116-127: Ohayo sensei! The delete implementation needs some love!

The current implementation has several potential issues:

  1. The subrecord ID calculation (record_id + 1) assumes sequential IDs, which might not always be true
  2. Missing error handling for non-existent records
  3. No events are emitted for deletion tracking

Consider this improved implementation:

 fn delete(ref self: ContractState, record_id: u32) {
     let mut world = self.world(@"types_test");
+    // Verify record exists before proceeding
+    match world.try_read_model::<Record>(record_id) {
+        Option::Some(record) => {
+            let record_sibling: RecordSibling = world.read_model(record_id);
+            // Read subrecord using the stored ID from the main record
+            let subrecord: Subrecord = world.read_model((record_id, record.subrecord_id));
 
-    let record: Record = world.read_model(record_id);
-    let record_sibling: RecordSibling = world.read_model(record_id);
+            world.erase_model(@record);
+            world.erase_model(@record_sibling);
+            world.erase_model(@subrecord);
 
-    let subrecord_id = record_id + 1;
-    let subrecord: Subrecord = world.read_model((record_id, subrecord_id));
+            // Emit deletion event
+            world.emit_event(
+                @RecordDeleted { record_id }
+            );
+        },
+        Option::None => {
+            panic!("Record not found");
+        }
+    }
-    world.erase_model(@record);
-    world.erase_model(@record_sibling);
-    world.erase_model(@subrecord);
 }

Line range hint 116-127: Consider implementing batch operations for better performance

Ohayo sensei! Since this PR aims to support batching entities and reduce permission check overhead, consider implementing batch operations for model deletions. Instead of individual erase_model calls, you could:

  1. Collect all models to be deleted in a batch
  2. Implement a batch deletion operation
  3. Emit a single batch deletion event

This would align better with the PR's objective of reducing permission check overhead.

Would you like me to help design the batch deletion implementation?

crates/dojo/lang/src/attribute_macros/event.rs (1)

Line range hint 65-82: Robust event validation maintained, excellent work sensei!

The strict validation requiring both key and non-key members is crucial for maintaining data integrity in the batch processing context. This helps ensure that events remain properly structured even when processed in batches.

Consider documenting these validation requirements in the module-level documentation to help other developers understand the event structure requirements.

crates/dojo/core-cairo-test/src/tests/helpers.cairo (1)

29-36: Ohayo sensei! The NotCopiable struct looks well-designed!

The struct effectively demonstrates handling of non-copyable types in batch operations, which aligns perfectly with the PR's objectives. The choice of Array and ByteArray as fields provides good coverage for testing complex data structures.

Consider adding a comment explaining that this struct serves as a test case for batch operations with non-copyable types, to help other developers understand its purpose in the test suite.

bin/sozo/src/commands/events.rs (1)

Line range hint 350-370: Ohayo! Let's enhance the value printing for better readability, sensei!

I noticed a couple of TODOs related to value printing:

  1. Model value implementation and printing for StoreUpdateRecord
  2. Pretty printing of values for StoreUpdateMember

These improvements would enhance the readability of the event output.

Would you like me to help implement these pretty printing features or create GitHub issues to track them?

crates/dojo/core/src/model/storage.cairo (2)

64-66: Ohayo, sensei! Optimize read_values_from_ids for large datasets

When retrieving multiple model values using read_values_from_ids, consider the performance implications with large spans. Optimizing with asynchronous handling or batching may improve efficiency.


114-115: Ohayo, sensei! Enhance error handling in write_values_from_ids_test

Consider adding error handling for invalid entity_ids in write_values_from_ids_test to improve the robustness of your tests.

crates/dojo/core/src/world/iworld.cairo (2)

133-141: Clarify 'emit_events' parameters for better understanding, sensei

Ohayo! Consider specifying in the documentation that event_selector applies to all batched events in emit_events. This will help future developers understand that the method emits multiple events of the same type.


169-170: Unify terminology: 'indexes' or 'indices', sensei?

Ohayo! To maintain consistency, please use either 'indexes' or 'indices' in both the documentation and parameter names for the entities method. Currently, the documentation refers to indices while the parameter is named indexes.

Also applies to: 172-173

crates/dojo/core/src/world/storage.cairo (5)

154-167: Ensure consistency in erase_models function

Ohayo, sensei! In the erase_models function, verifying that all models are successfully erased would improve reliability. Consider adding error handling to confirm each deletion, allowing for proper handling in cases where some models might not be found or cannot be deleted.


182-201: Check for existence before erasing in erase_models_ptrs

Ohayo, sensei! When erasing models using pointers, it's prudent to check if each model exists before attempting deletion. This can prevent unnecessary errors and provide clearer feedback on which models were successfully erased.


376-381: Optimize write_models_test with batch processing

Ohayo, sensei! In write_models_test, you're looping through models and calling write_model_test individually. To improve efficiency, consider implementing batch processing similar to write_models to reduce overhead during tests.


395-400: Enhance erase_models_test with error handling

Ohayo, sensei! Incorporating error handling in erase_models_test would make testing more robust by ensuring that any issues during model deletion are captured and can be addressed promptly.


418-443: Simplify erase_models_ptrs_test loop

Ohayo, sensei! The loop in erase_models_ptrs_test could be simplified for better readability by iterating directly over ids without building an intermediate array.

Here's a suggested refactor:

-            let mut ids: Array<felt252> = array![];
-            for p in ptrs {
-                ids
-                    .append(
-                        match p {
-                            ModelPtr::Id(id) => *id,
-                            ModelPtr::Keys(keys) => entity_id_from_keys(*keys),
-                        }
-                    );
-            };
-
-            let world_test = dojo::world::IWorldTestDispatcher {
-                contract_address: self.dispatcher.contract_address
-            };
-
-            for i in ids {
+            let world_test = dojo::world::IWorldTestDispatcher {
+                contract_address: self.dispatcher.contract_address
+            };
+            for p in ptrs {
+                let i = match p {
+                    ModelPtr::Id(id) => *id,
+                    ModelPtr::Keys(keys) => entity_id_from_keys(*keys),
+                };
                 dojo::world::IWorldTestDispatcherTrait::delete_entity_test(
                     world_test,
                     Model::<M>::selector(self.namespace_hash),
                     ModelIndex::Id(i),
                     Model::<M>::layout()
                 );
             }
crates/dojo/core/src/world/world_contract.cairo (4)

800-838: Ohayo sensei! Simplify the loop in emit_events function

To improve readability and maintain consistency, consider replacing the manual loop with a for loop.

Apply this diff to simplify the loop:

             if keys.len() != values.len() {
                 panic_with_byte_array(
                     @errors::lengths_mismatch(@"keys", @"values", @"emit_events")
                 );
             }

-            let mut i = 0;
-            loop {
-                if i >= keys.len() {
-                    break;
-                }
-
-                self
-                    .emit(
-                        EventEmitted {
-                            selector: event_selector,
-                            system_address: get_caller_address(),
-                            keys: *keys[i],
-                            values: *values[i],
-                        }
-                    );
-
-                i += 1;
-            }
+            for i in 0..keys.len() {
+                self
+                    .emit(
+                        EventEmitted {
+                            selector: event_selector,
+                            system_address: get_caller_address(),
+                            keys: *keys[i],
+                            values: *values[i],
+                        }
+                    );
+            }

846-856: Ohayo sensei! Consider preallocating the array in entities function

To improve performance, you can initialize the array with the capacity of indexes.len().

Apply this diff to preallocate the array:

             fn entities(
                 self: @ContractState, model_selector: felt252, indexes: Span<ModelIndex>, layout: Layout
             ) -> Span<Span<felt252>> {
-                let mut models: Array<Span<felt252>> = array![];
+                let mut models: Array<Span<felt252>> = Array::with_capacity(indexes.len());

                 for i in indexes {
                     models.append(self.get_entity_internal(model_selector, *i, layout));
                 };

                 models.span()
             }

875-906: Ohayo sensei! Simplify the loop in set_entities function

Similar to the previous suggestion, replacing the manual loop with a for loop can enhance readability.

Apply this diff to simplify the loop:

             if indexes.len() != values.len() {
                 panic_with_byte_array(
                     @errors::lengths_mismatch(@"indexes", @"values", @"set_entities")
                 );
             }

-            let mut i = 0;
-            loop {
-                if i >= indexes.len() {
-                    break;
-                }
-
-                self.set_entity_internal(model_selector, *indexes[i], *values[i], layout);
-
-                i += 1;
-            };
+            for i in 0..indexes.len() {
+                self.set_entity_internal(model_selector, *indexes[i], *values[i], layout);
+            };

921-939: Ohayo sensei! Simplify the loop in delete_entities function

Updating the loop structure can improve code clarity.

Apply this diff to simplify the loop:

                 if let Resource::Model((_, _)) = self.resources.read(model_selector) {
                     self.assert_caller_permissions(model_selector, Permission::Writer);
 
-                    for i in indexes {
-                        self.delete_entity_internal(model_selector, *i, layout);
-                    }
+                    for i in indexes {
+                        self.delete_entity_internal(model_selector, *i, layout);
+                    }
                 } else {
                     panic_with_byte_array(
                         @errors::resource_conflict(@format!("{model_selector}"), @"model")
                     );
                 }
crates/dojo/world/src/contracts/abigen/world.rs (2)

3228-3247: Add documentation comments for the entities method

Ohayo sensei! The entities method lacks Rust doc comments. Adding them would enhance code readability and assist other developers in understanding its purpose and usage.


4079-4098: Consider adding emit_events method to WorldContractReader for consistency

While emit_events has been added to WorldContract, adding it to WorldContractReader would maintain consistency and could be beneficial for read-only batch operations.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 92cfad0 and 2abf09e.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • spawn-and-move-db.tar.gz is excluded by !**/*.gz
  • types-test-db.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (25)
  • Cargo.toml (0 hunks)
  • bin/sozo/src/commands/events.rs (1 hunks)
  • bin/sozo/tests/test_data/policies.json (1 hunks)
  • crates/dojo/core-cairo-test/src/lib.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/event/event.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/helpers.cairo (2 hunks)
  • crates/dojo/core-cairo-test/src/tests/world/storage.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/world/world.cairo (0 hunks)
  • crates/dojo/core/src/event/event.cairo (0 hunks)
  • crates/dojo/core/src/event/interface.cairo (0 hunks)
  • crates/dojo/core/src/lib.cairo (0 hunks)
  • crates/dojo/core/src/model/model.cairo (0 hunks)
  • crates/dojo/core/src/model/model_value.cairo (0 hunks)
  • crates/dojo/core/src/model/storage.cairo (4 hunks)
  • crates/dojo/core/src/world/errors.cairo (1 hunks)
  • crates/dojo/core/src/world/iworld.cairo (5 hunks)
  • crates/dojo/core/src/world/storage.cairo (12 hunks)
  • crates/dojo/core/src/world/world_contract.cairo (5 hunks)
  • crates/dojo/lang/src/attribute_macros/event.rs (1 hunks)
  • crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo (1 hunks)
  • crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo (0 hunks)
  • crates/dojo/world/src/contracts/abigen/world.rs (6 hunks)
  • crates/torii/core/src/processors/event_message.rs (1 hunks)
  • crates/torii/types-test/src/contracts.cairo (1 hunks)
  • examples/spawn-and-move/dojo_dev.toml (1 hunks)
💤 Files with no reviewable changes (8)
  • Cargo.toml
  • crates/dojo/core-cairo-test/src/tests/world/world.cairo
  • crates/dojo/core/src/event/event.cairo
  • crates/dojo/core/src/event/interface.cairo
  • crates/dojo/core/src/lib.cairo
  • crates/dojo/core/src/model/model.cairo
  • crates/dojo/core/src/model/model_value.cairo
  • crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo
✅ Files skipped from review due to trivial changes (1)
  • examples/spawn-and-move/dojo_dev.toml
🔇 Additional comments (25)
crates/dojo/core-cairo-test/src/lib.cairo (1)

50-50: Ohayo! The storage module addition looks good, sensei!

The new storage module within world aligns perfectly with the PR's objective of implementing batch entities functionality, providing a proper testing structure for the new features.

crates/dojo/core/src/world/errors.cairo (1)

5-7: Ohayo! Clean implementation of the length mismatch error formatter!

The new lengths_mismatch function aligns perfectly with the PR's batch operations feature and follows the established error formatting patterns in the codebase. The error message is clear and provides good context for debugging.

Let's verify its usage in batch operations:

✅ Verification successful

Ohayo! The lengths_mismatch error function is correctly used in batch operations!

The verification shows that the error function is properly integrated into batch operations:

  • Used in set_entities to validate that indexes and values arrays have matching lengths
  • Part of the delete_entities context, maintaining consistency in batch operations error handling

The implementation serves its intended purpose in the batch operations feature, providing clear error messages when array lengths don't match.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find usages of lengths_mismatch in batch-related functions
rg -l "lengths_mismatch" | xargs rg -A 5 "batch|set_entities|delete_entities"

Length of output: 1620

crates/dojo/core-cairo-test/src/tests/world/storage.cairo (1)

1-3: Ohayo! Clean and focused imports, sensei!

The imports are well-organized and include only the necessary components for the tests.

bin/sozo/tests/test_data/policies.json (3)

3-39: Address consolidation pattern requires verification.

Many methods are now pointing to a centralized target address (0x4bf1624...). While this consolidation might simplify management, it's crucial to ensure proper access controls are in place.

Let's verify the contract at this address:

#!/bin/bash
# Search for contract declarations or implementations
ast-grep --pattern 'contract World {
  $$$
}'

# Search for access control implementations
rg -A 5 "access_control" 

Also applies to: 43-87, 127-127


91-93: Verify emit_events implementation for event ordering.

The new emit_events method should maintain proper event ordering and atomicity.

Let's check the implementation:

✅ Verification successful

Event ordering and atomicity are properly implemented in emit_events, sensei!

The implementation in world_contract.cairo shows proper handling of event ordering and atomicity through:

  • Validation of matching lengths between keys and values
  • Sequential processing of events in a deterministic loop
  • Permission checks before event emission
  • Atomic transaction handling via the contract state
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for emit_events implementation
ast-grep --pattern 'fn emit_events($$$) {
  $$$
}'

Length of output: 231


Script:

#!/bin/bash
# Let's try a different approach to find emit_events implementation
# First, let's use ripgrep to find files containing emit_events
rg -l "emit_events" 

# Then let's see the actual implementation with context
rg "emit_events" -A 10

Length of output: 7159


111-124: New permission management methods enhance security model.

The addition of granular permission management methods (grant_owner, revoke_owner, grant_writer, revoke_writer) provides better access control capabilities.

Let's verify the permission hierarchy implementation:

✅ Verification successful

Ohayo sensei! Based on the code analysis, I can now provide a conclusive response:

Permission management implementation is properly integrated

The codebase shows a complete implementation of the permission system with:

  • Full grant/revoke functionality for both owners and writers in the World contract
  • Integration in the auth module for permission management operations
  • Proper test coverage in multiple test files
  • Usage across different parts of the system (sozo, torii, dojo)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for owner/writer permission checks in the codebase
rg -A 3 "check_(owner|writer)_permission" 

Length of output: 43


Script:

#!/bin/bash
# Let's search for permission-related functions and methods in the codebase
rg -A 5 "(grant|revoke)_(owner|writer)" --type rust

# Also search for any permission-related structs or traits
ast-grep --pattern 'trait $_ {
  $$$
  fn $_(owner|writer)$_ {
    $$$
  }
  $$$
}'

# Look for permission checks in a different way
rg -A 3 "has_(owner|writer)_permission" --type rust

Length of output: 19853

crates/torii/types-test/src/contracts.cairo (1)

Line range hint 18-26: Ohayo! Nice addition of Serde derive!

The addition of Serde derive to RecordLogged enhances the struct's serialization capabilities while maintaining proper event structure with key fields. This aligns well with the PR's objective of ensuring event structure in the ABI.

crates/dojo/lang/src/attribute_macros/event.rs (2)

13-13: Ohayo! Clean import optimizations look good, sensei!

The streamlined imports align perfectly with the removal of the historical parameters functionality.

Also applies to: 16-16, 20-20


Line range hint 31-144: Verify impact of version removal across the system, sensei!

While the removal of version tracking aligns with the PR objectives, we should verify that this doesn't impact event consumers.

crates/dojo/core-cairo-test/src/tests/helpers.cairo (1)

220-223: The world deployment setup is properly updated, sensei!

The NotCopiable model is correctly registered in the test world setup, enabling comprehensive testing of batch operations with non-copyable types.

Let's verify that the NotCopiable model is used in corresponding test cases:

✅ Verification successful

Verification complete, all is well, sensei!

The NotCopiable model is properly used in test cases, specifically in storage.cairo where it's thoroughly tested in the write_multiple_not_copiable function. The test validates:

  • Writing multiple NotCopiable models
  • Reading the models back
  • Proper model erasure
  • Correct handling of non-copyable types in batch operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases using NotCopiable
rg -l "NotCopiable" --type cairo

Length of output: 62


Script:

#!/bin/bash
# Search for NotCopiable in all files
rg -l "NotCopiable"

Length of output: 129


Script:

#!/bin/bash
# Find cairo files and search for NotCopiable
fd -e cairo | xargs rg -l "NotCopiable"

Length of output: 149


Script:

#!/bin/bash
# Find cairo files and show context around NotCopiable usage
fd -e cairo | xargs rg -C 3 "NotCopiable"

Length of output: 5136

bin/sozo/src/commands/events.rs (1)

348-348: Ohayo! The event output format update looks good, sensei!

The removal of the historical field from the event output format aligns perfectly with the PR's objective of removing historical aspects from the chain. The change maintains all essential event information while streamlining the output.

crates/dojo/core/src/model/storage.cairo (6)

37-39: Ohayo, sensei! Ensure consistency in batch delete with erase_models

The erase_models method aligns with the batch processing implementation. Verify that deleting multiple models does not lead to inconsistent states if some deletions fail.

Consider implementing transactional behavior or rollback mechanisms for batch deletions.


56-60: Ohayo, sensei! Consistent generic constraints in read_values

The method read_values correctly extends the functionality for batch reads. Ensure that the generic constraints are consistent with other methods to prevent type mismatches.


89-90: Ohayo, sensei! Comprehensive testing in write_models_test

The addition of write_models_test is excellent for testing batch writes. Ensure that tests cover diverse scenarios, including error handling for partial successes.


93-94: Ohayo, sensei! Verify complete deletion in erase_models_test

In erase_models_test, confirm that all specified models are successfully deleted and that the method handles non-existent models gracefully.

Do you need assistance in creating test cases for these scenarios?


97-98: Ohayo, sensei! Maintain type integrity in erase_models_ptrs_test

Ensure that erase_models_ptrs_test maintains type integrity when deleting models by pointers in a test environment.


44-46: Ohayo, sensei! Confirm type safety in erase_models_ptrs

Ensure that ModelPtr<M> provides adequate type inference and that the method correctly handles different pointer types during batch deletions.

✅ Verification successful

Let me gather more information about the ModelPtr type and its usage to ensure type safety.


Ohayo! Type safety in erase_models_ptrs is properly maintained, sensei!

The implementation shows that ModelPtr<M> is a well-defined enum with proper type handling:

  • It correctly handles both Id and Keys variants in the implementation
  • The generic parameter M is consistently used for type inference
  • The world storage implementation properly matches and processes both pointer types during batch deletions
  • Type safety is enforced through the trait interface and its implementations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for correct usage of `erase_models_ptrs` with various `ModelPtr<M>` types.

# Expected: Consistent usage without type inference issues.
rg 'erase_models_ptrs' -A 3

Length of output: 1359


Script:

#!/bin/bash
# Check ModelPtr definition and implementation
ast-grep --pattern 'struct ModelPtr { $$$ }'

# Check for ModelPtr usage patterns
rg "ModelPtr" -B 2 -A 2

# Look for any type-related implementations or traits for ModelPtr
ast-grep --pattern 'impl $_ of $_ for ModelPtr { $$$ }'

Length of output: 6952

crates/dojo/core/src/world/iworld.cairo (4)

130-131: Excellent adjustment in 'emit_event', sensei!

Ohayo! Removing the historical parameter streamlines the method and aligns with the updated event handling strategy.


191-207: Efficient batching in 'set_entities', sensei!

Ohayo! The introduction of set_entities enhances performance by batching writes and reducing permission checks. Great job optimizing the system!


218-229: Smart addition of 'delete_entities', sensei!

Ohayo! Implementing delete_entities improves efficiency by batching deletions. This aligns well with the PR objectives to reduce overhead.


311-311: Good alignment of 'emit_event_test', sensei!

Ohayo! The changes to emit_event_test correctly reflect the updates made to emit_event, ensuring consistency in the test interface.

crates/dojo/core/src/world/world_contract.cairo (3)

307-307: Ohayo sensei! Confirming the correctness of the event emission

The added line correctly includes system_address: get_caller_address() in the EventEmitted struct. This ensures that the system address is accurately captured when emitting events during tests.


843-843: Ohayo sensei! Confirming the use of internal method in entity

The refactoring to use self.get_entity_internal enhances code reusability and maintains consistency.


1183-1210: Ohayo sensei! Confirming the implementation of get_entity_internal

The get_entity_internal function correctly handles the different ModelIndex variants and retrieves the appropriate entity data.

crates/dojo/world/src/contracts/abigen/world.rs (1)

3455-3491: Verify the correctness of batch event emission in emit_events methods

Ohayo sensei! Ensure that the new emit_events methods correctly handle batch event emissions without side effects or unexpected behaviors.

Run the following script to verify uses of emit_events:

✅ Verification successful

Let me gather more context about the event emission implementation and usage.


Let me gather more specific information about the event emission implementation.


Batch event emission implementation is correctly structured

Ohayo sensei! After analyzing the codebase, I can confirm that the emit_events implementation is correct and safe:

  • The method properly serializes event data using CairoSerde
  • Parameters are correctly typed with Vec<Vec<starknet::core::types::Felt>> for batch processing
  • The implementation follows the same pattern as the single event emission
  • Proper clippy allowances are in place for valid cases
  • The method correctly creates and executes the call via the account abstraction
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that `emit_events` is properly used throughout the codebase
# Expected: All batch event emissions use `emit_events` correctly

# Search for all `emit_events` function calls
rg 'emit_events\(' -t rust -A 3

# Ensure that the parameters passed match the expected types and lengths

Length of output: 372


Script:

#!/bin/bash
# Search for the World contract implementation and event-related code
ast-grep --pattern 'struct World {
  $$$
}'

# Look for event-related tests
rg 'test.*emit.*event' -t rust -A 5

# Find any event emission related implementations
rg 'fn.*emit' -t rust -A 3

# Look for actual usage of emit_events in the codebase
rg '\.emit_events\(' -t rust -A 3

Length of output: 2220


Script:

#!/bin/bash
# Look for test cases that specifically use emit_events
rg 'emit_events\(' -t rust -B 5 -A 10

# Check for any error handling or validation around event emission
ast-grep --pattern 'fn emit_events($$$) {
  $$$
}'

# Look for any related event structs or types
rg 'struct.*Event' -t rust -A 5

# Search for any comments or documentation about event emission
rg '//.*emit.*event' -t rust
rg '/\*.*emit.*event.*\*/' -t rust

Length of output: 17122

Comment on lines +32 to +79
#[test]
fn write_multiple_copiable() {
let (mut world, _) = deploy_world_and_foo();

let mut models_snaps: Array<@Foo> = array![];
let mut keys: Array<starknet::ContractAddress> = array![];

for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
keys.append(caller);

if i % 2 == 0 {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
} else {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
}
};

world.write_models(models_snaps.span());

let mut models: Array<Foo> = world.read_models(keys.span());

assert_eq!(models.len(), 10);

for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
// Can desnap as copiable.
let model: Foo = *models[i.try_into().unwrap()];
assert_eq!(model.caller, caller);
assert_eq!(model.a, felt);
assert_eq!(model.b, i);
};

world.erase_models(models_snaps.span());

let mut models: Array<Foo> = world.read_models(keys.span());

while let Option::Some(m) = models.pop_front() {
assert_eq!(m.a, 0);
assert_eq!(m.b, 0);
};
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo! Let's enhance the test structure, sensei!

A few suggestions to improve the test:

  1. Consider extracting the magic number 10 into a constant
  2. The if/else branches contain identical code, making the condition unnecessary
  3. The comment "Can desnap as copiable" is redundant given the type information

Here's a suggested refactor for the redundant if/else:

-            if i % 2 == 0 {
-                let foo = Foo { caller, a: felt, b: i };
-                models_snaps.append(@foo);
-            } else {
-                let foo = Foo { caller, a: felt, b: i };
-                models_snaps.append(@foo);
-            }
+            let foo = Foo { caller, a: felt, b: i };
+            models_snaps.append(@foo);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[test]
fn write_multiple_copiable() {
let (mut world, _) = deploy_world_and_foo();
let mut models_snaps: Array<@Foo> = array![];
let mut keys: Array<starknet::ContractAddress> = array![];
for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
keys.append(caller);
if i % 2 == 0 {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
} else {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
}
};
world.write_models(models_snaps.span());
let mut models: Array<Foo> = world.read_models(keys.span());
assert_eq!(models.len(), 10);
for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
// Can desnap as copiable.
let model: Foo = *models[i.try_into().unwrap()];
assert_eq!(model.caller, caller);
assert_eq!(model.a, felt);
assert_eq!(model.b, i);
};
world.erase_models(models_snaps.span());
let mut models: Array<Foo> = world.read_models(keys.span());
while let Option::Some(m) = models.pop_front() {
assert_eq!(m.a, 0);
assert_eq!(m.b, 0);
};
}
#[test]
fn write_multiple_copiable() {
let (mut world, _) = deploy_world_and_foo();
let mut models_snaps: Array<@Foo> = array![];
let mut keys: Array<starknet::ContractAddress> = array![];
for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
keys.append(caller);
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
};
world.write_models(models_snaps.span());
let mut models: Array<Foo> = world.read_models(keys.span());
assert_eq!(models.len(), 10);
for i in 0_u128
..10_u128 {
let felt: felt252 = i.into();
let caller: starknet::ContractAddress = felt.try_into().unwrap();
let model: Foo = *models[i.try_into().unwrap()];
assert_eq!(model.caller, caller);
assert_eq!(model.a, felt);
assert_eq!(model.b, i);
};
world.erase_models(models_snaps.span());
let mut models: Array<Foo> = world.read_models(keys.span());
while let Option::Some(m) = models.pop_front() {
assert_eq!(m.a, 0);
assert_eq!(m.b, 0);
};
}

Comment on lines +23 to +25
/// Sets multiple models of type `M`.
fn write_models(ref self: S, models: Span<@M>);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Implement error handling for batch writes

The write_models method enhances efficiency by allowing batch writing of models. However, consider implementing error handling for partial failures to maintain data integrity during batch operations.

Comment on lines +29 to +33
/// Retrieves multiple models of type `M` using the provided keys of type `K`.
/// Returnes an array to ensure the user can consume the models, even if the type is not
/// copiable.
fn read_models<K, +Drop<K>, +Serde<K>>(self: @S, keys: Span<K>) -> Array<M>;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ohayo, sensei! Handle deserialization errors in read_models

When reading multiple models with read_models, ensure that you handle potential deserialization errors gracefully. Returning an array might obscure failures if some models cannot be deserialized.

Would you like assistance in enhancing error handling for partial deserialization failures?

Comment on lines +70 to +74
/// Updates multiple model values of type `V`.
fn write_values<K, +Drop<K>, +Serde<K>, +ModelValueKey<V, K>>(
ref self: S, keys: Span<K>, values: Span<@V>
);

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ohayo, sensei! Validate matching lengths in write_values

Ensure that the lengths of keys and values in the write_values method match. Mismatched lengths could lead to indexing errors or unintended behavior.

Comment on lines +78 to +79
/// Updates multiple model values of type `V`.
fn write_values_from_ids(ref self: S, entity_ids: Span<felt252>, values: Span<@V>);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Error handling in write_values_from_ids

Implement validation to confirm that all entity_ids are valid before writing values. This prevents potential runtime errors and maintains data integrity.

Comment on lines +484 to +496
fn write_values_from_ids_test(
ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>
) {
let mut i = 0;
loop {
if i >= entity_ids.len() {
break;
}

dojo::world::IWorldTestDispatcherTrait::delete_entity_test(
world_test,
ModelValue::<V>::selector(self.namespace_hash),
ModelIndex::Id(entity_id),
ModelValue::<V>::layout()
);
Self::write_value_from_id_test(ref self, *entity_ids[i], *values[i]);

i += 1;
}
Copy link

@coderabbitai coderabbitai bot Nov 5, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent index errors in write_values_from_ids_test

Ohayo, sensei! Similar to previous suggestions, in write_values_from_ids_test, verifying that entity_ids and values have matching lengths will enhance test reliability and prevent runtime errors.

Suggested addition:

+            if entity_ids.len() != values.len() {
+                panic!("Entity IDs and values must have the same length for testing");
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn write_values_from_ids_test(
ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>
) {
let mut i = 0;
loop {
if i >= entity_ids.len() {
break;
}
dojo::world::IWorldTestDispatcherTrait::delete_entity_test(
world_test,
ModelValue::<V>::selector(self.namespace_hash),
ModelIndex::Id(entity_id),
ModelValue::<V>::layout()
);
Self::write_value_from_id_test(ref self, *entity_ids[i], *values[i]);
i += 1;
}
fn write_values_from_ids_test(
ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>
) {
if entity_ids.len() != values.len() {
panic!("Entity IDs and values must have the same length for testing");
}
let mut i = 0;
loop {
if i >= entity_ids.len() {
break;
}
Self::write_value_from_id_test(ref self, *entity_ids[i], *values[i]);
i += 1;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not required for the tests API.

Copy link

Choose a reason for hiding this comment

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

@glihm, understood. I'll note that the length check is not required for the tests API.


✏️ Learnings added
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/core/src/world/storage.cairo:484-0
Timestamp: 2024-11-05T04:29:12.152Z
Learning: In the Cairo codebase for the Dojo project, within `crates/dojo/core/src/world/storage.cairo`, length checks between `entity_ids` and `values` are not required in test API functions like `write_values_from_ids_test`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +313 to +337

fn write_values_from_ids(ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>) {
let mut indexes: Array<ModelIndex> = array![];
let mut all_values: Array<Span<felt252>> = array![];
let mut i = 0;

loop {
if i >= entity_ids.len() {
break;
}

indexes.append(ModelIndex::Id(*entity_ids[i]));
all_values.append(ModelValue::<V>::values(*values[i]));

i += 1;
};

IWorldDispatcherTrait::set_entities(
self.dispatcher,
ModelValue::<V>::selector(self.namespace_hash),
indexes.span(),
all_values.span(),
ModelValue::<V>::layout()
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure synchronized lengths in write_values_from_ids

Ohayo, sensei! The write_values_from_ids function assumes that entity_ids and values are of equal length. Adding a check to confirm this would prevent indexing errors and enhance reliability.

Suggested addition:

+            if entity_ids.len() != values.len() {
+                panic!("Entity IDs and values must have the same length");
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn write_values_from_ids(ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>) {
let mut indexes: Array<ModelIndex> = array![];
let mut all_values: Array<Span<felt252>> = array![];
let mut i = 0;
loop {
if i >= entity_ids.len() {
break;
}
indexes.append(ModelIndex::Id(*entity_ids[i]));
all_values.append(ModelValue::<V>::values(*values[i]));
i += 1;
};
IWorldDispatcherTrait::set_entities(
self.dispatcher,
ModelValue::<V>::selector(self.namespace_hash),
indexes.span(),
all_values.span(),
ModelValue::<V>::layout()
);
}
fn write_values_from_ids(ref self: WorldStorage, entity_ids: Span<felt252>, values: Span<@V>) {
if entity_ids.len() != values.len() {
panic!("Entity IDs and values must have the same length");
}
let mut indexes: Array<ModelIndex> = array![];
let mut all_values: Array<Span<felt252>> = array![];
let mut i = 0;
loop {
if i >= entity_ids.len() {
break;
}
indexes.append(ModelIndex::Id(*entity_ids[i]));
all_values.append(ModelValue::<V>::values(*values[i]));
i += 1;
};
IWorldDispatcherTrait::set_entities(
self.dispatcher,
ModelValue::<V>::selector(self.namespace_hash),
indexes.span(),
all_values.span(),
ModelValue::<V>::layout()
);
}

Comment on lines +242 to +278
fn read_values_from_ids(self: @WorldStorage, entity_ids: Span<felt252>) -> Array<V> {
let mut indexes: Array<ModelIndex> = array![];
for id in entity_ids {
indexes.append(ModelIndex::Id(*id));
};

let mut all_values = IWorldDispatcherTrait::entities(
*self.dispatcher,
ModelValue::<V>::selector(*self.namespace_hash),
indexes.span(),
ModelValue::<V>::layout()
);

let mut values: Array<V> = array![];
let mut i = 0;
loop {
if i >= indexes.len() {
break;
}

let entity_id = *entity_ids[i];
let mut v = *all_values[i];

match ModelValue::<V>::from_values(entity_id, ref v) {
Option::Some(value) => values.append(value),
Option::None => {
panic!(
"Value: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct."
)
}
}

i += 1;
};

values
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add length check in read_values_from_ids to prevent indexing errors

Ohayo, sensei! In the read_values_from_ids function, there's a potential risk of index out-of-bounds errors if entity_ids and all_values lengths mismatch. Consider adding a length check before the loop to ensure they are equal.

Here's a suggested addition:

+            if entity_ids.len() != all_values.len() {
+                panic!("Mismatch between entity_ids and retrieved values lengths");
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn read_values_from_ids(self: @WorldStorage, entity_ids: Span<felt252>) -> Array<V> {
let mut indexes: Array<ModelIndex> = array![];
for id in entity_ids {
indexes.append(ModelIndex::Id(*id));
};
let mut all_values = IWorldDispatcherTrait::entities(
*self.dispatcher,
ModelValue::<V>::selector(*self.namespace_hash),
indexes.span(),
ModelValue::<V>::layout()
);
let mut values: Array<V> = array![];
let mut i = 0;
loop {
if i >= indexes.len() {
break;
}
let entity_id = *entity_ids[i];
let mut v = *all_values[i];
match ModelValue::<V>::from_values(entity_id, ref v) {
Option::Some(value) => values.append(value),
Option::None => {
panic!(
"Value: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct."
)
}
}
i += 1;
};
values
}
fn read_values_from_ids(self: @WorldStorage, entity_ids: Span<felt252>) -> Array<V> {
let mut indexes: Array<ModelIndex> = array![];
for id in entity_ids {
indexes.append(ModelIndex::Id(*id));
};
let mut all_values = IWorldDispatcherTrait::entities(
*self.dispatcher,
ModelValue::<V>::selector(*self.namespace_hash),
indexes.span(),
ModelValue::<V>::layout()
);
if entity_ids.len() != all_values.len() {
panic!("Mismatch between entity_ids and retrieved values lengths");
}
let mut values: Array<V> = array![];
let mut i = 0;
loop {
if i >= indexes.len() {
break;
}
let entity_id = *entity_ids[i];
let mut v = *all_values[i];
match ModelValue::<V>::from_values(entity_id, ref v) {
Option::Some(value) => values.append(value),
Option::None => {
panic!(
"Value: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct."
)
}
}
i += 1;
};
values
}

Comment on lines +3338 to +3374
pub fn delete_entities_getcall(
&self,
model_selector: &starknet::core::types::Felt,
indexes: &Vec<ModelIndex>,
layout: &Layout,
) -> starknet::core::types::Call {
use cainome::cairo_serde::CairoSerde;
let mut __calldata = vec![];
__calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));
__calldata.extend(Vec::<ModelIndex>::cairo_serialize(indexes));
__calldata.extend(Layout::cairo_serialize(layout));
starknet::core::types::Call {
to: self.address,
selector: starknet::macros::selector!("delete_entities"),
calldata: __calldata,
}
}
#[allow(clippy::ptr_arg)]
#[allow(clippy::too_many_arguments)]
pub fn delete_entities(
&self,
model_selector: &starknet::core::types::Felt,
indexes: &Vec<ModelIndex>,
layout: &Layout,
) -> starknet::accounts::ExecutionV1<A> {
use cainome::cairo_serde::CairoSerde;
let mut __calldata = vec![];
__calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));
__calldata.extend(Vec::<ModelIndex>::cairo_serialize(indexes));
__calldata.extend(Layout::cairo_serialize(layout));
let __call = starknet::core::types::Call {
to: self.address,
selector: starknet::macros::selector!("delete_entities"),
calldata: __calldata,
};
self.account.execute_v1(vec![__call])
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor to reduce duplication between delete_entities and delete_entity methods

Both methods share similar logic. Consider refactoring to avoid code duplication, which will improve maintainability and adhere to the DRY principle.

Apply this diff to refactor:

-#[allow(clippy::ptr_arg)]
-#[allow(clippy::too_many_arguments)]
-pub fn delete_entities_getcall(
-    &self,
-    model_selector: &starknet::core::types::Felt,
-    indexes: &Vec<ModelIndex>,
-    layout: &Layout,
-) -> starknet::core::types::Call {
-    // Implementation
-}
-
-#[allow(clippy::ptr_arg)]
-#[allow(clippy::too_many_arguments)]
-pub fn delete_entity_getcall(
-    &self,
-    model_selector: &starknet::core::types::Felt,
-    index: &ModelIndex,
-    layout: &Layout,
-) -> starknet::core::types::Call {
-    // Similar implementation
-}
+#[allow(clippy::ptr_arg)]
+#[allow(clippy::too_many_arguments)]
+pub fn delete_entities_getcall(
+    &self,
+    model_selector: &starknet::core::types::Felt,
+    indexes: &[ModelIndex],
+    layout: &Layout,
+) -> starknet::core::types::Call {
+    // Implementation
+}
+
+pub fn delete_entity_getcall(
+    &self,
+    model_selector: &starknet::core::types::Felt,
+    index: &ModelIndex,
+    layout: &Layout,
+) -> starknet::core::types::Call {
+    self.delete_entities_getcall(model_selector, &vec![index.clone()], layout)
+}

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

Comment on lines +3809 to +3849
pub fn set_entities_getcall(
&self,
model_selector: &starknet::core::types::Felt,
indexes: &Vec<ModelIndex>,
values: &Vec<Vec<starknet::core::types::Felt>>,
layout: &Layout,
) -> starknet::core::types::Call {
use cainome::cairo_serde::CairoSerde;
let mut __calldata = vec![];
__calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));
__calldata.extend(Vec::<ModelIndex>::cairo_serialize(indexes));
__calldata.extend(Vec::<Vec<starknet::core::types::Felt>>::cairo_serialize(values));
__calldata.extend(Layout::cairo_serialize(layout));
starknet::core::types::Call {
to: self.address,
selector: starknet::macros::selector!("set_entities"),
calldata: __calldata,
}
}
#[allow(clippy::ptr_arg)]
#[allow(clippy::too_many_arguments)]
pub fn set_entities(
&self,
model_selector: &starknet::core::types::Felt,
indexes: &Vec<ModelIndex>,
values: &Vec<Vec<starknet::core::types::Felt>>,
layout: &Layout,
) -> starknet::accounts::ExecutionV1<A> {
use cainome::cairo_serde::CairoSerde;
let mut __calldata = vec![];
__calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));
__calldata.extend(Vec::<ModelIndex>::cairo_serialize(indexes));
__calldata.extend(Vec::<Vec<starknet::core::types::Felt>>::cairo_serialize(values));
__calldata.extend(Layout::cairo_serialize(layout));
let __call = starknet::core::types::Call {
to: self.address,
selector: starknet::macros::selector!("set_entities"),
calldata: __calldata,
};
self.account.execute_v1(vec![__call])
}
Copy link

@coderabbitai coderabbitai bot Nov 5, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle empty inputs in set_entities method

The set_entities method does not currently check for empty indexes or values, which could lead to runtime errors or inconsistent state.

Apply this diff to add input validation:

 pub fn set_entities_getcall(
     &self,
     model_selector: &starknet::core::types::Felt,
     indexes: &Vec<ModelIndex>,
     values: &Vec<Vec<starknet::core::types::Felt>>,
     layout: &Layout,
 ) -> starknet::core::types::Call {
+    if indexes.is_empty() || values.is_empty() {
+        panic!("Indexes and values cannot be empty");
+    }
+
     use cainome::cairo_serde::CairoSerde;
     let mut __calldata = vec![];
     __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is auto generated code.

Copy link

Choose a reason for hiding this comment

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

@glihm, ohayo sensei! Thank you for letting me know that this code is auto-generated. To prevent me from reviewing auto-generated files in the future, you can configure CodeRabbit to ignore specific paths by adding the following to your configuration:

path_filters:
  exclude:
    - 'crates/dojo/world/src/contracts/abigen/**'

This will ensure that auto-generated code in that directory is excluded from code reviews.


✏️ Learnings added
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.697Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link

codecov bot commented Nov 5, 2024

Codecov Report

Attention: Patch coverage is 2.00000% with 147 lines in your changes missing coverage. Please review.

Project coverage is 56.81%. Comparing base (92cfad0) to head (2f973a2).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
crates/dojo/world/src/contracts/abigen/world.rs 0.00% 146 Missing ⚠️
bin/sozo/src/commands/events.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2633      +/-   ##
==========================================
- Coverage   56.89%   56.81%   -0.09%     
==========================================
  Files         397      397              
  Lines       49467    49535      +68     
==========================================
- Hits        28143    28142       -1     
- Misses      21324    21393      +69     

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

Copy link

coderabbitai bot commented Nov 5, 2024

Walkthrough

Ohayo, sensei! This pull request introduces a series of changes across multiple files, focusing on enhancing dependency management, event handling, and storage capabilities within the Dojo framework. Key modifications include the activation of previously commented dependencies in Cargo.toml, the introduction of new methods for batch processing events and entities, and the removal of certain parameters related to event historical tracking. The changes aim to streamline functionality and improve the overall efficiency of the codebase.

Changes

File Change Summary
Cargo.toml Updated dependencies: scarb and scarb-ui activated from commented lines; topological-sort version set to "0.2".
bin/sozo/src/commands/events.rs Removed historical field from output in match_event function.
bin/sozo/tests/test_data/policies.json Updated target addresses for multiple methods; added new methods with target addresses.
crates/dojo/core-cairo-test/src/lib.cairo Added new module storage within world module.
crates/dojo/core-cairo-test/src/tests/event/event.cairo Added struct FooEvent with derived traits and fields.
crates/dojo/core-cairo-test/src/tests/helpers.cairo Added struct NotCopiable; updated deploy_world_and_foo function to include NotCopiable.
crates/dojo/core-cairo-test/src/tests/world/storage.cairo Introduced unit tests: write_simple, write_multiple_copiable, write_multiple_not_copiable.
crates/dojo/core/cairo/src/event/event.cairo Removed version field from EventDefinition struct and version and historical methods from Event trait.
crates/dojo/core/src/event/interface.cairo Removed version method from IEvent trait.
crates/dojo/core/src/lib.cairo Removed exports for ModelTest and ModelValueTest for testing.
crates/dojo/core/src/model/model.cairo Removed ModelTest trait and its implementation.
crates/dojo/core/src/model/model_value.cairo Removed ModelValueTest trait and its implementation.
crates/dojo/core/src/model/storage.cairo Added methods for batch operations in ModelStorage and ModelValueStorage traits.
crates/dojo/core/src/world/errors.cairo Added lengths_mismatch function for error handling.
crates/dojo/core/src/world/iworld.cairo Added methods for batch processing events and entities, updated emit_event method.
crates/dojo/core/src/world/storage.cairo Added methods for batch operations in WorldStorage.
crates/dojo/core/src/world/world_contract.cairo Added methods for batch event emission and entity management.
crates/dojo/lang/src/attribute_macros/event.rs Removed EventParameters struct and related logic.
crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo Removed version and historical methods from event implementations; added ensure_abi method.
crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo Added new struct and implementations for model handling.
crates/dojo/world/src/contracts/abigen/world.rs Added methods for batch entity and event management in WorldContract and WorldContractReader.
crates/torii/core/src/processors/event_message.rs Changed historical parameter to a hardcoded value in process method.
crates/torii/types-test/src/contracts.cairo Enhanced RecordLogged struct with Serde trait; added delete method.
examples/spawn-and-move/dojo_dev.toml Updated world_address field in [env] section.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WorldContract
    participant EventProcessor
    participant Storage

    User->>WorldContract: emit_events(keys, values)
    WorldContract->>EventProcessor: process events
    EventProcessor->>Storage: store event data
    Storage-->>EventProcessor: confirm storage
    EventProcessor-->>WorldContract: events processed
    WorldContract-->>User: confirmation
Loading

🪧 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: 4

🧹 Outside diff range and nitpick comments (34)
crates/dojo/core-cairo-test/src/tests/event/event.cairo (2)

Line range hint 1-9: Ohayo! The event structure looks solid, sensei!

The FooEvent struct is well-structured with appropriate field types and key annotations. Consider adding documentation comments to describe the purpose of each field for better maintainability.

Add documentation like this:

 #[derive(Drop, Serde)]
 #[dojo::event]
+/// Represents a test event for validating event definition functionality
 struct FooEvent {
+    /// First key field of type u8
     #[key]
     k1: u8,
+    /// Second key field of type felt252
     #[key]
     k2: felt252,
+    /// First value field storing a u128 number
     v1: u128,
+    /// Second value field storing a u32 number
     v2: u32
 }

Line range hint 11-17: Consider enhancing test coverage, sensei!

While the current test verifies basic event definition properties, consider adding test cases for:

  • Event emission
  • Batch event handling (aligning with PR's batch entities feature)
  • Serialization/deserialization validation

Would you like me to help generate these additional test cases?

crates/torii/core/src/processors/event_message.rs (1)

74-74: Track the TODO with an issue

Ohayo sensei! The TODO comment indicates a pending implementation for configuration-based historical tracking. Let's ensure this doesn't get lost in the codebase.

Would you like me to create a GitHub issue to track this TODO for implementing the configuration-based historical value?

crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo (1)

71-81: Ohayo! Consider enhancing the ABI ensure implementation, sensei! 🎋

While the implementation is functionally correct, we could make it more robust and clearer:

  1. The comment could better explain why the Event struct needs explicit ABI inclusion
  2. The parameter and variable naming could be more specific

Consider this enhancement:

     #[generate_trait]
     impl $type_name$Impl of I$type_name${
-        // Ensures the ABI contains the Event struct, since it's never used
-        // by systems directly.
+        /// Ensures the Event struct is included in the contract's ABI.
+        /// This is necessary because events are typically emitted rather than
+        /// directly used as parameters, which could cause them to be omitted
+        /// from the ABI generation.
         #[external(v0)]
-        fn ensure_abi(self: @ContractState, event: $type_name$) {
-            let _event = event;
+        fn ensure_abi(self: @ContractState, event_struct: $type_name$) {
+            let _preserved_event = event_struct;
         }
     }
crates/dojo/core/src/world/errors.cairo (1)

5-7: Ohayo! The implementation looks solid, sensei!

The new lengths_mismatch function follows the established error formatting patterns and will be valuable for batch operations validation. Consider adding a brief doc comment to explain its usage context.

+/// Formats an error message for length mismatches between two byte arrays in batch operations.
+/// 
+/// # Arguments
+/// * `a` - First byte array reference
+/// * `b` - Second byte array reference
+/// * `context` - Description of where the mismatch occurred
 pub fn lengths_mismatch(a: @ByteArray, b: @ByteArray, context: @ByteArray) -> ByteArray {
     format!("Length mismatch: `{a}` and `{b}` in `{context}`")
 }
crates/dojo/core-cairo-test/src/tests/world/storage.cairo (3)

5-30: Consider adding error cases and batch operation tests, sensei!

While the basic CRUD operations are well tested, consider adding:

  1. Error cases (e.g., reading non-existent models)
  2. Batch operations to align with the PR's objective of optimizing permissions checks for multiple entities

64-65: Update the misleading comment, sensei!

The comment "Can desnap as copiable" is misleading since we're accessing an array element, not performing deserialization.

-            // Can desnap as copiable.
+            // Access array element directly since Foo is copiable

113-114: Fix incorrect comment, sensei!

The comment about deserialization is incorrect for non-copiable types.

-            // Can desnap as copiable.
+            // Pop from array since NotCopiable is move-only
bin/sozo/tests/test_data/policies.json (1)

111-113: New granular permission management methods added.

The addition of grant_owner, revoke_owner, grant_writer, and revoke_writer methods introduces fine-grained permission control. This follows the principle of least privilege and provides better access control management.

Consider documenting the permission hierarchy and access control model in the project documentation to help developers understand the implications of these new methods.

Also applies to: 115-117, 119-121, 123-125

crates/torii/types-test/src/contracts.cairo (3)

Line range hint 29-119: Consider batching the model writes, sensei!

The create method currently performs individual write_model calls for each record, sibling, and subrecord. Since this PR introduces batch entity capabilities, we could optimize this by batching these writes together.

Consider refactoring to use batch operations:

-                world.write_model(@record);
-                world.write_model(@record_sibling);
-                world.write_model(@subrecord);
+                let models = array![record, record_sibling, subrecord];
+                world.batch_write_models(models);

Line range hint 121-122: Add error handling for record existence, sensei!

The delete method should verify that the record exists before proceeding with deletion operations.

Consider adding validation:

+            // Verify record exists before deletion
+            if !world.model_exists<Record>(record_id) {
+                panic_with_felt252('Record does not exist');
+            }

Line range hint 129-131: Optimize deletions using batch operations

Since this PR introduces batch capabilities, we should leverage them for deletions as well.

Consider refactoring to:

-            world.erase_model(@record);
-            world.erase_model(@record_sibling);
-            world.erase_model(@subrecord);
+            let models_to_delete = array![record, record_sibling, subrecord];
+            world.batch_erase_models(models_to_delete);
crates/dojo/lang/src/attribute_macros/event.rs (1)

Line range hint 31-140: Consider enhancing event validation for batch operations

Since this PR introduces batch entity processing, the event validation in from_struct might benefit from additional checks:

 if serialized_keys.is_empty() {
     diagnostics.push(PluginDiagnostic {
-        message: "Event must define at least one #[key] attribute".into(),
+        message: "Event must define at least one #[key] attribute. For batch operations, consider using composite keys".into(),
         stable_ptr: struct_ast.name(db).stable_ptr().untyped(),
         severity: Severity::Error,
     });
 }

This would help guide developers in properly structuring their events for batch operations.

crates/dojo/core-cairo-test/src/tests/helpers.cairo (2)

29-36: Ohayo sensei! The NotCopiable model looks well-structured!

The model effectively demonstrates handling of non-copyable types (Array, ByteArray) which is crucial for testing batch operations. The trait implementations (Drop, Serde, Debug) are appropriate for the model's purpose.

Consider documenting the purpose of this test model with a comment explaining its role in batch entity testing scenarios. This would help other developers understand why we're specifically testing with non-copyable types.


220-223: Consider renaming the function for clarity, sensei!

The function now deploys both Foo and NotCopiable models, but its name deploy_world_and_foo only suggests the deployment of the Foo model.

Consider renaming to deploy_world_and_models or similar to better reflect its current responsibility:

-pub fn deploy_world_and_foo() -> (WorldStorage, felt252) {
+pub fn deploy_world_and_models() -> (WorldStorage, felt252) {
bin/sozo/src/commands/events.rs (2)

348-348: Ohayo! The format string update aligns with historical removal.

The format string has been simplified by removing the historical field, which aligns well with the PR objective of removing historical aspects from the chain. The remaining fields provide comprehensive event information including selector, contract, keys, values, and data.

However, consider adding a comment explaining why historical tracking was removed and where users can find this information in the Torii configuration.


Line range hint 348-361: Consider improving the format string readability, sensei!

The current format string spans multiple lines with nested formatting. Consider extracting the key-value formatting logic into a helper function for better maintainability.

+ fn format_hex_array(values: &[Felt], prefix: &str) -> String {
+     format!("{}: {}", prefix, values
+         .iter()
+         .map(|v| format!("{:#066x}", v))
+         .collect::<Vec<String>>()
+         .join(", "))
+ }

- "Selector: {:#066x}\nContract: {}\nKeys: {}\nValues: {}\nData:\n{}",
- e.selector,
- contract_tag,
- e.keys
-     .iter()
-     .map(|k| format!("{:#066x}", k))
-     .collect::<Vec<String>>()
-     .join(", "),
- e.values
-     .iter()
-     .map(|v| format!("{:#066x}", v))
-     .collect::<Vec<String>>()
-     .join(", "),
- record
+ "{}\nContract: {}\n{}\n{}\nData:\n{}",
+ format!("Selector: {:#066x}", e.selector),
+ contract_tag,
+ format_hex_array(&e.keys, "Keys"),
+ format_hex_array(&e.values, "Values"),
+ record
crates/dojo/core/src/model/storage.cairo (3)

29-32: Minor typo in documentation comment

Ohayo, sensei! Just a small nitpick—the comment for read_models has a typo:

  • "Returnes" should be "Returns"

Apply this diff to fix the typo:

-/// Returnes an array to ensure the user can consume the models, even if the type is not
+/// Returns an array to ensure the user can consume the models, even if the type is not

44-46: Consider renaming for consistency

Ohayo, sensei! For consistency with other method names, consider renaming erase_models_ptrs to erase_model_ptrs (singular "model") to match erase_model_ptr.

Apply this diff for consistent naming:

-fn erase_models_ptrs(ref self: S, ptrs: Span<ModelPtr<M>>);
+fn erase_model_ptrs(ref self: S, ptrs: Span<ModelPtr<M>>);

97-98: Align test method naming

Ohayo, sensei! Similar to the earlier suggestion, consider renaming erase_models_ptrs_test to erase_model_ptrs_test for consistency.

Apply this diff for consistent naming:

-fn erase_models_ptrs_test(ref self: S, ptrs: Span<ModelPtr<M>>);
+fn erase_model_ptrs_test(ref self: S, ptrs: Span<ModelPtr<M>>);
crates/dojo/core/src/world/iworld.cairo (4)

133-146: Great addition of emit_events for batch processing

Introducing the emit_events function enhances performance by allowing multiple events to be emitted with a single permissions check, reducing overhead.


169-173: Inconsistent terminology: 'indices' vs 'indexes' in entities function

There's an inconsistency between the parameter name indexes and the documentation referring to indices. For clarity, consider standardizing the term.

Apply this diff to rename the parameter:

     /// * `indices` - The indexes of the entities/members to read.
     fn entities(
-        self: @T, model_selector: felt252, indexes: Span<ModelIndex>, layout: Layout
+        self: @T, model_selector: felt252, indices: Span<ModelIndex>, layout: Layout
     ) -> Span<Span<felt252>>;

197-206: Inconsistent terminology: 'indices' vs 'indexes' in set_entities function

Similarly, in the set_entities function, the parameter indexes conflicts with the use of indices in the comments. Standardizing improves readability.

Apply this diff:

     /// * `indices` - The indexes of the entities/members to write.
     fn set_entities(
         ref self: T,
         model_selector: felt252,
-        indexes: Span<ModelIndex>,
+        indices: Span<ModelIndex>,
         values: Span<Span<felt252>>,
         layout: Layout
     );

223-228: Inconsistent terminology: 'indices' vs 'indexes' in delete_entities function

The delete_entities function also mixes indexes in parameters with indices in documentation. Consistency is key for maintainability.

Apply this diff:

     /// * `indices` - The indexes of the entities/members to delete.
     fn delete_entities(
         ref self: T, 
         model_selector: felt252, 
-        indexes: Span<ModelIndex>, 
+        indices: Span<ModelIndex>, 
         layout: Layout
     );
crates/dojo/core/src/world/storage.cairo (4)

78-116: Consider Refactoring Batch Operations for Maintainability

Ohayo sensei! I noticed that the methods read_models, write_models, and erase_models share similar looping structures and logic for handling batch operations. To enhance maintainability and reduce code duplication, consider refactoring common code into generic helper functions.


95-113: Refactor Loop to Use for Construct for Enhanced Readability

Ohayo sensei! In the loop starting at line 95, using a for loop can simplify the code and improve readability. Here's how you might refactor it:

- let mut i = 0;
- loop {
-     if i >= indexes.len() {
-         break;
-     }
-
-     // Existing code
-
-     i += 1;
- };
+ for i in 0..indexes.len() {
+
+     // Existing code
+
+ }

Line range hint 208-278: Ensure Unit Test Coverage for New Batch Methods

Ohayo sensei! To maintain our code quality standards, please ensure that the new batch methods like read_values and read_values_from_ids are thoroughly covered by unit tests.


376-380: Utilize Batch Methods in Test Implementations

Ohayo sensei! In write_models_test, consider using the write_models method directly instead of iterating over each model. This can make the test code more efficient and align it with the batch operation implementations.

crates/dojo/core/src/world/world_contract.cairo (5)

800-838: Refactor loop for enhanced readability

Ohayo, sensei! Consider replacing the manual loop with a for loop in the emit_events function to improve clarity and maintainability.

Apply this diff to refactor the loop:

                let mut i = 0;
                loop {
                    if i >= keys.len() {
                        break;
                    }

                    self
                        .emit(
                            EventEmitted {
                                selector: event_selector,
                                system_address: get_caller_address(),
                                keys: *keys[i],
                                values: *values[i],
                            }
                        );

                    i += 1;
                }

Replace with:

+               for i in 0..keys.len() {
+                   self.emit(
+                       EventEmitted {
+                           selector: event_selector,
+                           system_address: get_caller_address(),
+                           keys: *keys[i],
+                           values: *values[i],
+                       }
+                   );
+               }

846-856: Preallocate array capacity for performance

Ohayo, sensei! In the entities function, preallocating the capacity of the models array can enhance performance, especially when dealing with large datasets.

Apply this diff to preallocate the array capacity:

                let mut models: Array<Span<felt252>> = array![];
+               models.reserve(indexes.len());

875-907: Consistent loop usage for better maintainability

Ohayo, sensei! To maintain consistency and improve readability, consider refactoring the manual loop in the set_entities function to a for loop.

Apply this diff to refactor the loop:

                let mut i = 0;
                loop {
                    if i >= indexes.len() {
                        break;
                    }

                    self.set_entity_internal(model_selector, *indexes[i], *values[i], layout);

                    i += 1;
                };

Replace with:

+               for i in 0..indexes.len() {
+                   self.set_entity_internal(model_selector, *indexes[i], *values[i], layout);
+               }

921-939: Simplify iteration in delete_entities function

Ohayo, sensei! Streamline the iteration over indexes in the delete_entities function by using a direct for loop, enhancing code clarity.

Apply this diff to simplify the loop:

                    for i in indexes {
                        self.delete_entity_internal(model_selector, *i, layout);
                    }

Replace with:

+                   for index in indexes {
+                       self.delete_entity_internal(model_selector, *index, layout);
+                   }

1183-1210: Enhance match expression with concise patterns

Ohayo, sensei! In the get_entity_internal function, consider using concise patterns in the match expression for improved readability.

Apply this diff to streamline the match cases:

                match index {
                    ModelIndex::Keys(keys) => {
                        let entity_id = entity_id_from_keys(keys);
                        storage::entity_model::read_model_entity(model_selector, entity_id, layout)
                    },
                    ModelIndex::Id(entity_id) => {
                        storage::entity_model::read_model_entity(model_selector, entity_id, layout)
                    },
                    ModelIndex::MemberId((
                        entity_id, member_id
                    )) => {
                        storage::entity_model::read_model_member(
                            model_selector, entity_id, member_id, layout
                        )
                    }
                }

Replace with:

+               match index {
+                   ModelIndex::Keys(keys) => {
+                       let entity_id = entity_id_from_keys(keys);
+                       storage::entity_model::read_model_entity(model_selector, entity_id, layout)
+                   },
+                   ModelIndex::Id(entity_id) => storage::entity_model::read_model_entity(model_selector, entity_id, layout),
+                   ModelIndex::MemberId((entity_id, member_id)) => storage::entity_model::read_model_member(
+                       model_selector, entity_id, member_id, layout
+                   ),
+               }
crates/dojo/world/src/contracts/abigen/world.rs (1)

3228-3247: Ohayo, sensei! Consider using slices instead of references to vectors in function parameters.

In the functions entities, delete_entities_getcall, emit_events_getcall, set_entities_getcall, and the entities method in WorldContractReader, parameters like indexes: &Vec<ModelIndex> and values: &Vec<Vec<starknet::core::types::Felt>> are used. It's more idiomatic in Rust to accept slices, such as &[ModelIndex] or &[Vec<starknet::core::types::Felt>], for read-only access. This provides greater flexibility and can improve performance.

Here's how you might refactor one of these functions:

- pub fn entities(
-     &self,
-     model_selector: &starknet::core::types::Felt,
-     indexes: &Vec<ModelIndex>,
-     layout: &Layout,
- ) -> cainome::cairo_serde::call::FCall<A::Provider, Vec<Vec<starknet::core::types::Felt>>> {
+ pub fn entities(
+     &self,
+     model_selector: &starknet::core::types::Felt,
+     indexes: &[ModelIndex],
+     layout: &Layout,
+ ) -> cainome::cairo_serde::call::FCall<A::Provider, Vec<Vec<starknet::core::types::Felt>>> {
      // function body remains the same
  }

Applying this change to similar function signatures enhances code flexibility.

Also applies to: 3338-3354, 3455-3471, 3809-3827, 4079-4098

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 92cfad0 and 2f973a2.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • spawn-and-move-db.tar.gz is excluded by !**/*.gz
  • types-test-db.tar.gz is excluded by !**/*.gz
📒 Files selected for processing (25)
  • Cargo.toml (0 hunks)
  • bin/sozo/src/commands/events.rs (1 hunks)
  • bin/sozo/tests/test_data/policies.json (1 hunks)
  • crates/dojo/core-cairo-test/src/lib.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/event/event.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/helpers.cairo (2 hunks)
  • crates/dojo/core-cairo-test/src/tests/world/storage.cairo (1 hunks)
  • crates/dojo/core-cairo-test/src/tests/world/world.cairo (0 hunks)
  • crates/dojo/core/src/event/event.cairo (0 hunks)
  • crates/dojo/core/src/event/interface.cairo (0 hunks)
  • crates/dojo/core/src/lib.cairo (0 hunks)
  • crates/dojo/core/src/model/model.cairo (0 hunks)
  • crates/dojo/core/src/model/model_value.cairo (0 hunks)
  • crates/dojo/core/src/model/storage.cairo (4 hunks)
  • crates/dojo/core/src/world/errors.cairo (1 hunks)
  • crates/dojo/core/src/world/iworld.cairo (5 hunks)
  • crates/dojo/core/src/world/storage.cairo (12 hunks)
  • crates/dojo/core/src/world/world_contract.cairo (5 hunks)
  • crates/dojo/lang/src/attribute_macros/event.rs (1 hunks)
  • crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo (1 hunks)
  • crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo (0 hunks)
  • crates/dojo/world/src/contracts/abigen/world.rs (6 hunks)
  • crates/torii/core/src/processors/event_message.rs (1 hunks)
  • crates/torii/types-test/src/contracts.cairo (1 hunks)
  • examples/spawn-and-move/dojo_dev.toml (1 hunks)
💤 Files with no reviewable changes (8)
  • Cargo.toml
  • crates/dojo/core-cairo-test/src/tests/world/world.cairo
  • crates/dojo/core/src/event/event.cairo
  • crates/dojo/core/src/event/interface.cairo
  • crates/dojo/core/src/lib.cairo
  • crates/dojo/core/src/model/model.cairo
  • crates/dojo/core/src/model/model_value.cairo
  • crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo
✅ Files skipped from review due to trivial changes (1)
  • examples/spawn-and-move/dojo_dev.toml
🔇 Additional comments (34)
crates/dojo/core-cairo-test/src/lib.cairo (2)

50-50: Ohayo! The storage module addition looks good, sensei!

The new storage module under world aligns well with the PR's objective of introducing batch entity operations. This will help ensure the new storage functionality is properly tested.


Line range hint 19-21: Consider uncommenting related test modules for comprehensive coverage.

Ohayo sensei! I notice that the model and benchmarks modules are commented out. Since this PR introduces significant changes to entity handling and storage, it might be beneficial to uncomment and update these test modules to ensure comprehensive test coverage, especially for:

  • model/model.cairo: To test model-related functionality with the new batch operations
  • benchmarks: To measure performance improvements from batch operations

Let's check if these modules exist in the repository:

Also applies to: 42-43

crates/dojo/core-cairo-test/src/tests/world/storage.cairo (2)

1-3: Ohayo sensei! The imports look clean and focused.

The necessary dependencies are properly imported for the storage tests.


81-128: Great test coverage for batch operations, sensei!

The test effectively verifies batch operations on non-copiable types with complex fields (arrays and strings), which aligns well with the PR's objective of optimizing multiple entity operations.

bin/sozo/tests/test_data/policies.json (2)

91-93: Ohayo sensei! New batch operations align perfectly with PR objectives.

The introduction of emit_events, set_entities, and delete_entities methods supports the PR's goal of reducing overhead for batch operations. These methods share the same target address (0x4bf...bdc) as their single-entity counterparts, maintaining consistency.

Also applies to: 99-101, 107-109


3-3: Verify upgrade target address changes.

Multiple upgrade method targets have been modified. Let's verify the consistency of these changes across the codebase.

Also applies to: 7-7, 39-39, 43-43, 127-127

crates/torii/types-test/src/contracts.cairo (2)

Line range hint 18-25: Ohayo! Nice work on enhancing the RecordLogged event structure!

The addition of Serde trait derivation aligns perfectly with the PR objective of ensuring event structure inclusion in the ABI. The key annotations are well-placed for proper event indexing.


Line range hint 126-127: Reconsider the subrecord_id calculation approach

The current approach of record_id + 1 for subrecord_id seems brittle and could lead to incorrect deletions if the IDs don't follow this pattern.

Let's verify the ID relationship pattern:

Consider storing the subrecord_id relationship explicitly or querying it from an index.

crates/dojo/lang/src/attribute_macros/event.rs (2)

13-22: Ohayo! LGTM on the import cleanup, sensei!

The import statements have been properly cleaned up after removing the historical parameter functionality.


Line range hint 1-140: Verify the impact of removing historical event tracking

The removal of historical event tracking aligns with the PR objectives, but we should verify the impact on existing consumers.

Let's verify the usage:

Consider documenting this architectural change in:

  1. Migration guides for existing consumers
  2. Event handling documentation
  3. Torii configuration examples, since historical tracking is moving there
✅ Verification successful

Let me gather more information about the event system changes:

The previous results show that historical event handling has moved to Torii, but let's verify the documentation and migration paths for users.


Let me try a different approach to find documentation and migration info:

The previous search revealed that historical events are now handled in Torii, but we need to verify if there's proper documentation and examples for users migrating from the old system.


Ohayo sensei! Let me check one more thing about the event system changes:

The previous results show that historical event tracking has been moved to Torii's responsibility, but let's verify if there are any migration notes or breaking changes documented.


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

Historical event tracking removal is properly handled by Torii

The removal of historical event tracking from the core is safe because:

  • Torii now handles historical events through dedicated tables (event_messages_historical)
  • Migration scripts are in place (20241028234131_event_message_historical.sql)
  • The functionality is fully implemented in Torii's event processing system

No additional documentation is needed as this is an internal architectural change that doesn't affect external consumers - they will continue to access historical events through Torii's interfaces.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to historical events
rg -i "historical.*event" 

# Search for potential event consumers that might be affected
ast-grep --pattern 'fn $name($$$) {
  $$$
  emit_event($$$)
  $$$
}'

Length of output: 1947


Script:

#!/bin/bash
# Check for event-related changes in migration files
fd migration sql$ --exec cat {}

# Look for event system documentation
fd -e md -e txt | grep -i "event" | xargs cat

# Check for event-related configuration examples
fd -g "*config*" -g "*example*" | grep -i "event" | xargs cat

Length of output: 334


Script:

#!/bin/bash
# Check for documentation files
fd -e md | xargs cat

# Look for examples directory content
fd -t f -d 3 example

# Check specific paths for configuration
rg -l "torii.*config" 

Length of output: 45408


Script:

# Check for event-related changes in the codebase
rg -A 5 "event.*historical" crates/torii/

# Look for any migration or breaking changes documentation
fd -e md | grep -i "migration\|changelog" | xargs cat

Length of output: 6428

bin/sozo/src/commands/events.rs (1)

Line range hint 1-392: Verify event batch processing implementation.

The PR objectives mention batch entities support, but I don't see any direct changes in this file related to batch processing of events. Let's verify if we need additional changes to support batch operations.

crates/dojo/core/src/model/storage.cairo (11)

23-24: Efficient batch write method added

Ohayo, sensei! The addition of write_models enhances the capability to handle multiple models efficiently, aligning with the PR objectives to reduce overhead. The method signature and documentation look correct.


29-32: Verify trait constraints for non-copiable models

Ohayo, sensei! The comment mentions handling models "even if the type is not copiable." Ensure that Array<M> can handle non-copiable types and that M satisfies the necessary trait bounds (Drop and Serde).

Would you like to confirm that M implements Drop and Serde traits required by Array<M>?


37-39: Batch erase method improves efficiency

Ohayo, sensei! Introducing erase_models aligns with the goal of reducing overhead by allowing batch deletion of models. The method is well-documented and correctly implemented.


56-60: Batch read enhances performance

Ohayo, sensei! The read_values method adds batch retrieval of model values, which should improve performance significantly. The method signature and generic constraints appear correct.


64-66: Consistency in method naming

Ohayo, sensei! The method read_values_from_ids is a great addition. For consistency, ensure similar methods follow the same naming pattern across the traits.

Would you like to review other method names for consistency?


70-74: Batch update method for model values

Ohayo, sensei! The write_values function effectively adds batch update capability for model values, aligning with the goal to reduce overhead. The use of spans for keys and values is appropriate.


78-79: Efficient batch write from IDs

Ohayo, sensei! The write_values_from_ids method allows updating multiple values directly via entity IDs, enhancing efficiency.


89-90: Test trait extended for batch writes

Ohayo, sensei! Adding write_models_test to the ModelStorageTest trait ensures batch operations are testable, which is excellent for maintaining code quality.


93-94: Batch erase in tests improves coverage

Ohayo, sensei! The inclusion of erase_models_test allows for comprehensive testing of batch delete operations.


108-111: Batch write values in tests

Ohayo, sensei! The write_values_test method addition is great for testing batch updates of model values, ensuring robustness of the new functionality.


114-115: Completing test trait with batch write from IDs

Ohayo, sensei! The write_values_from_ids_test method rounds out the batch operation methods in the test trait, providing full test coverage.

crates/dojo/core/src/world/iworld.cairo (2)

130-131: Ohayo, sensei! Simplified emit_event function signature

The removal of the historical argument from emit_event streamlines the method and aligns with the updated event handling strategy.


311-311: Alignment of emit_event_test with updated emit_event

The emit_event_test function now reflects the updated signature of emit_event, maintaining consistency across the interface.

crates/dojo/core/src/world/storage.cairo (9)

128-143: Apply Loop Refactoring to write_models Method

Ohayo sensei! Similar to the previous suggestion, the write_models method can benefit from using a for loop instead of manual index management for improved readability.


154-166: Refactor Loops in erase_models for Consistency

Ohayo sensei! The loop in erase_models also follows the same pattern. Refactoring it with a for loop will maintain consistency across your batch operation methods.


182-200: Streamline Loop in erase_models_ptrs Method

Ohayo sensei! In erase_models_ptrs, consider refactoring the loop to enhance clarity and consistency with other methods.


231-278: Refactor Loop Using for in read_values Methods

Ohayo sensei! The loops in read_values and read_values_from_ids can be refactored to use for loops for better readability.


Line range hint 293-337: Optimize Loop Structures in write_values Methods

Ohayo sensei! Refactoring the loops in write_values and write_values_from_ids with for loops will enhance code clarity and maintain consistency.


395-400: Refactor erase_models_test to Use Batch Deletion

Ohayo sensei! Similar to the previous suggestion, erase_models_test can leverage the erase_models method for batch deletion to improve test efficiency.


418-443: Batch Deletion in erase_models_ptrs_test

Ohayo sensei! In erase_models_ptrs_test, consider refactoring to use a batch deletion approach if possible, to maintain consistency and improve performance in tests.


459-469: Enhance write_values_test with Batch Operations

Ohayo sensei! The write_values_test method can be refactored to use batch writing operations, aligning with the implementation in the main code.


484-496: Refactor Loops in write_values_from_ids_test for Clarity

Ohayo sensei! For improved readability, consider refactoring the loop in write_values_from_ids_test to a for loop.

crates/dojo/world/src/contracts/abigen/world.rs (1)

244-244: Ohayo, sensei! Confirm removal of the historical field in EventEmitted.

At line 244, the EventEmitted struct is instantiated without the historical field, consistent with the AI summary stating its removal. Please verify that all usages of EventEmitted across the codebase have been updated to reflect this change to prevent potential deserialization errors.

You can run the following script to identify any outdated usages:

✅ Verification successful

Ohayo! The historical field has been properly removed from all EventEmitted usages, sensei!

The search results show that all EventEmitted struct definitions and instantiations across the codebase are consistent with the new structure, containing only selector, system_address, keys, and values fields. No instances of the historical field were found in relation to EventEmitted.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find instances where `EventEmitted` is used with the `historical` field.

# Search for `EventEmitted` struct initializations containing `historical`
rg "EventEmitted\s*\{[^}]*historical\s*:" -A 5

Length of output: 48


Script:

#!/bin/bash
# Let's try a broader search to find all EventEmitted struct usages and definitions

# Search for EventEmitted struct definitions
echo "=== EventEmitted struct definitions ==="
ast-grep --pattern 'struct EventEmitted {
  $$$
}'

# Search for EventEmitted instantiations
echo -e "\n=== EventEmitted instantiations ==="
rg "EventEmitted\s*\{" -A 3

# Search for any mentions of 'historical' near EventEmitted
echo -e "\n=== 'historical' mentions near EventEmitted ==="
rg -B 2 -A 2 "EventEmitted.*historical|historical.*EventEmitted"

Length of output: 3877

Comment on lines +75 to +76
let historical = false;
db.set_event_message(entity, event_id, block_timestamp, historical).await?;
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Ohayo sensei! After analyzing the codebase, I can now provide a clear response about the configuration suggestion.

Consider using existing IndexingFlags for historical configuration

The hardcoded historical = false can leverage the existing configuration infrastructure. The EngineConfig already has a flags system (IndexingFlags) that's used for similar toggles like TRANSACTIONS and RAW_EVENTS. Adding a new flag for historical events would be consistent with the current architecture.

Example locations that need attention:

  • crates/torii/core/src/engine.rs: Add new flag constant like HISTORICAL_EVENTS to IndexingFlags
  • crates/torii/core/src/processors/event_message.rs: Replace hardcoded false with flag check
🔗 Analysis chain

Consider implementing configuration now

The hardcoded historical = false aligns with the PR's objective of removing historical aspects. However, since this will eventually need configuration support, consider implementing it now to avoid technical debt.

Let's check if there's existing configuration infrastructure we can leverage:


Let me search for any existing configuration infrastructure specifically related to event processing.


Let me check the implementation of EngineConfig to see if it already has support for historical events configuration.


Let me try a different approach to check the EngineConfig implementation.


Let me check what IndexingFlags contains since it's part of EngineConfig.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for configuration-related code in Torii
rg -g '!target' -g '!*.lock' -A 5 'config' crates/torii/

Length of output: 24032


Script:

#!/bin/bash
# Search for configuration related to event processing and historical data
rg -g '!target' -g '!*.lock' "EngineConfig|struct.*Config" crates/torii/core/src/

Length of output: 537


Script:

#!/bin/bash
# Check EngineConfig implementation
ast-grep --pattern 'struct EngineConfig {
  $$$
}' crates/torii/core/src/engine.rs

Length of output: 84


Script:

#!/bin/bash
# Check EngineConfig implementation using ripgrep with context
rg -g '!target' -g '!*.lock' -A 10 'pub struct EngineConfig' crates/torii/core/src/

Length of output: 720


Script:

#!/bin/bash
# Check IndexingFlags implementation
rg -g '!target' -g '!*.lock' -A 10 'IndexingFlags' crates/torii/core/src/

Length of output: 4264

Comment on lines +45 to +51
if i % 2 == 0 {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
} else {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify redundant conditional block, sensei!

The if-else block contains identical code. You can remove it entirely since both branches perform the same operation.

-            if i % 2 == 0 {
-                let foo = Foo { caller, a: felt, b: i };
-                models_snaps.append(@foo);
-            } else {
-                let foo = Foo { caller, a: felt, b: i };
-                models_snaps.append(@foo);
-            }
+            let foo = Foo { caller, a: felt, b: i };
+            models_snaps.append(@foo);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if i % 2 == 0 {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
} else {
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);
}
let foo = Foo { caller, a: felt, b: i };
models_snaps.append(@foo);

Comment on lines +94 to +100
if i % 2 == 0 {
let foo = NotCopiable { caller, a: array![felt], b: "ab" };
models_snaps.append(@foo);
} else {
let foo = NotCopiable { caller, a: array![felt], b: "ab" };
models_snaps.append(@foo);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove duplicate code block, sensei!

Similar to the previous test, this if-else block contains identical code paths.

-            if i % 2 == 0 {
-                let foo = NotCopiable { caller, a: array![felt], b: "ab" };
-                models_snaps.append(@foo);
-            } else {
-                let foo = NotCopiable { caller, a: array![felt], b: "ab" };
-                models_snaps.append(@foo);
-            }
+            let foo = NotCopiable { caller, a: array![felt], b: "ab" };
+            models_snaps.append(@foo);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if i % 2 == 0 {
let foo = NotCopiable { caller, a: array![felt], b: "ab" };
models_snaps.append(@foo);
} else {
let foo = NotCopiable { caller, a: array![felt], b: "ab" };
models_snaps.append(@foo);
}
let foo = NotCopiable { caller, a: array![felt], b: "ab" };
models_snaps.append(@foo);

Comment on lines +3338 to +3354
pub fn delete_entities_getcall(
&self,
model_selector: &starknet::core::types::Felt,
indexes: &Vec<ModelIndex>,
layout: &Layout,
) -> starknet::core::types::Call {
use cainome::cairo_serde::CairoSerde;
let mut __calldata = vec![];
__calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector));
__calldata.extend(Vec::<ModelIndex>::cairo_serialize(indexes));
__calldata.extend(Layout::cairo_serialize(layout));
starknet::core::types::Call {
to: self.address,
selector: starknet::macros::selector!("delete_entities"),
calldata: __calldata,
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Add input validation for matching lengths in batch operations.

The batch functions delete_entities_getcall, emit_events_getcall, and set_entities_getcall do not validate whether the lengths of input vectors like indexes and values (where applicable) match. This could lead to unexpected behavior or runtime errors if mismatched inputs are provided.

Consider adding checks to ensure that the lengths of these vectors are equal and handle discrepancies appropriately.

Also applies to: 3455-3471, 3809-3827

@glihm glihm merged commit cf1d99f into main Nov 5, 2024
12 of 14 checks passed
@glihm glihm deleted the feat/entities-batch branch November 5, 2024 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant