Adding migrations
continuous-integration/drone/push Build is passing Details

main
Drew Bednar 5 days ago
parent 62f9656e19
commit 8522dbae20

@ -2,6 +2,7 @@ package main
import (
"context"
"database/sql"
"errors"
// "flag"
@ -15,8 +16,9 @@ import (
"time"
"git.runcible.io/learning/pulley/internal/config"
"git.runcible.io/learning/pulley/internal/database"
"git.runcible.io/learning/pulley/internal/logging"
"github.com/jackc/pgx/v5/pgxpool"
"git.runcible.io/learning/pulley/migrations"
)
const Version = "1.0.0"
@ -62,23 +64,31 @@ func run(ctx context.Context, w io.Writer, args []string) error {
appCtx, cancel := context.WithCancel(signalCtx)
defer cancel()
pool, err := pgxpool.New(appCtx, cfg.DatabaseUri)
//run migrations
db, err := sql.Open("pgx", cfg.DatabaseUri)
if err != nil {
slog.Error("Error encountered in creating pgx postgres connection pool", "error", err.Error())
logger.Error("Error opening migrations connection")
return err
}
defer func() {
slog.Info("Closing database connection pool")
pool.Close()
}()
defer db.Close()
timoutCtx, close := context.WithTimeout(appCtx, 5*time.Second)
defer close()
err = migrations.Migrate(db)
if err != nil {
logger.Error("Error in migrations", "error", err.Error())
return err
}
if err := pool.Ping(timoutCtx); err != nil {
slog.Error("Error in attempting first postgres database connection")
logger.Info("Migrations applied.")
db.Close()
pool, err := database.OpenPgPool(ctx, cfg)
if err != nil {
return err
}
defer func() {
slog.Info("Closing database connection pool")
pool.Close()
}()
app := application{config: cfg, logger: logger}

@ -2,14 +2,22 @@ module git.runcible.io/learning/pulley
go 1.24.1
require github.com/julienschmidt/httprouter v1.3.0
require (
github.com/golang-migrate/migrate v3.5.4+incompatible
github.com/golang-migrate/migrate/v4 v4.18.3
github.com/jackc/pgx/v5 v5.7.5
github.com/julienschmidt/httprouter v1.3.0
github.com/kelseyhightower/envconfig v1.4.0
)
require (
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.5 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/text v0.24.0 // indirect

@ -1,4 +1,17 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@ -11,10 +24,17 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
@ -23,3 +43,5 @@ golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -0,0 +1,37 @@
package database
import (
"context"
"log/slog"
"time"
"git.runcible.io/learning/pulley/internal/config"
"github.com/jackc/pgx/v5/pgxpool"
)
// https://medium.com/@neelkanthsingh.jr/understanding-database-connection-pools-and-the-pgx-library-in-go-3087f3c5a0c
// pgxpool.New implicitly creates a dbConfig from the database uri params which can include connection params
// newPgxConfig creates a pgxpool Config from the application service config
// func newPgxConfig(cfg config.ServiceConfig) (pgxpool.Config, error) {
// dbconfig, err := pgxpool.ParseConfig(cfg.DatabaseUri)
// }
// OpenPgPool creates a db pool and tests connectivity
func OpenPgPool(ctx context.Context, cfg config.ServiceConfig) (*pgxpool.Pool, error) {
pool, err := pgxpool.New(ctx, cfg.DatabaseUri)
if err != nil {
return nil, err
}
timoutCtx, close := context.WithTimeout(ctx, 5*time.Second)
defer close()
if err := pool.Ping(timoutCtx); err != nil {
slog.Error("Error in attempting first postgres database connection")
pool.Close()
return nil, err
}
return pool, nil
}

@ -0,0 +1,2 @@
DROP TABLE IF EXISTS movies;

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS movies (
id bigserial PRIMARY KEY,
created_at timestamp(0) with time zone NOT NULL DEFAULT NOW(),
title text NOT NULL,
year integer NOT NULL,
runtime integer NOT NULL,
genres text[] NOT NULL,
version integer NOT NULL DEFAULT 1
);

@ -0,0 +1,41 @@
package migrations
import (
"database/sql"
"embed"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/pgx/v5"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
//go:embed *.sql
var migrationFiles embed.FS
func Migrate(db *sql.DB) error {
//create database driver
driver, err := pgx.WithInstance(db, &pgx.Config{})
if err != nil {
}
// Create IFS source from embedded files
source, err := iofs.New(migrationFiles, ".")
if err != nil {
return err
}
//creat new migrations instance
m, err := migrate.NewWithInstance("iofs", source, "pgx", driver)
if err != nil {
return err
}
// Run Migrations
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
return err
}
return nil
}
Loading…
Cancel
Save