Skip to content
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

issue 1062: Keep track of (context cancelled) error on connection, and make rows.Next return it #1064

Merged
merged 7 commits into from
Nov 8, 2021

Conversation

mjl-
Copy link
Contributor

@mjl- mjl- commented Oct 19, 2021

For #1062

Instead of just whether the connection is ErrBadConn. Often times, the error
will still be ErrBadConn. But for expired/cancelled contexts, it will be the
error for the context. Most functions still return ErrBadConn per the
database/sql/driver contract ("ErrBadConn should only be returned from [...] a
query method"). For rows.Next() we return the context-related error.

The database/sql/driver contract doesn't look very precise. Is Next a "query
method" and should database/sql handle ErrBadConns when Next returns them?

Do we have more functions that should return the canceled-context error
message?

Instead of just whether the connection is ErrBadConn. Often times, the error
will still be ErrBadConn. But for expired/cancelled contexts, it will be the
error for the context. Most functions still return ErrBadConn per the
database/sql/driver contract ("ErrBadConn should only be returned from [...] a
query method"). For rows.Next() we return the context-related error.

The database/sql/driver contract doesn't look very precise. Is Next a "query
method" and should database/sql handle ErrBadConns when Next returns them?

Do we have more functions that should return the canceled-context error
message?
Copy link
Collaborator

@otan otan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't check this repo often, sorry for the super slow reply (you'll need to ping me if its >24 business hours)

have a couple of cleanup suggestions for you

@@ -166,6 +167,40 @@ type conn struct {
gss GSS
}

type syncErr struct {
err error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason not to use type syncErr atomic.Value here, avoiding the mutex in the impls below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, I tried and ran into not being able to store a nil value. I currently don't see the code storing nil though, so I could have run into it while testing only. I'll give it a try.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, the actual reason is that syncErr.set only wants to set an error if it is currently nil. atomic.Value's CompareAndSwap was introduced only in go1.17.

conn_test.go Outdated
func() {
defer cn.errRecover(&err)
panic(io.EOF)
}()
if err != driver.ErrBadConn {
t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
}
if !cn.getBad() {
if err := cn.err.get(); err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should assert what kind of error gets returned here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

conn_test.go Outdated
@@ -721,7 +716,7 @@ func TestBadConn(t *testing.T) {
if err != driver.ErrBadConn {
t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
}
if !cn.getBad() {
if err := cn.err.get(); err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also fixed

copy.go Outdated

closed bool

sync.Mutex // guards err
sync.Mutex // guards err and Result
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whilst you're here, can you make this easier to not make a mistake by going:

type copyin struct {
  // ....
  type mu struct {
     sync.Mutex
     driver.Result
     err error
  }
}

then use

var c copyin
c.mu.Lock() ....
c.mu.Result() ...

that way it's clear how the mutex is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added the mu struct. by making the err & Result available under a different name, and fixing the uses, i noticed the usage wasn't correct.

issues_test.go Outdated Show resolved Hide resolved
@otan
Copy link
Collaborator

otan commented Nov 7, 2021

looks like this is also failing tests

@mjl-
Copy link
Contributor Author

mjl- commented Nov 8, 2021

The failed error was due to existing checks around "context canceled" not handling the error.
Those places still check for driver.ErrBadConn. I'll look into if I can remove those errors there.

I'll also look into your other cleanup suggestions. Hopefully within the next few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants