Giter VIP home page Giter VIP logo

Comments (3)

jackc avatar jackc commented on September 10, 2024

Does your context have a deadline set? Or are you manually setting a deadline on the net.Conn? That's the only way that error should occur.

from pgx.

ndsistsys avatar ndsistsys commented on September 10, 2024

The problem was indeed related to a context cancellation.
In the original code, there was a little "innocent" method setting a context deadline and wrapping the call of Pool.Query; this method was calling the cancellation function as a defer function.
Moving at higher level the call of the defer function solved the problem.

I can finally attach a minimal reproducible example as a reference.
Thank you very much for your answer!

package main

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

type myStruct struct {
	ID       string     `json:"id"`
	Metadata []metadata `json:"metadata"`
}

type metadata struct {
	description
	intCouple
	MyString string `json:"myString"`
}

type intCouple struct {
	First  int64 `json:"f"`
	Second int64 `json:"s"`
}

type description struct {
	ID        string `json:"id"`
	AnotherID string `json:"anotherID"`
}

func main() {
	// created a postgres container with the following command
	// >> docker run --name postgres-test -p 5432:5432 -e POSTGRES_PASSWORD=pwd -d postgres:15

	// created a table with the following command
	//
	// CREATE TABLE mytable (
	//   id VARCHAR(10) NOT NULL,
	//   metadata JSONB NOT NULL,
	//   PRIMARY KEY (id));
	//

	ctx := context.Background()
	connectionString := "postgresql://postgres:pwd@localhost:5432/postgres?application_name=mytest&sslmode=disable"
	roConfig, err := pgxpool.ParseConfig(connectionString)
	if err != nil {
		fmt.Println(err)
		return
	}

	pool, err := pgxpool.NewWithConfig(ctx, roConfig)
	if err != nil {
		fmt.Println(err)
		return
	}

	if err := pool.Ping(ctx); err != nil {
		fmt.Println(err)
		return
	}

	// with mdSize = 10, even the bugged implementation works
	mdSize := 1000

	md := make([]metadata, 0, mdSize)
	longString := strings.Repeat("z", 200)
	for i := 0; i < mdSize; i++ {
		md = append(md, metadata{
			description: description{
				ID:        fmt.Sprintf("id-%s-%d", longString, i),
				AnotherID: fmt.Sprintf("type-0123456789012345678901234567890123456789-%d", i),
			},
			intCouple: intCouple{
				First:  int64(i) * 1000,
				Second: (int64(i)+1)*1000 - 1,
			},
			MyString: fmt.Sprintf("myString0123456789012345678901234567890123456789-%d", i),
		})
	}

	s := &myStruct{
		ID:       "id",
		Metadata: md,
	}

	_, err = pool.Exec(ctx, "INSERT INTO mytable(id, metadata) VALUES($1, $2)", s.ID, s.Metadata)
	if err != nil {
		fmt.Println(err)
		return
	}

	// working implmentation
	//ctxTimeout, cancel := context.WithTimeout(ctx, time.Minute*5)
	//defer cancel()
	// rows, err := pool.Query(ctxTimeout, "SELECT id, metadata FROM mytable WHERE id = $1", s.ID)

	// bugged implementation
	rows, err := innocentFunc(ctx, pool, "SELECT id, metadata FROM mytable WHERE id = $1", s.ID)
	//------------------------------------------------------------
	if err != nil {
		fmt.Println(err)
		return
	}
	defer rows.Close()

	counter := 0
	for rows.Next() {
		counter++
	}

	fmt.Println("loop counter: ", counter)
}

func innocentFunc(
	ctx context.Context,
	pool *pgxpool.Pool,
	query string,
	args ...any,
) (pgx.Rows, error) {
	ctxTimeout, cancel := context.WithTimeout(ctx, time.Minute*5)
	defer cancel()

	return pool.Query(ctxTimeout, query, args...)
}

from pgx.

jackc avatar jackc commented on September 10, 2024

👍

from pgx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.