Add initial support for database migrations

This commit is contained in:
Till Faelligen 2023-07-28 15:10:15 +02:00
parent 2191248cda
commit 9b7d27dd87
No known key found for this signature in database
GPG Key ID: ACCDC9606D472758
3 changed files with 83 additions and 0 deletions

View File

@ -1,7 +1,9 @@
package main
import (
"flag"
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"os"
@ -16,6 +18,7 @@ import (
syncv3 "github.com/matrix-org/sliding-sync"
"github.com/matrix-org/sliding-sync/internal"
"github.com/matrix-org/sliding-sync/sync2"
"github.com/pressly/goose/v3"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/zerolog"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
@ -25,6 +28,10 @@ var GitCommit string
const version = "0.99.4"
var (
flags = flag.NewFlagSet("goose", flag.ExitOnError)
)
const (
// Required fields
EnvServer = "SYNCV3_SERVER"
@ -71,6 +78,12 @@ func main() {
fmt.Printf("Sync v3 [%s] (%s)\n", version, GitCommit)
sync2.ProxyVersion = version
syncv3.Version = fmt.Sprintf("%s (%s)", version, GitCommit)
if os.Args[1] == "migrate" {
executeMigrations()
return
}
args := map[string]string{
EnvServer: os.Getenv(EnvServer),
EnvDB: os.Getenv(EnvDB),
@ -216,3 +229,49 @@ func WaitForShutdown(sentryInUse bool) {
fmt.Printf("Exiting now")
}
func executeMigrations() {
envArgs := map[string]string{
EnvDB: os.Getenv(EnvDB),
}
requiredEnvVars := []string{EnvDB}
for _, requiredEnvVar := range requiredEnvVars {
if envArgs[requiredEnvVar] == "" {
fmt.Print(helpMsg)
fmt.Printf("\n%s is not set", requiredEnvVar)
fmt.Printf("\n%s must be set\n", strings.Join(requiredEnvVars, ", "))
os.Exit(1)
}
}
flags.Parse(os.Args[1:])
args := flags.Args()
if len(args) < 2 {
flags.Usage()
return
}
command := args[1]
db, err := goose.OpenDBWithDriver("postgres", envArgs[EnvDB])
if err != nil {
log.Fatalf("goose: failed to open DB: %v\n", err)
}
defer func() {
if err := db.Close(); err != nil {
log.Fatalf("goose: failed to close DB: %v\n", err)
}
}()
arguments := []string{}
if len(args) > 2 {
arguments = append(arguments, args[2:]...)
}
goose.SetBaseFS(syncv3.EmbedMigrations)
if err := goose.Run(command, db, "state/migrations", arguments...); err != nil {
log.Fatalf("goose %v: %v", command, err)
}
}

View File

@ -0,0 +1,11 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE syncv3_device_data DROP COLUMN IF EXISTS id;
DROP SEQUENCE IF EXISTS syncv3_device_data_seq;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
CREATE SEQUENCE IF NOT EXISTS syncv3_device_data_seq;
ALTER TABLE syncv3_device_data ADD COLUMN IF NOT EXISTS id BIGINT PRIMARY KEY NOT NULL DEFAULT nextval('syncv3_device_data_seq') ;
-- +goose StatementEnd

13
v3.go
View File

@ -1,6 +1,7 @@
package slidingsync
import (
"embed"
"encoding/json"
"fmt"
"net/http"
@ -10,6 +11,7 @@ import (
"github.com/getsentry/sentry-go"
"github.com/jmoiron/sqlx"
"github.com/pressly/goose/v3"
"github.com/gorilla/mux"
"github.com/matrix-org/sliding-sync/internal"
@ -22,6 +24,9 @@ import (
"github.com/rs/zerolog/hlog"
)
//go:embed state/migrations/*
var EmbedMigrations embed.FS
var logger = zerolog.New(os.Stdout).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{
Out: os.Stderr,
TimeFormat: "15:04:05",
@ -83,6 +88,14 @@ func Setup(destHomeserver, postgresURI, secret string, opts Opts) (*handler2.Han
// TODO: if we panic(), will sentry have a chance to flush the event?
logger.Panic().Err(err).Str("uri", postgresURI).Msg("failed to open SQL DB")
}
// Automatically execute migrations
goose.SetBaseFS(EmbedMigrations)
err = goose.Up(db.DB, "state/migrations", goose.WithAllowMissing())
if err != nil {
logger.Panic().Err(err).Msg("failed to execute migrations")
}
if opts.DBMaxConns > 0 {
// https://github.com/go-sql-driver/mysql#important-settings
// "db.SetMaxIdleConns() is recommended to be set same to db.SetMaxOpenConns(). When it is smaller