-
Notifications
You must be signed in to change notification settings - Fork 45
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
test: implement index manager tests #982
Conversation
frrist
commented
Jun 9, 2022
•
edited
Loading
edited
- also found and fixed deadlock on fatal errors
96bddd2
to
e1d6c42
Compare
Codecov Report
@@ Coverage Diff @@
## master #982 +/- ##
========================================
+ Coverage 34.0% 35.2% +1.2%
========================================
Files 30 31 +1
Lines 2020 2087 +67
========================================
+ Hits 687 736 +49
- Misses 1256 1266 +10
- Partials 77 85 +8 |
return false, fatal | ||
default: | ||
success := atomic.NewBool(true) | ||
grp, ctx := errgroup.WithContext(ctx) |
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.
introduction of errgroup fixes deadlock by allowing both channels to be read from simultaneously. Prior to this taskErrors
was only read when a taskResults
was received. If there wasn't a taskResult
then the tipset indexer deadlocked writing to the taskErrors
channel since nothing was reading from it.
@@ -331,11 +334,12 @@ func (t *TipSetIndexer) TipSet(ctx context.Context, ts *types.TipSet) (chan *Res | |||
|
|||
var ( | |||
outCh = make(chan *Result, len(stateResults)) | |||
errCh = make(chan error) | |||
errCh = make(chan error, 1) |
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.
buffered channel to ensure writes never block
) | ||
go func() { | ||
defer func() { | ||
close(outCh) | ||
close(errCh) |
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.
close the channel signaling to consumers in the manager to exit.
func (m *LilyNodeAPI) LogList(ctx context.Context) ([]string, error) { | ||
func (m *LilyNodeAPI) LogList(_ context.Context) ([]string, error) { | ||
return logging.GetSubsystems(), nil | ||
} | ||
|
||
func (m *LilyNodeAPI) LogSetLevel(ctx context.Context, subsystem, level string) error { | ||
func (m *LilyNodeAPI) LogSetLevel(_ context.Context, subsystem, level string) error { | ||
return logging.SetLogLevel(subsystem, level) | ||
} | ||
|
||
func (m *LilyNodeAPI) LogSetLevelRegex(ctx context.Context, regex, level string) error { | ||
func (m *LilyNodeAPI) LogSetLevelRegex(_ context.Context, regex, level string) error { | ||
return logging.SetLogLevelRegex(regex, level) | ||
} | ||
|
||
func (m *LilyNodeAPI) Shutdown(ctx context.Context) error { | ||
func (m *LilyNodeAPI) Shutdown(_ context.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.
linting
func (l *LogQueryHook) AfterQuery(ctx context.Context, event *pg.QueryEvent) error { | ||
func (l *LogQueryHook) AfterQuery(_ context.Context, _ *pg.QueryEvent) error { | ||
return nil |
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.
more linting
@@ -0,0 +1,562 @@ | |||
package integrated |
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.
unit test the indexer manager with mocks
- fix deadlock on fatal errors
e1d6c42
to
72c7ff3
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.
Tests look wonderful! Thanks for comments, as well! 🍻
chain/indexer/integrated/manager.go
Outdated
@@ -54,7 +60,7 @@ func NewManager(api tasks.DataSource, strg model.Storage, name string, opts ...M | |||
opt(im) | |||
} | |||
|
|||
im.indexBuilder = NewBuilder(api, name) | |||
im.indexBuilder = idxBuilder | |||
|
|||
if im.exporter == nil { | |||
im.exporter = indexer.NewModelExporter(name) |
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 stuttering on name
in the function signature suggests you could collapse it into the builder. Making the builder responsible for the name gives you a cleaner signature.
func NewManager(strg model.Storage, idxBuilder tipset.IndexerBuilder, opts ...ManagerOpt) (*Manager, error)
im.exporter = indexer.NewModelExporter(name) | |
im.exporter = indexer.NewModelExporter(idxBuilder.Name()) |
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.
ohh god idea!
chain/indexer/integrated/manager.go
Outdated
|
||
// synchronously export extracted data and its report. If datas at this height are currently being persisted this method will block to avoid deadlocking the database. | ||
if err := i.exporter.ExportResult(ctx, i.storage, int64(ts.Height()), modelResults); err != nil { | ||
if len(modelResults) > 0 { |
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.
If you put this check inside ExportResult
, then the dev doesn't need to worry about this case before consuming it. According to the godoc there, you could return a nil
error and not break the semantics.
require.True(t, success) | ||
} | ||
|
||
func TestManagerStatusOKAndError(t *testing.T) { |
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 would like to see this test name in the failure output and understand what is being protected. Something like:
func TestManagerStatusOKAndError(t *testing.T) { | |
func TestManagerResultsContainingErrorReturnsError(t *testing.T) { |
|
||
} | ||
|
||
func TestManagerStatusOKAndSkip(t *testing.T) { |
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 TestManagerStatusOKAndSkip(t *testing.T) { | |
func TestManagerResultsContainingSkipReturnsError(t *testing.T) { |
success, err := manager.TipSet(ctx, ts1) | ||
require.NoError(t, err) | ||
require.False(t, success) | ||
} |
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.
Maybe this is a repeat of the test at https://github.com/filecoin-project/lily/pull/982/files#diff-0df3028ac9493f131c71862e7a8dd54d2e09a4ed31205f2a0a2fc09d31f1e976R149 (TestManagerStatusOKAndError
)?
success, err := manager.TipSet(ctx, ts1) | ||
require.Error(t, err) | ||
require.False(t, success) | ||
} |
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.
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 tell or show me what is being repeated? A lot of the setup is the same, but the tests validate different things.
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.
Sorry, I started to recontextualize what I was thinking here (I should've been more descriptive) and abandoned for other tasks. It's not a big deal if there's double coverage, if at all. It just seemed there was overlapping coverage in these examples. Nit only.
require.False(t, success) | ||
} | ||
|
||
func TestManagerFatalErrorAndOkReport(t *testing.T) { |
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 TestManagerFatalErrorAndOkReport(t *testing.T) { | |
func TestManagerFatalErrorDoesntBlockOkReport(t *testing.T) { |
f63b805
to
e9515ea
Compare