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

[Storage Refactor] Refactor saving execution results #6906

Open
wants to merge 51 commits into
base: master
Choose a base branch
from

Conversation

zhangchiqing
Copy link
Member

@zhangchiqing zhangchiqing commented Jan 16, 2025

This PR updates the execution node and access node’s saving result process to use the new storage abstraction.

The following database modules are refactored into new storage abstraction:

  • events
  • service events
  • light transaction results
  • transactionResultErrorMessages
  • commits
  • execution results
  • execution receipts
  • my execution receipts
  • transaction results

@zhangchiqing zhangchiqing force-pushed the leo/db-ops-save-execution-results branch 2 times, most recently from f793dcf to 51b6fa0 Compare January 22, 2025 21:48
@codecov-commenter
Copy link

codecov-commenter commented Jan 22, 2025

Codecov Report

Attention: Patch coverage is 38.89479% with 575 lines in your changes missing coverage. Please review.

Project coverage is 41.24%. Comparing base (c895ec9) to head (a323c20).
Report is 651 commits behind head on master.

Files with missing lines Patch % Lines
storage/operation/transaction_results.go 0.00% 94 Missing ⚠️
engine/execution/state/state.go 49.25% 27 Missing and 7 partials ⚠️
storage/store/results.go 65.26% 27 Missing and 6 partials ⚠️
cmd/execution_builder.go 0.00% 30 Missing ⚠️
storage/store/receipts.go 57.35% 22 Missing and 7 partials ⚠️
storage/store/events.go 26.31% 28 Missing ⚠️
engine/testutil/nodes.go 0.00% 22 Missing ⚠️
storage/store/transaction_results.go 54.54% 17 Missing and 3 partials ⚠️
...ck-executed-height/cmd/rollback_executed_height.go 0.00% 19 Missing ⚠️
storage/store/light_transaction_results.go 57.14% 15 Missing and 3 partials ⚠️
... and 37 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6906      +/-   ##
==========================================
+ Coverage   41.14%   41.24%   +0.10%     
==========================================
  Files        2133     2141       +8     
  Lines      187011   188713    +1702     
==========================================
+ Hits        76946    77838     +892     
- Misses     103622   104363     +741     
- Partials     6443     6512      +69     
Flag Coverage Δ
unittests 41.24% <38.89%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

@zhangchiqing zhangchiqing force-pushed the leo/db-ops-save-execution-results branch 6 times, most recently from 7aaf9ae to 868a31e Compare February 12, 2025 23:13
@zhangchiqing zhangchiqing force-pushed the leo/db-ops-save-execution-results branch from 2a5846c to e9fe482 Compare February 13, 2025 00:30
Comment on lines +350 to +352
events storage.Events
lightTransactionResults storage.LightTransactionResults
transactionResultErrorMessages storage.TransactionResultErrorMessages
Copy link
Member Author

Choose a reason for hiding this comment

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

Access node syncs events, transaction results from EN with indexer engine, I'm refactoring them altogether along with the execution node's saving results process.

@@ -872,7 +877,7 @@ func (builder *FlowAccessNodeBuilder) BuildExecutionSyncComponents() *FlowAccess
return nil
}).
Module("transaction results storage", func(node *cmd.NodeConfig) error {
builder.Storage.LightTransactionResults = bstorage.NewLightTransactionResults(node.Metrics.Cache, node.DB, bstorage.DefaultCacheSize)
builder.lightTransactionResults = store.NewLightTransactionResults(node.Metrics.Cache, node.ProtocolDB, bstorage.DefaultCacheSize)
Copy link
Member Author

Choose a reason for hiding this comment

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

ProtocolDB is a storage abstraction, so that we can change in a single place to decide using badger or pebble.

@@ -760,7 +782,8 @@ func (exeNode *ExecutionNode) LoadExecutionState(
exeNode.events,
exeNode.serviceEvents,
exeNode.txResults,
node.DB,
node.ProtocolDB,
getLatestFinalized,
Copy link
Member Author

Choose a reason for hiding this comment

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

This is for the execution state to implement getting highest finalized and executed block.

@@ -179,15 +180,20 @@ func findLastExecutedAndSealedHeight(state protocol.State, db *badger.DB) (uint6
}

var blockID flow.Identifier
var lastExecuted uint64
err = db.View(procedure.GetLastExecutedBlock(&lastExecuted, &blockID))
Copy link
Member Author

Choose a reason for hiding this comment

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

The GetLastExecutedBlock procedure is replaced by RetrieveExecutedBlock which returns only the block ID, and getting the block with protocol State.

}

// RemoveStateCommitment removes the state commitment by block ID
func RemoveStateCommitment(w storage.Writer, blockID flow.Identifier) error {
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is mostly identical with storage/badger/operation/commits.go, except BatchRemoveStateCommitment and BatchIndexStateCommitment are removed, since RemoveStateCommitment is always a batch updates.

@@ -0,0 +1,31 @@
package operation_test
Copy link
Member Author

Choose a reason for hiding this comment

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

this file is identical to the same file in storage/badger/operation/

@@ -0,0 +1,166 @@
package operation
Copy link
Member Author

Choose a reason for hiding this comment

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

this file is identical to the same file in storage/badger/operation/

Except the following functions are removed:

  • BatchInsertTransactionResult
  • BatchIndexTransactionResult

@@ -0,0 +1,82 @@
package store
Copy link
Member Author

Choose a reason for hiding this comment

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

this file is identical to the same file in storage/badger/operation/

blockID := receipt.ExecutionResult.BlockID
receiptID := receipt.ID()
var myOwnReceiptExecutedBefore flow.Identifier
err := operation.LookupOwnExecutionReceipt(rw.GlobalReader(), blockID, &myOwnReceiptExecutedBefore)
Copy link
Member Author

Choose a reason for hiding this comment

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

This is where we need to pay attention to, the original implementation can check if an own receipt already exist during insert.

			if errors.Is(err, storage.ErrAlreadyExists) {
				var savedReceiptID flow.Identifier
				err := operation.LookupOwnExecutionReceipt(blockID, &savedReceiptID)(tx)
				if err != nil {
					return err
				}

The original implementation can do so because it's using badger transaction. However, the new storage abstraction uses badger updates, so we have to check it ourselves.

The new way it works is to acquire the indexingOwnReceipts and ensure no other process is storing own receipts, so that the check for if any own receipts for this block won't be stale.

})
})

t.Run("store1 different receipt concurrent for same block should fail", func(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is the same as the original, except this added concurrent tests.

@zhangchiqing zhangchiqing changed the title [WIP] [Storage Refactor] Refactor saving execution results [Storage Refactor] Refactor saving execution results Feb 21, 2025
block := unittest.BlockFixture()
receipt1 := unittest.ReceiptForBlockFixture(&block)

err := db.WithReaderBatchWriter(func(rw storage.ReaderBatchWriter) error {
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is the same as the deleted storage/badger/my_receipts_test.go, except the StoreMyReceipt call is replaced with BatchStoreMyReceipt, since we never call StoreMyReceipt alone.

@zhangchiqing zhangchiqing marked this pull request as ready for review February 21, 2025 19:15
@zhangchiqing zhangchiqing requested a review from a team as a code owner February 21, 2025 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants