-
Notifications
You must be signed in to change notification settings - Fork 895
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
GODRIVER-1925 Surface cursor errors in DownloadStream fillBuffer #653
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ( | |
"io" | ||
"math/rand" | ||
"runtime" | ||
"strings" | ||
"testing" | ||
"time" | ||
|
||
|
@@ -369,6 +370,61 @@ func TestGridFS(x *testing.T) { | |
_, err = bucket.OpenDownloadStream(oid) | ||
assert.Equal(mt, gridfs.ErrMissingChunkSize, err, "expected error %v, got %v", gridfs.ErrMissingChunkSize, err) | ||
}) | ||
mt.Run("cursor error during read after downloading", func(mt *mtest.T) { | ||
// To simulate a cursor error we upload a file larger than the 16MB default batch size, | ||
// so the underlying cursor remains open on the server. Since the ReadDeadline is | ||
// set in the past, Read should cause a timeout. | ||
|
||
fileName := "read-error-test" | ||
fileData := make([]byte, 17000000) | ||
|
||
bucket, err := gridfs.NewBucket(mt.DB) | ||
assert.Nil(mt, err, "NewBucket error: %v", err) | ||
defer func() { _ = bucket.Drop() }() | ||
benjirewis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
dataReader := bytes.NewReader(fileData) | ||
_, err = bucket.UploadFromStream(fileName, dataReader) | ||
assert.Nil(mt, err, "UploadFromStream error: %v", err) | ||
|
||
ds, err := bucket.OpenDownloadStreamByName(fileName) | ||
assert.Nil(mt, err, "OpenDownloadStreamByName error: %v", err) | ||
|
||
err = ds.SetReadDeadline(time.Now().Add(-1 * time.Second)) | ||
assert.Nil(mt, err, "SetReadDeadline error: %v", err) | ||
|
||
p := make([]byte, len(fileData)) | ||
_, err = ds.Read(p) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you parameterize this test case, or add a test for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah great catch. |
||
assert.NotNil(mt, err, "expected error from Read, got nil") | ||
assert.True(mt, strings.Contains(err.Error(), "context deadline exceeded"), | ||
"expected error to contain 'context deadline exceeded', got %v", err.Error()) | ||
}) | ||
mt.Run("cursor error during skip after downloading", func(mt *mtest.T) { | ||
// To simulate a cursor error we upload a file larger than the 16MB default batch size, | ||
// so the underlying cursor remains open on the server. Since the ReadDeadline is | ||
// set in the past, Skip should cause a timeout. | ||
|
||
fileName := "skip-error-test" | ||
fileData := make([]byte, 17000000) | ||
|
||
bucket, err := gridfs.NewBucket(mt.DB) | ||
assert.Nil(mt, err, "NewBucket error: %v", err) | ||
defer func() { _ = bucket.Drop() }() | ||
|
||
dataReader := bytes.NewReader(fileData) | ||
_, err = bucket.UploadFromStream(fileName, dataReader) | ||
assert.Nil(mt, err, "UploadFromStream error: %v", err) | ||
|
||
ds, err := bucket.OpenDownloadStreamByName(fileName) | ||
assert.Nil(mt, err, "OpenDownloadStreamByName error: %v", err) | ||
|
||
err = ds.SetReadDeadline(time.Now().Add(-1 * time.Second)) | ||
assert.Nil(mt, err, "SetReadDeadline error: %v", err) | ||
|
||
_, err = ds.Skip(int64(len(fileData))) | ||
assert.NotNil(mt, err, "expected error from Skip, got nil") | ||
assert.True(mt, strings.Contains(err.Error(), "context deadline exceeded"), | ||
"expected error to contain 'context deadline exceeded', got %v", err.Error()) | ||
}) | ||
}) | ||
|
||
mt.RunOpts("bucket collection accessors", noClientOpts, func(mt *mtest.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.
No need to change. I was initially slightly concerned. This adds blocking work with
context.Background()
, which could block indefinitely. But previously this would always return immediately.Though, if the cursor is exhausted, this should do no work (killCursors won't be sent to the server). If the cursor is not exhausted, this still seems preferable to leaking cursors server-side in the event of 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.
A good point and valid concern. But, leaking cursors doesn't seem great; and on the driver side, not closing the cursor in this case will leave a session open (
client.NumberSessionsInProgress() > 0
).