From 98acf573cce94af544d41b3e2bbfc9d86b7494cf Mon Sep 17 00:00:00 2001 From: Artemiy Ryabinkov Date: Sat, 13 Jul 2019 21:21:23 +0300 Subject: [PATCH] fix errors collecting on multi-host Signed-off-by: Artemiy Ryabinkov --- conn.go | 4 +- examples/multihosts/README.md | 25 ++++++++++++ examples/multihosts/main.go | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 examples/multihosts/README.md create mode 100644 examples/multihosts/main.go diff --git a/conn.go b/conn.go index e195bb2f..7f2ae6a8 100644 --- a/conn.go +++ b/conn.go @@ -467,8 +467,8 @@ func connect(config ConnConfig, connInfo *pgtype.ConnInfo) (c *Conn, err error) } errmsgs := make([]string, len(errs)) - for _, err := range errs { - errmsgs = append(errmsgs, err.Error()) + for i, err := range errs { + errmsgs[i] = err.Error() } return nil, errors.New(strings.Join(errmsgs, ";")) diff --git a/examples/multihosts/README.md b/examples/multihosts/README.md new file mode 100644 index 00000000..4b73eb51 --- /dev/null +++ b/examples/multihosts/README.md @@ -0,0 +1,25 @@ +# Description + +This is a sample chat program implemented using PostgreSQL's listen/notify +functionality with pgx. + +Start multiple instances of this program connected to the same database to chat +between them. + +## Connection configuration + +The database connection is configured via the standard PostgreSQL environment variables. + +* PGHOST - defaults to localhost +* PGUSER - defaults to current OS user +* PGPASSWORD - defaults to empty string +* PGDATABASE - defaults to user name + +You can either export them then run chat: + + export PGHOST=/private/tmp + ./chat + +Or you can prefix the chat execution with the environment variables: + + PGHOST=/private/tmp ./chat diff --git a/examples/multihosts/main.go b/examples/multihosts/main.go new file mode 100644 index 00000000..83b16c02 --- /dev/null +++ b/examples/multihosts/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "os" + + "github.com/jackc/pgx" +) + +var pool *pgx.ConnPool + +func main() { + config, err := pgx.ParseEnvLibpq() + if err != nil { + fmt.Fprintln(os.Stderr, "Unable to parse environment:", err) + os.Exit(1) + } + + pool, err = pgx.NewConnPool(pgx.ConnPoolConfig{ConnConfig: config}) + if err != nil { + fmt.Fprintln(os.Stderr, "Unable to connect to database:", err) + os.Exit(1) + } + + go listen() + + fmt.Println(`Type a message and press enter. + +This message should appear in any other chat instances connected to the same +database. + +Type "exit" to quit.`) + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + msg := scanner.Text() + if msg == "exit" { + os.Exit(0) + } + + _, err = pool.Exec("select pg_notify('chat', $1)", msg) + if err != nil { + fmt.Fprintln(os.Stderr, "Error sending notification:", err) + os.Exit(1) + } + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "Error scanning from stdin:", err) + os.Exit(1) + } +} + +func listen() { + conn, err := pool.Acquire() + if err != nil { + fmt.Fprintln(os.Stderr, "Error acquiring connection:", err) + os.Exit(1) + } + defer pool.Release(conn) + + conn.Listen("chat") + + for { + notification, err := conn.WaitForNotification(context.Background()) + if err != nil { + fmt.Fprintln(os.Stderr, "Error waiting for notification:", err) + os.Exit(1) + } + + fmt.Println("PID:", notification.PID, "Channel:", notification.Channel, "Payload:", notification.Payload) + } +}