-
Notifications
You must be signed in to change notification settings - Fork 181
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 Approvals #6868
Conversation
77fb95b
to
5b15c09
Compare
43bfcd3
to
cc06a44
Compare
90051e1
to
a4bfe1f
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6868 +/- ##
==========================================
+ Coverage 41.10% 41.16% +0.05%
==========================================
Files 2127 2129 +2
Lines 186321 186390 +69
==========================================
+ Hits 76586 76725 +139
+ Misses 103308 103237 -71
- Partials 6427 6428 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
added a few comments about docs, but othewise looks good.
storage/store/approvals.go
Outdated
return fmt.Errorf("could not lookup result approval ID: %w", err) | ||
} | ||
|
||
// no approval found, index the approval |
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.
should this go after the error conditional completes on line 79?
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.
No, line 79 is when we have found an approval indexed by the chunk, in that case, we need to compare if the stored on is the same as the new one. And we should not store if they are different, because we should not allow a different approval for the same chunk.
storage/store/cache.go
Outdated
|
||
type Cache[K comparable, V any] struct { | ||
metrics module.CacheMetrics | ||
// nolint:unused |
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.
is this needed? looks like limit
is used
storage/store/cache.go
Outdated
"github.com/onflow/flow-go/storage" | ||
) | ||
|
||
// nolint:unused |
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.
do we need all of these nolint
directives? seems like they will become out of date quickly.
storage/store/cache.go
Outdated
} | ||
|
||
// Get will try to retrieve the resource from cache first, and then from the | ||
// injected. During normal operations, the following error returns are expected: |
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.
what's the injected
referring to here?
storage/store/cache.go
Outdated
} | ||
|
||
// Get will try to retrieve the resource from cache first, and then from the | ||
// injected. During normal operations, the following error returns are expected: |
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.
nit: it's easier to find the error part when it starts on a new line
// injected. During normal operations, the following error returns are expected: | |
// injected. | |
// During normal operations, the following error returns are expected: |
storage/store/cache.go
Outdated
return resource, nil | ||
} | ||
|
||
func (c *Cache[K, V]) Remove(key K) { |
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.
can you add docs for this method too?
a4bfe1f
to
dd1a8d5
Compare
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.
Thanks Leo, this all look very good. Essentially all of my suggestions are regarding documentation and code aesthetics.
storage/store/approvals.go
Outdated
withRetrieve(retrieve)), | ||
indexing: new(sync.Mutex), | ||
} | ||
|
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.
or maybe inline the return statement in line 33 for compactness
storage/store/approvals.go
Outdated
// ResultApprovals store is only used within a verification node, where it is | ||
// assumed that there is never more than one approval per chunk. | ||
func (r *ResultApprovals) ByChunk(resultID flow.Identifier, chunkIndex uint64) (*flow.ResultApproval, error) { | ||
return r.byChunk(r.db.Reader(), resultID, chunkIndex) |
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.
would suggest to inline the body of the byChunk
method here to avoid unnecessary layers of abstraction. This is the only place where byChunk
is used
storage/store/cache_test.go
Outdated
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 test coverage is kind of very minimal 😅. I know that store.cache
is a generalization using generics of existing code that has ran since very long time without problems. Though, if you can spare the time, it would be great to improve the test coverage to mission-critical aspects of the cache at least:
- Tests confirming that the
storage.ErrNotFound
is returned in case of cache misses would be good:flow-go/storage/store/cache.go
Lines 87 to 90 in dd1a8d5
// Get will try to retrieve the resource from cache first, and then from the // injected. During normal operations, the following error returns are expected: // - `storage.ErrNotFound` if key is unknown. func (c *Cache[K, V]) Get(r storage.Reader, key K) (V, error) { - I think it would be good if we verified that unexpected errors from the [
storeFunc](https://github.com/onflow/flow-go/blob/dd1a8d5c13a0b4da1a64759c50df5749fd419d0c/storage/store/cache.go#L22-L27)
andretrieveFunc
functions are passed up and not accidentally wrapped intostorage.ErrNotFound
- It would be nice to have tests that checks:
- if an element is already cached, we don't interact with the database (i.e
retrieve
is not called) - after a cache miss and then getting an element from the DB, the element is cached
- if an element is already cached, we don't interact with the database (i.e
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.
to me, it looks like you moved the file storage/badger/approvals_test.go
and modified it? I think it would be good to also retain the tests for storage/badger/approvals.go
since the old badger-version will probably be still in use for quite some time and maybe even be modified.
Hey, inspired by your PR, I extended the documentation of the |
Co-authored-by: Alexander Hentschel <[email protected]>
8c82715
to
5c6f00c
Compare
This PR refactors the approvals storage from badger transaction to badger batch updates.
It is to prepare for switching from badger to pebble.
Referrals:
#6381
#6466