-
Notifications
You must be signed in to change notification settings - Fork 18k
database/sql: if a context is cancelled, then pass back that error #25829
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
Comments
I'm not clear on what the bug is here. Perhaps @kardianos can clarify. (Questions rather than bug reports normally go to a forum, not the issue tracker; see https://golang.org/wiki/Questions. But I see that @kardianos suggested posting there.) |
The poster wants to be able to differentiate errors caused by context cancelations and other database errors. I don't think we always pass back the context error, esp with the closed rows. I'll assign to me and look into. |
I think here's a reproduction for this error we've been seeing.
|
If you want to behave differently based on whether a context has ended, check |
@dsymonds For my purposes, it's specifically (But I'm sure your advice will be useful to others who come looking for this stuff.) Except...
Can you elaborate? I'm not sure I understand. |
If a client provides an arbitrarily short deadline, you'll get My point about the extra context is that it is common for Go errors to be returned up the stack with extra information added. That loses the error type and value identity. For instance, if I wrote a function like this: func f(ctx context.Context) error {
if err := g(ctx); err != nil {
return fmt.Errorf("running g: %v", err)
}
...
if err := h(ctx); err != nil {
return fmt.Errorf("running h: %v", err)
}
...
} Now if |
@dsymonds I agree I don't think it must return ctx.Err(). However, I would like to see the error to be consistent regardless of when the context is canceled (super short deadline or long deadline) during a query, not sometimes ctx.Err() and sometimes "Rows are closed". I believe the issue summary has additional concerns. While crafting the test case, I remember among various cases I came up with, only one resulted in "Rows are closed" error instead of ctx.Err(). That leads me to think it's very tricky to foresee the need to check the context, as we'd see ctx.Err() coming back most of the time in testing. "sql: Rows are closed" also does not indicate the cause of closing. It'd be nice if the error extends ctx.Err() like in your example. Something like go/grpc's statusError seems nice. |
@dsymonds I don't think you're wrong, but I think you might be missing the point. @changpingc I appreciate the test case. I'm not 100% certain we can address the issue, but I'll see what can be reasonably be done. I agree that when possible, it would be good to have the error that caused the abort to be represented by the error returned. I think the conversation about what to do with errors when they are returned is less relevant here. |
We now have now seen another DB error that seems to be caused by context canceled and we're downgrading: // If the request context is canceled by the user just before a transactions commit is
// attempted, then the following error will occur. We'll treat this like the other
// context.Canceled downgrades.
if cause.Error() == "sql: Transaction has already been committed or rolled back" &&
ctx.Err() == context.Canceled {
...downgrade
} |
Change https://golang.org/cl/145204 mentions this issue: |
@adam-p Are you able to review / test the CL https://go-review.googlesource.com/c/go/+/145204 ? I think it would solve your issue. |
Getting the DB errors to manifest in my local machine is pretty difficult, so I can't really test it. I read the diff, but it's hard to intuit what Question: Do you want to set |
Nope. If you look at |
What version of Go are you using (
go version
)?1.10.1
Does this issue reproduce with the latest release?
Probably?
What operating system and processor architecture are you using (
go env
)?linux amd64; running on AWS Elastic Container Service Fargate.
What did you do?
(This is mostly a copy-paste from a golang-sql post, as requested by @kardianos .)
It’s pretty common (for client reasons) for our API server to get context.Canceled errors when clients terminate their connections before server response processing is complete. We detect and treat these differently (as warnings rather than errors, in a logging sense), since they’re client triggered and don’t indicate something wrong with the running of the server. So that’s fine.
But… Every now and then the context getting canceled will first surface as a DB error, like: “QueryRowContext failed: sql: Rows are closed”. It seems like a sort of race condition as to where the canceled state is first detected.
This case looks unavoidable, but, as above, we’d still prefer to detect and downgrade it to a warning. So… Is there a robust way to do this?
The origin of the error suggests that there’s no unique error type for “rows are closed” to compare against. So, is the string used for the error considered stable enough to compare against to detect the error type?
Or maybe any DB error could fall into checking “are the rows closed?” But I don’t see an API for checking that (either in database/sql or pgx).
Or maybe any DB error could fall into checking if the context has been canceled (
ctx.Err() == context.Canceled
)? But that seems like it might mask real DB errors if the context was only coincidentally cancelled. Low probability of that occurring, though.But is there a right way to do this?
Thanks in advance.
The text was updated successfully, but these errors were encountered: