-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
fix: Do not panic when using an unexpected cursor type #26165
base: main-2.x
Are you sure you want to change the base?
Conversation
This PR is used to alleviate the erroneous panic we are seeing corresponding with #26142. There should not be a panic and instead we should be throwing an 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.
Still some panics left in the code, and error messages are cryptic.
storage/reads/array_cursor.gen.go
Outdated
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
unreachable
is a bad error message. Help the user out with something like unsupported array cursor type
storage/reads/array_cursor.gen.go
Outdated
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
As above for error message.
storage/reads/array_cursor.gen.go
Outdated
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
As above for error message
storage/reads/array_cursor.gen.go
Outdated
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
As above.
panic(fmt.Sprintf("unsupported for aggregate min: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unsupported for aggregate min: %s", arrayCursorType(cur)), |
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.
Yes, a better error message!
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
Better error message, see above.
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
Better error message, see suggestions above.
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
Better message
panic(fmt.Sprintf("unreachable: %T", cur)) | ||
return nil, &errors2.Error{ | ||
Code: errors2.EInvalid, | ||
Msg: fmt.Sprintf("unreachable: %s", arrayCursorType(cur)), |
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.
Better error message.
case datatypes.Aggregate_AggregateTypeMax: | ||
return newWindowMaxArrayCursor(cursor, window), nil | ||
return newWindowMaxArrayCursor(cursor, window) | ||
case datatypes.Aggregate_AggregateTypeMean: | ||
return newWindowMeanArrayCursor(cursor, window) | ||
default: |
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.
Don't panic in this default
statement
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.
See also panic on line 143. We should not panic for bad flux.
Converting to draft as I make changes here. |
72977bc
to
c8ee812
Compare
storage/flux/reader.go
Outdated
@@ -311,6 +314,7 @@ func (gi *groupIterator) handleRead(f func(flux.Table) error, rs storage.GroupRe | |||
gc storage.GroupCursor | |||
cur cursors.Cursor | |||
table storageTable | |||
err 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.
Should be a separate declaration, because it is not a resource that much be closed if not nil on return.
@@ -121,7 +121,10 @@ func (g *groupResultSet) Next() GroupCursor { | |||
// the time range of the query. | |||
func (g *groupResultSet) seriesHasPoints(row *SeriesRow) bool { | |||
// TODO(sgc): this is expensive. Storage engine must provide efficient time range queries of series keys. | |||
cur := g.arrayCursors.createCursor(*row) | |||
cur, err := g.arrayCursors.createCursor(*row) |
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.
So this is a lost error; unreported, never makes it out of this method scope. I'm not sure how to handle this, but because there is also a panic on line 148, you may need to return a (bool, error)
from this method to get this error and the (soon-to-be-eliminated) panic out to the user.
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.
A few notes on this draft.
cur = c.arrayCursors.createCursor(seriesRow) | ||
cur, err = c.arrayCursors.createCursor(seriesRow) | ||
if err != nil { | ||
return nil, err |
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 other returns are (cur, err)
. Should we hand back the cur
here (in case there is some clean-up necessary on it)? Or are we certain it is always nil if createCursor
fails (which would be better).
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.
cur
here will be nil
if the createCursor
call fails.
This switch statement gets called during createCursor
func newWindowAggregateArrayCursor(ctx context.Context, agg *datatypes.Aggregate, window interval.Window, cursor cursors.Cursor) (cursors.Cursor, error) {
if cursor == nil {
return nil, nil
}
switch agg.Type {
case datatypes.Aggregate_AggregateTypeCount:
return newWindowCountArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeSum:
return newWindowSumArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeFirst:
return newWindowFirstArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeLast:
return newWindowLastArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeMin:
return newWindowMinArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeMax:
return newWindowMaxArrayCursor(cursor, window)
case datatypes.Aggregate_AggregateTypeMean:
return newWindowMeanArrayCursor(cursor, window)
default:
return nil, &errors2.Error{
Code: errors2.EInvalid,
Msg: fmt.Sprintf("unsupported window aggregate cursor: %s", agg.Type),
}
}
}
Each of the newWindow...Cursor
calls also has a switch statement that will bubble up nil for the cursor value as well.
@@ -119,7 +119,7 @@ func resultSetToString(wr io.Writer, rs reads.ResultSet, opts ...optionFn) { | |||
for rs.Next() { | |||
fmt.Fprint(wr, "series: ") | |||
tagsToString(wr, rs.Tags()) | |||
cur := rs.Cursor() | |||
cur, _ := rs.Cursor() |
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.
Hmmm, not sure how important this is to fix....
At least add a comment.
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.
Sounds good can do - I was actually planning on going back and adding in this error while I work on some tests for these changes to test capturing errors.
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.
Taking a look at this code it looks like the tests that resultSetToString
gets called in all have a nil cursor so the error will never bubble up in these tests. The continue here
influxdb/storage/reads/store_test.go
Line 125 in e862501
continue |
@@ -257,7 +257,11 @@ func (s *Store) tagKeysWithFieldPredicate(ctx context.Context, mqAttrs *metaquer | |||
rs := reads.NewFilteredResultSet(ctx, mqAttrs.start, mqAttrs.end, cur) | |||
for rs.Next() { | |||
func() { | |||
c := rs.Cursor() | |||
c, err := rs.Cursor() |
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.
Return the error out of this anonymous function; the top level function has an error return, so the plumbing is only local.
The rs.Next
loop should halt on error (as opposed to continuing as is should for c == nil
when there is no data.
@@ -623,7 +627,11 @@ func (s *Store) tagValuesSlow(ctx context.Context, mqAttrs *metaqueryAttributes, | |||
rs := reads.NewFilteredResultSet(ctx, mqAttrs.start, mqAttrs.end, cur) | |||
for rs.Next() { | |||
func() { | |||
c := rs.Cursor() | |||
c, err := rs.Cursor() |
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.
Same comments as in the similar code above.
@@ -764,7 +772,11 @@ func (s *Store) seriesCardinalityWithPredicateAndTime(ctx context.Context, shard | |||
rs := reads.NewFilteredResultSet(ctx, start, end, cur) | |||
for rs.Next() { | |||
func() { | |||
c := rs.Cursor() | |||
c, err := rs.Cursor() | |||
if err != 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.
As above.
move error var declaration outside of closed vars in flux reader
This PR is used to alleviate the erroneous panic we are seeing corresponding with #26142 There should not be a panic and instead we should be throwing an error.