-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
spanner: ReadWriteTransaction reties on io.ErrUnexpectedEOF #1384
Comments
Could you provide a little more information? Which method returned io.ErrUnexpectedEOF, and why should this not be retried? |
porto.Unmarshal might. It's necessary to do so within an RWT to manipulate it atomically if the data stored in spanner is a proto blob. |
@ashi009 Wrapping the error in a custom error with a custom error message should work. Running the following test works for me, in the sense that the transaction does not retry but fails with the custom error: func TestReadWriteTransactionCustomError(t *testing.T) {
// setup test client
....
_, err = client.ReadWriteTransaction(ctx,
func(ctx context.Context, transaction *spanner.ReadWriteTransaction) error {
_, err = unmarshal()
if err == io.ErrUnexpectedEOF {
err = &CustomError{
Description:"Custom error",
Err:io.ErrUnexpectedEOF,
}
}
if err != nil {
return err
}
return nil
})
if err == nil {
t.Fatalf("missing exception")
}
if err.Error() != "Custom error" {
t.Fatalf("unexpected exception: %s, expected %s", err.Error(), "Custom error")
}
e, ok := err.(*CustomError)
if !ok {
t.Fatalf("expected CustomError")
}
if e.Err != io.ErrUnexpectedEOF {
t.Fatalf("expected io.ErrUnexpectedEOF as underlying error")
}
}
type CustomError struct {
Description string
Err error
}
func (e *CustomError) Error() string {
return e.Description
}
func unmarshal() (int, error) {
return 0, io.ErrUnexpectedEOF
} Running the same test without wrapping |
@olavloite This is indeed a working solution. However, it's unintuitive, as the convention for wrapping an error is to prepend the context. In that case, the "unexpected EOF" message will always present in the final error message and trigger the retry. |
Might want to remove the bottom part of this retry logic, which seems obsolete: google-cloud-go/spanner/retry.go Lines 87 to 95 in 844a547
|
1.14 was released last August, any prior version is more than 6 months old.
If this project is subject to the build horizon policy (maybe not for an
open source project?), removing it SGTM.
Chris Broadfoot <notifications@github.com>于2019年5月3日 周五上午1:00写道:
Might want to remove this retry logic, which seems obsolete:
https://github.com/googleapis/google-cloud-go/blob/844a54768fdb2daa81cfafe91355d68439698b3d/spanner/retry.go#L92-L95
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1384 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAFH2B6KXI647SRE3R32AHTPTMM2RANCNFSM4HEPTX4A>
.
--
Sent from Gmail Mobile
|
This change contains the following global changes: 1. spanner.Client uses the generated gapic client for gRPC calls, instead of a gRPC connection and a spannerpb.SpannerClient. 2. The gapic client uses the default gax retry logic. 3. Most custom retry logic has been removed, except: * retry on aborted transactions * retry for resumableStreamDecoder.next() The change also includes an in-memory Spanner server for test purposes. The server requires the user to mock the result of queries and update statements. Sessions and transactions are handled automatically. It also allows the user to register specific errors to be returned for each gRPC function. This test server makes it easier to develop test cases that verify the behavior of the client library for an entire transaction for situations that cannot easily be created in an integration test using a real Cloud Spanner instance, such as aborted transactions or temporary retryable errors. The test cases can use the standard Spanner client withouth the need to mock any of the server functions, other than specifying the results for queries and updates. Fixes #1418 and #1384 Change-Id: If0a8bbed50b512b32d73a8ef7ad74cdb1192294b Reviewed-on: https://code-review.googlesource.com/c/gocloud/+/41131 Reviewed-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jean de Klerk <deklerk@google.com>
This issue was also solved with the change mentioned above. |
ReadWriteTransaction function returned io.ErrUnexpectedEOF will cause spanner client to retry the transaction repeatedly.
Even wrapping the returned error will cause it to retry, due to the way isRetryable works:
google-cloud-go/spanner/retry.go
Lines 77 to 94 in deb0013
The text was updated successfully, but these errors were encountered: