-
Notifications
You must be signed in to change notification settings - Fork 101
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
[OTE-176] Reduce the cost of adding an indexer event. #1078
Conversation
Currently we unmarshalled and marshalled all of them which grew linearly with the number of messages so as blocks got larger this became a noticeable cost.
WalkthroughThe updates mainly focus on improving data serialization and storage within the indexer components of a blockchain protocol. Key changes include transitioning from custom or older serialization methods to Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
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 as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 4
Configuration used: CodeRabbit UI
Files selected for processing (14)
- protocol/indexer/indexer_manager/events.go (4 hunks)
- protocol/indexer/indexer_manager/on_chain_updates.go (2 hunks)
- protocol/indexer/off_chain_updates/off_chain_updates.go (4 hunks)
- protocol/indexer/off_chain_updates/off_chain_updates_test.go (3 hunks)
- protocol/testing/e2e/trading_rewards/trading_rewards_test.go (3 hunks)
- protocol/testutil/keeper/assets.go (2 hunks)
- protocol/testutil/keeper/keeper.go (1 hunks)
- protocol/testutil/keeper/perpetuals.go (2 hunks)
- protocol/testutil/keeper/prices.go (3 hunks)
- protocol/testutil/keeper/rewards.go (3 hunks)
- protocol/testutil/keeper/subaccounts.go (2 hunks)
- protocol/x/clob/keeper/orders_test.go (3 hunks)
- protocol/x/perpetuals/keeper/perpetual_test.go (4 hunks)
- protocol/x/sending/keeper/transfer_test.go (4 hunks)
Additional comments: 27
protocol/indexer/indexer_manager/on_chain_updates.go (1)
- 21-21: The switch to
proto.Marshal
for marshalingIndexerTendermintBlock
aligns with the PR's goal of optimizing serialization. Ensure that corresponding unmarshaling operations are also updated to useproto.Unmarshal
for consistency.protocol/testutil/keeper/keeper.go (1)
- 32-32: Updating the variable name to
indexer_manager.TransientStoreKey
improves naming clarity and consistency. Ensure that this key is correctly defined and consistently used across the system.protocol/testutil/keeper/assets.go (1)
- 113-113: Replacing
common.UnmarshalerImpl{}
withproto.Unmarshal()
for unmarshalingAssetCreateEventV1
aligns with the PR's optimization goals. Ensure thatAssetCreateEventV1
is fully compatible withproto.Unmarshal
.protocol/testutil/keeper/rewards.go (1)
- 136-136: Switching to
proto.Unmarshal()
for unmarshalingTradingRewardsEventV1
is in line with the PR's optimization efforts. Ensure thatTradingRewardsEventV1
is fully compatible withproto.Unmarshal
.protocol/testutil/keeper/subaccounts.go (1)
- 155-155: Replacing
common.UnmarshalerImpl{}
withproto.Unmarshal()
for unmarshalingSubaccountUpdateEventV1
aligns with the PR's optimization goals. Ensure thatSubaccountUpdateEventV1
is fully compatible withproto.Unmarshal
.protocol/indexer/indexer_manager/events.go (4)
- 19-23: The introduction of
IndexerEventsCountKey
andIndexerEventsPrefix
for managing indexer events storage is a good optimization. Ensure these keys are consistently used across the system.- 28-49: Refactoring
getIndexerEventsCount
andgetIndexerEvents
to handle count and individual events retrieval more efficiently is a positive change. Ensure thorough testing to confirm correct functionality.- 112-120: The modifications in
addEvent
to handle count increment and individual event storage usingproto.Marshal
align with the PR's optimization goals. Ensure compatibility and correctness of serialization.- 130-130: Updating
clearEvents
to delete the count key instead of the events key simplifies the event clearing process. Verify that this change does not impact the retrieval of events in any negative way.protocol/testutil/keeper/perpetuals.go (2)
- 6-6: The addition of
github.com/cosmos/gogoproto/proto
is appropriate for the context of optimizing serialization and deserialization processes. This aligns well with the PR's objectives.- 199-199: Switching to
proto.Unmarshal
for unmarshallingliquidityTierEvent
is a positive change, enhancing efficiency and maintainability by utilizing the standard library over custom implementations.protocol/testutil/keeper/prices.go (2)
- 5-5: The addition of
github.com/cosmos/gogoproto/proto
supports the optimization of data handling processes, specifically for unmarshallingMarketEventV1
.- 186-186: Utilizing
proto.Unmarshal
for unmarshallingMarketEventV1
is a beneficial change, promoting efficiency and code maintainability by leveraging standardized library functions.protocol/indexer/off_chain_updates/off_chain_updates.go (3)
- 255-255: The use of
proto.Marshal
innewOrderPlaceMessage
is a positive change for standardizing serialization. Ensure that all instances where this serialized data is consumed (e.g., deserialized) are compatible with theproto
format to maintain interoperability.- 276-276: The introduction of
proto.Marshal
innewOrderRemoveMessage
aligns with the goal of optimizing serialization. Verify that the serialized data structure matches the expected schema in all contexts where it's used, to prevent any data integrity issues.- 295-295: Using
proto.Marshal
innewOrderUpdateMessage
standardizes the serialization process. It's important to ensure that the serialized format is consistently handled across the system, especially in parts of the codebase that interact with these messages.protocol/x/sending/keeper/transfer_test.go (3)
- 55-55: Replacing custom unmarshalling with
proto.Unmarshal
inassertTransferEventInIndexerBlock
is a good practice for consistency. Ensure that theTransferEventV1
struct is fully compatible with the serialized data to avoid any potential issues during tests.- 80-80: The use of
proto.Unmarshal
inassertDepositEventInIndexerBlock
for standardizing unmarshalling is commendable. Double-check that theTransferEventV1
struct accurately represents the expected schema for deposit events in all test scenarios.- 105-105: Introducing
proto.Unmarshal
inassertWithdrawEventInIndexerBlock
enhances consistency in data handling. Verify that theTransferEventV1
struct is correctly structured to match the serialized withdraw event data in tests.protocol/testing/e2e/trading_rewards/trading_rewards_test.go (1)
- 5-5: The addition of the
github.com/cosmos/gogoproto/proto
import aligns with the PR's objective to optimize data handling by leveraging standard serialization and deserialization methods. This change is consistent with the broader goal of improving performance and maintainability by using well-supported libraries.protocol/x/clob/keeper/orders_test.go (6)
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
The test suite provides comprehensive coverage for handling stateful and conditional orders. It's well-structured and covers a variety of scenarios, ensuring the system behaves as expected under different conditions.
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
It's commendable that the tests make extensive use of mocks to isolate the system under test and focus on the behavior of the
ClobKeeper
component. This approach ensures that the tests remain focused and do not inadvertently depend on external systems or state.
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
The tests for
TestPlaceStatefulOrdersFromLastBlock
andTestPlaceConditionalOrdersTriggeredInLastBlock
effectively simulate the conditions under which stateful and conditional orders should be placed or ignored. These tests are crucial for ensuring the reliability and correctness of order handling logic in the system.
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
The use of
require.PanicsWithValue
in tests likeTestPlaceStatefulOrdersFromLastBlock
andTestPlaceConditionalOrdersTriggeredInLastBlock
is a good practice for ensuring that the system behaves as expected in error scenarios. It's important to ensure that the system fails gracefully and provides meaningful error messages when encountering unexpected conditions.
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
The tests make good use of the
memClob
mock to simulate the behavior of the in-memory order book. This approach allows for precise control over the system's behavior during testing and ensures that the tests can focus on the logic of theClobKeeper
without being affected by the complexities of order book management.
- 116-127: > 📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [1-1]
The setup for each test case is thorough and carefully constructs the necessary state and conditions for the test to run. This meticulous setup is essential for ensuring that the tests accurately reflect the scenarios they are intended to simulate and that the assertions made at the end of each test are meaningful and valid.
protocol/x/perpetuals/keeper/perpetual_test.go (1)
- 1968-1968: The function
getFundingBlockEventsFromIndexerBlock
directly accesses theProduceBlock
method of theIndexerEventManager
and iterates through all events, looking specifically for funding events. This approach is efficient for extracting funding events but assumes that all events are correctly formatted and relevant to the context.The logic for extracting funding events is clear and straightforward. However, ensure that the broader system guarantees the integrity and relevance of these events to avoid processing irrelevant or malformed data.
var block indexer_manager.IndexerTendermintBlock | ||
_ = unmarshaler.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block) | ||
_ = proto.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The replacement of a custom unmarshalling implementation with proto.Unmarshal()
is a significant improvement in terms of both performance and code maintainability. By using a standard library method, the code becomes more readable, easier to maintain, and potentially more efficient. However, it's crucial to ensure that all data structures being unmarshalled are compatible with the proto
package and that this change does not introduce any regressions in how data is interpreted or processed.
One minor suggestion is to add error handling for the proto.Unmarshal()
call. Ignoring the error returned by this function can lead to hard-to-debug issues if the unmarshalling fails for any reason (e.g., due to incompatible data structures or corrupted data). Proper error handling would improve the robustness of the test code.
- _ = proto.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block)
+ err := proto.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block)
+ require.NoError(t, err, "Failed to unmarshal indexer tendermint block")
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.
_ = proto.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block) | |
err := proto.Unmarshal(msgSender.GetOnchainMessages()[0].Value, &block) | |
require.NoError(t, err, "Failed to unmarshal indexer tendermint block") |
var fundingEvent indexerevents.FundingEventV1 | ||
err := unmarshaler.Unmarshal(event.DataBytes, &fundingEvent) | ||
err := proto.Unmarshal(event.DataBytes, &fundingEvent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of proto.Unmarshal
directly without checking the event.Subtype
against a specific subtype related to funding events might lead to incorrect unmarshalling if the event data does not match the expected structure. It's crucial to ensure that the event data structure matches the expected indexerevents.FundingEventV1
structure to avoid runtime errors.
Consider adding a subtype check or ensuring through other means that the event data structure is indeed what is expected before attempting to unmarshal it.
Using panic
within the getFundingBlockEventsFromIndexerBlock
function upon encountering an error in proto.Unmarshal
is a harsh error handling strategy that could terminate the entire application. It's generally advisable to handle errors gracefully, especially in a blockchain context where stability is crucial.
Recommend replacing panic
with a more graceful error handling mechanism, such as returning the error to the caller, to prevent the application from crashing.
- panic(err)
+ return nil, err
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.
err := proto.Unmarshal(event.DataBytes, &fundingEvent) | |
err := proto.Unmarshal(event.DataBytes, &fundingEvent) | |
return nil, err |
The error handling in getFundingBlockEventsFromIndexerBlock
using panic
for unmarshalling errors is aggressive and could lead to service disruption. In blockchain applications, where uptime and reliability are paramount, consider handling errors more gracefully.
Suggest logging the error and continuing with the next event or returning an error collection for the caller to handle, rather than using panic
.
Changelist
[OTE-176] Reduce the cost of adding an indexer event.
Currently we unmarshalled and marshalled all of them which grew linearly with the number of messages so as blocks got larger this became a noticeable cost during the critical section when we hold effectively a global lock.
After this change:
Test Plan
No functional change, existing tests pass.
Author/Reviewer Checklist
state-breaking
label.indexer-postgres-breaking
label.PrepareProposal
orProcessProposal
, manually add the labelproposal-breaking
.feature:[feature-name]
.backport/[branch-name]
.refactor
,chore
,bug
.