I have the following code for connecting to a Postgres database:
func connectToPostgres(ctx context.Context, url string) (*pgxpool.Pool, error) {
var err error
for i := 0; i < 5; i++ {
p, err := pgxpool.Connect(ctx, url)
if err != nil || p == nil {
time.Sleep(3 * time.Second)
continue
}
log.Printf("pool returned from connect: %s", p)
return p, nil
}
return nil, errors.Wrap(err, "timed out waiting to connect postgres")
}
The use case is to wait for Postgres to become available when starting my server with docker-compose. Even though the code sleeps if p == nil
, the log just before the first return prints out: pool returned from connect: %!s(*pgxpool.Pool=<nil>)
Is there some way that a background process in pgxpool
could make p == nil
?
Any thoughts on why this would happen?
EDIT: This appears to only happen while running my app and Postgres via docker-compose. I'm using the following compose file:
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- "db"
db:
image: postgres
restart: always
environment:
- POSTGRES_DB=demo_db
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
ports:
- "8081:5432"
and the Dockerfile for my app:
FROM golang:1.17
WORKDIR /
COPY go.mod .
COPY go.sum .
COPY *.go .
RUN go mod download
RUN go build
EXPOSE 8080
CMD [ "./app" ]
And a minimally reproducible example go file:
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/pkg/errors"
)
func main() {
log.Printf("connecting to postgres...")
pgpool, err := connectToPostgres(context.Background(), "postgresql://localhost:5432/demo_db")
log.Printf("pool: %s", pgpool)
if err != nil {
log.Fatalln(err)
}
log.Printf("successfully connected to postgres")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
log.Println("stopped")
}
func connectToPostgres(ctx context.Context, url string) (*pgxpool.Pool, error) {
var err error
for i := 0; i < 5; i++ {
p, err := pgxpool.Connect(ctx, url)
if err != nil || p == nil {
time.Sleep(3 * time.Second)
continue
}
log.Printf("pool returned from connect: %s", p)
return p, nil
}
return nil, errors.Wrap(err, "timed out waiting to connect postgres")
}
log.Printf
implementation, the string format happens immediately if the value ofp
changed it would have had to be directly after the branch which seems incredibly unlikely. The code in the question is exactly what I'm running (at this point I've checked a dozen times). I also made sure the docker container I'm seeing this issue on has this exact build. It's happening consistently for me but it should be impossible as you say. – Illhumoreddb
, my connection string is:"postgres://postgres:mysecretpassword@db:5432/postgres"
– Minima