Skip to content
Snippets Groups Projects
Commit ddf9d6a6 authored by Michael Zigldrum's avatar Michael Zigldrum
Browse files

Merge branch 'fork' into 'main'

Moved and fixed postgres migration

See merge request eclipse/xfsc/libraries/microservice/core!9
parents 73123952 0350ac95
No related branches found
No related tags found
No related merge requests found
# Postgres
### Using Config
```golang
// config.go
pkg config
type Config struct {
cfgPkg.BaseConfig `mapstructure:",squash"`
Postgres postgresPkg.Config `mapstructure:"postgres"`
}
// main.go
var conf config.Config
config.LoadConfig("WELLKNOWN", &conf, nil)
pgDb, err := postgresPkg.ConnectRetry(ctx, conf.Postgres, time.Minute)
```
### Using ConnectRetry
`ConnectRetry` is a function that tries to establish a db connection for the given
`maxDuration time.Duration`. It will periodically retry, using a fibonacci backoff
pattern.
For usage example, see above.
### Using MigrateUp
Given the following folder structure:
```
src/
├─ postgres/
│ ├─ postgres.go
│ ├─ migrations/
│ │ ├─ 001_init.down.sql
│ │ ├─ 001_init.up.sql
├─ main.go
```
First, create a variable of type `embed.FS` and annotate it with `//go:embed relative-path`,
pointing to the folder containing the migration files (no `.` or `..` allowed):
```golang
// postgres/postgres.go
pkg postgres
//go:embed migrations
var Migrations embed.FS
```
Then, when you established the DB connection (here in `main.go`), pass
the variable and path to `MigrateUP()`
```golang
// main.go
pkg main
func main() {
// ...
pgDb, _ := postgresPkg.ConnectRetry(...)
postgres.MigrateUP(pgDb, postgres.Migrations, "migrations")
}
```
The last parameter is the path relative to the embedded file system.
\ No newline at end of file
package migration
import (
"embed"
"errors"
"fmt"
"net/http"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/source/httpfs"
"github.com/jackc/pgx/v5/pgxpool"
)
func MigrateUP(pool *pgxpool.Pool, migrations embed.FS, migrationsPath string) error {
source, err := httpfs.New(http.FS(migrations), migrationsPath)
if err != nil {
return nil
}
m, err := migrate.NewWithSourceInstance("httpfs", source, pool.Config().ConnString())
if err != nil {
return fmt.Errorf("failed to init migration: %w", err)
}
if err := m.Up(); err != nil && errors.Is(err, migrate.ErrNoChange) {
return err
}
return nil
}
...@@ -2,8 +2,15 @@ package postgres ...@@ -2,8 +2,15 @@ package postgres
import ( import (
"context" "context"
"embed"
"errors"
"fmt"
"net/http"
"time" "time"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/httpfs"
"github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
"github.com/sethvargo/go-retry" "github.com/sethvargo/go-retry"
...@@ -48,6 +55,24 @@ func ConnectRetry(ctx context.Context, conf Config, maxDuration time.Duration, e ...@@ -48,6 +55,24 @@ func ConnectRetry(ctx context.Context, conf Config, maxDuration time.Duration, e
return return
} }
func MigrateUP(pool *pgxpool.Pool, migrations embed.FS, migrationsPath string) error {
source, err := httpfs.New(http.FS(migrations), migrationsPath)
if err != nil {
return fmt.Errorf("could not initialize source: %w", err)
}
m, err := migrate.NewWithSourceInstance("httpfs", source, pool.Config().ConnString())
if err != nil {
return fmt.Errorf("failed to init migration: %w", err)
}
if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return err
}
return nil
}
func isRetryableError(err error) bool { func isRetryableError(err error) bool {
if _, ok := err.(*pgconn.ConnectError); ok { if _, ok := err.(*pgconn.ConnectError); ok {
return true return true
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment