-
Notifications
You must be signed in to change notification settings - Fork 199
[Storage] Refactor index execution result #8005
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
engine/execution/state/state.go
Outdated
| storage.LockIndexStateCommitment, | ||
| } | ||
| // Acquire locks to ensure it's concurrent safe when inserting the execution results and chunk data packs. | ||
| return storage.WithLocks(s.lockManager, locks, func(lctx lockctx.Context) error { |
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.
Does it make sense to change the argument from lockctx.Context to lockctx.Proof?
| return storage.WithLocks(s.lockManager, locks, func(lctx lockctx.Context) error { | |
| return storage.WithLocks(s.lockManager, locks, func(lctx lockctx.Proof) error { |
| Build() | ||
| builder := lockctx.NewDAGPolicyBuilder() | ||
|
|
||
| addLocks(builder, LockGroupAccessFinalizingBlock) |
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.
I created lock groups so that it's easy to track where they are used, and it's ok that duplicated lock policies are added, lockctx can ensure there is no cycle that would cause deadlock.
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.
👍 Good idea. Splitting out the DAG definition into groups makes sense to me.
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.
Nice work
| return fmt.Errorf("could not index initial genesis execution block: %w", err) | ||
| } | ||
|
|
||
| err = operation.IndexOwnOrSealedExecutionResult(lctx, rw, rootSeal.BlockID, rootSeal.ResultID) |
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.
| err = operation.IndexOwnOrSealedExecutionResult(lctx, rw, rootSeal.BlockID, rootSeal.ResultID) | |
| err = operation.IndexSealedOrMyExecutionResult(lctx, rw, rootSeal.BlockID, rootSeal.ResultID) |
I think using "My" rather than "Own" would be clearer, just because "own" is also a common verb
| } | ||
|
|
||
| // SaveExecutionResults saves all data related to the execution of a block. | ||
| // It is concurrent safe because chunk data packs store is conflict-free (storing data by hash), and protocol data requires a lock to store, which will be synchronized. |
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.
| // It is concurrent safe because chunk data packs store is conflict-free (storing data by hash), and protocol data requires a lock to store, which will be synchronized. | |
| // Calling this function multiple times with the same input is a no-op and will not return an error. |
(since we swallow ErrAlreadyExists)
storage/locks.go
Outdated
| // LockInsertOwnReceipt is intended for Execution Nodes to ensure that they never publish different receipts for the same block. | ||
| // Specifically, with this lock we prevent accidental overwrites of the index `executed block ID` ➜ `Receipt ID`. | ||
| LockInsertOwnReceipt = "lock_insert_own_receipt" | ||
| LockInsertOwnReceipt = "lock_insert_own_receipt" |
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.
| // LockInsertOwnReceipt is intended for Execution Nodes to ensure that they never publish different receipts for the same block. | |
| // Specifically, with this lock we prevent accidental overwrites of the index `executed block ID` ➜ `Receipt ID`. | |
| LockInsertOwnReceipt = "lock_insert_own_receipt" | |
| LockInsertOwnReceipt = "lock_insert_own_receipt" | |
| // LockInsertMyReceipt is intended for Execution Nodes to ensure that they never publish different receipts for the same block. | |
| // Specifically, with this lock we prevent accidental overwrites of the index `executed block ID` ➜ `Receipt ID`. | |
| LockInsertOwnReceipt = "lock_insert_my_receipt" |
Similar suggestion again. I think we should align on using the "my receipt" terminology for increased clarity. We already use it in some places, for example the store module:
flow-go/storage/store/my_receipts.go
Line 19 in 9dafecc
| type MyExecutionReceipts struct { |
storage/locks.go
Outdated
| LockBootstrapping = "lock_bootstrapping" | ||
| // LockInsertInstanceParams protects data that is *exclusively* written during bootstrapping. | ||
| LockInsertInstanceParams = "lock_insert_instance_params" | ||
| LockIndexCollectionsByBlock = "lock_index_collections_by_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.
| LockIndexCollectionsByBlock = "lock_index_collections_by_block" | |
| LockIndexBlockByPayloadGuarantees = "lock_index_block_by_payload_guarantees" |
Collection guarantees are distinct from collections (and have different IDs), so suggesting to be clear here (and in the implementation) that we are referring specifically to collection guarantees here.
Also, it feels like the index name is inverted currently. The underlying storage operation is inserting entries like guaranteeID -> blockID. Usually in these cases we say we are indexing the block (thing in the value) by guarantee (thing in the key).
| Build() | ||
| builder := lockctx.NewDAGPolicyBuilder() | ||
|
|
||
| addLocks(builder, LockGroupAccessFinalizingBlock) |
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.
👍 Good idea. Splitting out the DAG definition into groups makes sense to me.
storage/store/blocks.go
Outdated
| func (b *Blocks) BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, collIDs []flow.Identifier) error { | ||
| return operation.BatchIndexBlockContainingCollectionGuarantees(lctx, rw, blockID, collIDs) |
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.
| func (b *Blocks) BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, collIDs []flow.Identifier) error { | |
| return operation.BatchIndexBlockContainingCollectionGuarantees(lctx, rw, blockID, collIDs) | |
| func (b *Blocks) BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, guaranteeIDs []flow.Identifier) error { | |
| return operation.BatchIndexBlockContainingCollectionGuarantees(lctx, rw, blockID, guaranteeIDs) |
storage/operation/headers.go
Outdated
| func IndexBlockContainingCollectionGuarantee(w storage.Writer, collID flow.Identifier, blockID flow.Identifier) error { | ||
| return UpsertByKey(w, MakePrefix(codeCollectionBlock, collID), blockID) | ||
| // - [storage.ErrAlreadyExists] if any collection guarantee is already indexed | ||
| func BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, collIDs []flow.Identifier) error { |
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.
| func BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, collIDs []flow.Identifier) error { | |
| func BatchIndexBlockContainingCollectionGuarantees(lctx lockctx.Proof, rw storage.ReaderBatchWriter, blockID flow.Identifier, guaranteeIDs []flow.Identifier) error { |
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.
Could you also please update the variable naming in LookupBlockContainingCollectionGuarantee below 🙏
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.
Nice work
Co-authored-by: Jordan Schalm <[email protected]>
Work towards #7912