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
Context timeout/deadline not very effective on Exec, Query #1313
Comments
Ran into a similar problem in a different context, and now I'm a bit suspicious about how the context deadline is supposed to work. Go's standard |
I'm unable to duplicate this. package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/jackc/pgx/v5"
)
func main() {
ctx := context.Background()
conn, err := pgx.Connect(ctx, os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
defer conn.Close(ctx)
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
t1 := time.Now()
_, err = conn.Exec(ctx, `select 1, pg_sleep(60)`)
if err == nil {
log.Fatal("expected error but did not receive")
}
t2 := time.Now()
fmt.Println(err, t2.Sub(t1))
} Output:
As far a how the deadline gets to the network connection see package ctxwatch as used by Line 379 in 335c862
In short, a separate goroutine watches the context and when it is canceled it calls SetDeadline. |
I'm suspicious now that there's a kernel or hardware problem. I didn't see anything in |
After updating the kernel, I haven't seen a recurrence of this problem, so I'm chalking it up to a spurious external issue. |
Hi I have a question regarding this. I tried your example and it works, but according to I'm trying to avoid creating a batch per query creating an explicit transaction to be able to do |
@alejandrodnm It can take some time for a query to terminate gracefully. See, for example, this StackOverflow answer. In this case, I don't think You can forcibly terminate a query by terminating its associated process (which should be done through Postgres itself whenever possible), which will happen immediately under most circumstances, but this isn't recommended for typical cases. As far as I can tell, closing the session/connection that kicked off a query is equivalent to gracefully terminating it. |
Query cancellation does signal to server to cancel the query. Unfortunately, there is no guarantee the signal will be honored and PostgreSQL doesn't even provide any feedback regarding the state of the cancellation request. See https://www.postgresql.org/docs/current/protocol-flow.html#id-1.10.5.7.10.
|
Thanks @kbolino and @jackc , my confusion came because I didn't realise that the request to cancel the query is send asynchronously: Lines 583 to 598 in f803c79
When running @jackc example the program exited before the request to cancel the query was made. I guess that's what happened when I was testing the query cancelation part. When given some time to do the
THANK YOU ❤️ |
Describe the bug
The timeout/deadline specified on the context passed in to various operations does not seem to be very effective.
To Reproduce
WithDeadline
orWithTimeout
)e.g.
Expected behavior
Error is
deadline exceeded
, time elapsed is pretty close to timeout.Actual behavior
Error is
timeout: context already done: context deadline exceeded
(as expected) but time elapsed can be much longer than expected, for example I've seen it take 2–4 hours to finally fail on a 5-minute timeout.Version
Additional context
I believe the root cause is that the context is only checked for cancellation in between network calls. If the problem manifests as being stuck inside a read/write operation against the network connection, then the timeout is only effective once (if ever!) the operation fails in the underlying implementation of Go's standard library.
The solution would seem to be to propagate the context's deadline down to the network connection. This may be as simple as doing something like the following in the appropriate place:
The text was updated successfully, but these errors were encountered: