From 5b911cb4878a692a2ee7982a2a13810d85f758e3 Mon Sep 17 00:00:00 2001 From: GetPsyched Date: Mon, 9 Oct 2023 12:11:27 +0530 Subject: [PATCH] fix: use pgx.Pool to avoid busy connections --- database/init.go | 4 ++-- go.mod | 1 + go.sum | 2 ++ handlers/announcement.go | 5 +++-- handlers/club.go | 27 ++++++++++++++------------- handlers/course.go | 7 ++++--- handlers/student.go | 7 ++++--- server.go | 6 +++--- 8 files changed, 33 insertions(+), 26 deletions(-) diff --git a/database/init.go b/database/init.go index d2eb6a3..71a20c0 100644 --- a/database/init.go +++ b/database/init.go @@ -7,10 +7,10 @@ import ( "path/filepath" "strings" - "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" ) -func Init(conn *pgx.Conn) { +func Init(conn *pgxpool.Pool) { filenames := []string{"announcement", "student", "faculty", "guild", "club", "course"} script := []string{} for _, filename := range filenames { diff --git a/go.mod b/go.mod index cf53af2..c8ef7b5 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect golang.org/x/crypto v0.9.0 // indirect diff --git a/go.sum b/go.sum index 85f52d9..1fef2c5 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= diff --git a/handlers/announcement.go b/handlers/announcement.go index dd73d02..78a8dea 100644 --- a/handlers/announcement.go +++ b/handlers/announcement.go @@ -14,6 +14,7 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" + "github.com/jackc/pgx/v5/pgxpool" "golang.org/x/net/html" ) @@ -219,7 +220,7 @@ func parseDate(date string) (parsedDate pgtype.Date, err error) { // some formatting // // TODO: try to use sqlc or some other intermediate to store this query -func FetchAnnouncements(conn *pgx.Conn) { +func FetchAnnouncements(conn *pgxpool.Pool) { insert_query := query_prefix ctx := context.Background() queries := query.New(conn) @@ -263,7 +264,7 @@ func FetchAnnouncements(conn *pgx.Conn) { // GetAnnouncements returns all the announcements stored in database // // It is a wrapper function around -func GetAnnouncements(conn *pgx.Conn) http.HandlerFunc { +func GetAnnouncements(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/club.go b/handlers/club.go index 58a1ac3..e518030 100644 --- a/handlers/club.go +++ b/handlers/club.go @@ -13,6 +13,7 @@ import ( "github.com/gorilla/mux" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" + "github.com/jackc/pgx/v5/pgxpool" ) type Club struct { @@ -32,7 +33,7 @@ type Faculty struct { } // CreateClubFaculty creates a new faculty incharge for a group. -func CreateClubFaculty(conn *pgx.Conn) http.HandlerFunc { +func CreateClubFaculty(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -72,7 +73,7 @@ func CreateClubFaculty(conn *pgx.Conn) http.HandlerFunc { } // CreateClubMember adds a new member to a club. -func CreateClubMember(conn *pgx.Conn) http.HandlerFunc { +func CreateClubMember(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) @@ -111,7 +112,7 @@ func CreateClubMember(conn *pgx.Conn) http.HandlerFunc { } // CreateClubSocial adds a new social media handle of a group. -func CreateClubSocial(conn *pgx.Conn) http.HandlerFunc { +func CreateClubSocial(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -147,7 +148,7 @@ func CreateClubSocial(conn *pgx.Conn) http.HandlerFunc { } // DeleteClubFaculty deletes an existing faculty incharge of a group. -func DeleteClubFaculty(conn *pgx.Conn) http.HandlerFunc { +func DeleteClubFaculty(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -174,7 +175,7 @@ func DeleteClubFaculty(conn *pgx.Conn) http.HandlerFunc { } // DeleteClubMember deletes an existing member of a club. -func DeleteClubMember(conn *pgx.Conn) http.HandlerFunc { +func DeleteClubMember(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) @@ -207,7 +208,7 @@ func DeleteClubMember(conn *pgx.Conn) http.HandlerFunc { } // DeleteClubSocial deletes an existing social media handle of a group. -func DeleteClubSocial(conn *pgx.Conn) http.HandlerFunc { +func DeleteClubSocial(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -232,7 +233,7 @@ func DeleteClubSocial(conn *pgx.Conn) http.HandlerFunc { // // This handler takes in a name argument which is first // checked as an alias and then as the name of a group. -func GetClub(conn *pgx.Conn) http.HandlerFunc { +func GetClub(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -254,7 +255,7 @@ func GetClub(conn *pgx.Conn) http.HandlerFunc { } // GetClubs retrieves the group details from the database. -func GetClubs(conn *pgx.Conn) http.HandlerFunc { +func GetClubs(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -273,7 +274,7 @@ func GetClubs(conn *pgx.Conn) http.HandlerFunc { } // GetClubFaculty retrieves the management faculty of a group from the database. -func GetClubFaculty(conn *pgx.Conn) http.HandlerFunc { +func GetClubFaculty(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -289,7 +290,7 @@ func GetClubFaculty(conn *pgx.Conn) http.HandlerFunc { } // GetClubSocials retrieves the social media links of a group from the database. -func GetClubSocials(conn *pgx.Conn) http.HandlerFunc { +func GetClubSocials(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -305,7 +306,7 @@ func GetClubSocials(conn *pgx.Conn) http.HandlerFunc { } // ReadClubMembers retrieves the members of a club. -func ReadClubMembers(conn *pgx.Conn) http.HandlerFunc { +func ReadClubMembers(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) @@ -331,7 +332,7 @@ func ReadClubMembers(conn *pgx.Conn) http.HandlerFunc { } // UpdateClubMember updates a club member's details. -func UpdateClubMember(conn *pgx.Conn) http.HandlerFunc { +func UpdateClubMember(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) @@ -370,7 +371,7 @@ func UpdateClubMember(conn *pgx.Conn) http.HandlerFunc { } // UpdateClubSocials updates the link of a social media handle for a group. -func UpdateClubSocials(conn *pgx.Conn) http.HandlerFunc { +func UpdateClubSocials(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/course.go b/handlers/course.go index 32815b6..007ee67 100644 --- a/handlers/course.go +++ b/handlers/course.go @@ -14,6 +14,7 @@ import ( "github.com/google/go-github/github" "github.com/gorilla/mux" "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" "golang.org/x/exp/slices" "gopkg.in/yaml.v2" ) @@ -36,7 +37,7 @@ type Course struct { Specifics []BranchSpecifics } -func CreateCourse(conn *pgx.Conn) http.HandlerFunc { +func CreateCourse(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -89,7 +90,7 @@ func CreateCourse(conn *pgx.Conn) http.HandlerFunc { } // GetCourse is a handler for retrieving a single course via the `code` argument. -func GetCourse(conn *pgx.Conn) http.HandlerFunc { +func GetCourse(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -106,7 +107,7 @@ func GetCourse(conn *pgx.Conn) http.HandlerFunc { // GetCourses is a handler for retrieving all the courses matching the given // query parameters. It outputs all the courses if no parameter is passed. -func GetCourses(conn *pgx.Conn) http.HandlerFunc { +func GetCourses(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/student.go b/handlers/student.go index dec872c..982ea92 100644 --- a/handlers/student.go +++ b/handlers/student.go @@ -10,9 +10,10 @@ import ( "github.com/gorilla/mux" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" + "github.com/jackc/pgx/v5/pgxpool" ) -func GetDiscordLinkStatus(db *pgx.Conn) http.HandlerFunc { +func GetDiscordLinkStatus(db *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(db) return func(w http.ResponseWriter, r *http.Request) { @@ -33,7 +34,7 @@ func GetDiscordLinkStatus(db *pgx.Conn) http.HandlerFunc { } // GetHostels retrieves all the hostels and their meta data from the database. -func GetHostels(conn *pgx.Conn) http.HandlerFunc { +func GetHostels(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) return func(w http.ResponseWriter, r *http.Request) { @@ -43,7 +44,7 @@ func GetHostels(conn *pgx.Conn) http.HandlerFunc { } // GetStudent retrieves a single student's details based on their roll number, email, or Discord ID. -func GetStudent(conn *pgx.Conn) http.HandlerFunc { +func GetStudent(conn *pgxpool.Pool) http.HandlerFunc { ctx := context.Background() queries := query.New(conn) diff --git a/server.go b/server.go index 520e53d..5fbbe1d 100644 --- a/server.go +++ b/server.go @@ -13,18 +13,18 @@ import ( "github.com/go-co-op/gocron" "github.com/gorilla/mux" - "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" "github.com/rs/cors" ) type server struct { - conn *pgx.Conn + conn *pgxpool.Pool router *mux.Router } // NewServer returns a new app instance. func NewServer() *server { - conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL")) + conn, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL")) if err != nil { log.Fatalln("Unable to connect to database:\n", err) }