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

fix(store): properly update store head #207

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

cristaloleg
Copy link
Contributor

@cristaloleg cristaloleg commented Jun 26, 2024

Overview

The main idea of this PR is to make Store[H].Head working properly, to be precise: returning head that was written to the disk (*). Along with that heightSub.height is increased monotonically to prevent bugs when we have store appends out of order.

To test everything I'm adding 2 new tests: one that verifies out of order appends and another when which does this concurrently. Which helped to find 2 or even 3 edge cases during coding.

Fixes #201

@cristaloleg cristaloleg changed the title Store/fix store head fix(store): properly update store head Jun 27, 2024
store/heightsub.go Outdated Show resolved Hide resolved
from, to := headers[0].Height(), headers[ln-1].Height()
if height+1 != from && height != 0 { // height != 0 is needed to enable init from any height and not only 1
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removing this check 'cause we want non-adjacent adds.

Copy link
Member

Choose a reason for hiding this comment

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

We want non-adjacent adds, but we also want to make sure that to is not lower than from height (meaning headers are sorted by height (lowest --> highest)) before being published

Copy link
Member

Choose a reason for hiding this comment

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

I know the caller already sorts but it doesn't hurt to keep the check there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

sync/sync_head_test.go Show resolved Hide resolved
store/store_test.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
@cristaloleg cristaloleg marked this pull request as ready for review June 27, 2024 14:51
store/heightsub.go Show resolved Hide resolved
head, err := s.GetByHeight(ctx, s.heightSub.Height())
if err == nil {
return head, nil
headPtr := s.writeHead.Load()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

One of the biggest change: we always trying to return writeHead here and only when it's not available (read right after .Init and before 1st .Append) we will fetch data from underlying store.

Side effect: Store[H].Head should be faster now but just a bit 'cause GetByHeight uses cache.

store/store.go Outdated Show resolved Hide resolved
renaynay
renaynay previously approved these changes Jul 22, 2024
store/heightsub.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
store/heightsub.go Outdated Show resolved Hide resolved
from, to := headers[0].Height(), headers[ln-1].Height()
if height+1 != from && height != 0 { // height != 0 is needed to enable init from any height and not only 1
Copy link
Member

Choose a reason for hiding this comment

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

We want non-adjacent adds, but we also want to make sure that to is not lower than from height (meaning headers are sorted by height (lowest --> highest)) before being published

store/store.go Show resolved Hide resolved
from, to := headers[0].Height(), headers[ln-1].Height()
if height+1 != from && height != 0 { // height != 0 is needed to enable init from any height and not only 1
Copy link
Member

Choose a reason for hiding this comment

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

I know the caller already sorts but it doesn't hurt to keep the check there.

store/heightsub_test.go Show resolved Hide resolved
store/store.go Outdated Show resolved Hide resolved
@codecov-commenter
Copy link

Codecov Report

Attention: Patch coverage is 90.54054% with 7 lines in your changes missing coverage. Please review.

Project coverage is 63.82%. Comparing base (88c5b8c) to head (e552672).
Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
store/store.go 93.10% 2 Missing and 2 partials ⚠️
store/heightsub.go 81.25% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #207      +/-   ##
==========================================
+ Coverage   62.80%   63.82%   +1.01%     
==========================================
  Files          39       38       -1     
  Lines        3589     3621      +32     
==========================================
+ Hits         2254     2311      +57     
+ Misses       1160     1141      -19     
+ Partials      175      169       -6     

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

Comment on lines 101 to +102
from, to := headers[0].Height(), headers[ln-1].Height()
if height+1 != from && height != 0 { // height != 0 is needed to enable init from any height and not only 1
log.Fatalf("PLEASE FILE A BUG REPORT: headers given to the heightSub are in the wrong order: expected %d, got %d", height+1, from)
return
if from > to {
Copy link
Member

@walldiss walldiss Oct 16, 2024

Choose a reason for hiding this comment

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

Are from and to inclusive? For example, is interval like this is [from:10;to:10] is valid and has length 1?

Comment on lines +532 to +534
// TODO(cristaloleg): benchmark this timeout or make it dynamic.
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
Copy link
Member

Choose a reason for hiding this comment

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

What is the purpose of additional cap of timeout here instead of using original context?

Comment on lines +63 to +70
ok := true
ok = ok && exp.Height() == have.Height()
ok = ok && syncer.pending.Head() == nil

ok = ok && uint64(exp.Height()) == state.Height
ok = ok && uint64(2) == state.FromHeight
ok = ok && uint64(exp.Height()) == state.ToHeight
ok = ok && state.Finished()
Copy link
Member

Choose a reason for hiding this comment

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

Looks unusual. Can it be just couple of require.Equal() calls?

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.

store: Head of store needs to be the *contiguous* head of the store
6 participants