From d0c892c61b5afb8fa0f2f54b535b109522728730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bahattin=20=C3=87ini=C3=A7?= Date: Mon, 10 Jun 2024 11:16:20 +0300 Subject: [PATCH] feat: Added robust database migration layer --- database/database.go | 16 ++- database/migrations/202404171309_strava.go | 99 +++++++++++++++++++ database/migrations/202404171310_config.go | 31 ++++++ database/migrations/202404171311_dashboard.go | 39 ++++++++ database/migrations/migrations.go | 33 +++++++ go.mod | 3 +- go.sum | 5 +- 7 files changed, 214 insertions(+), 12 deletions(-) create mode 100644 database/migrations/202404171309_strava.go create mode 100644 database/migrations/202404171310_config.go create mode 100644 database/migrations/202404171311_dashboard.go create mode 100644 database/migrations/migrations.go diff --git a/database/database.go b/database/database.go index 00224d3..b609edc 100644 --- a/database/database.go +++ b/database/database.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/bahattincinic/fitwave/config" - "github.com/bahattincinic/fitwave/models" + "github.com/bahattincinic/fitwave/database/migrations" pkgerrors "github.com/pkg/errors" "go.uber.org/zap" "gorm.io/driver/mysql" @@ -19,6 +19,7 @@ type Database struct { db *gorm.DB cfg *config.Config log *zap.Logger + mig *migrations.Migration } func NewDatabase(ctx context.Context, log *zap.Logger, cfg *config.Config) (*Database, error) { @@ -39,11 +40,14 @@ func NewDatabase(ctx context.Context, log *zap.Logger, cfg *config.Config) (*Dat return nil, pkgerrors.Wrap(err, "Open") } + mig := migrations.NewMigration(db) + d := &Database{ db: db, ctx: ctx, log: log, cfg: cfg, + mig: mig, } if cfg.Database.AutoMigrate { @@ -56,15 +60,7 @@ func NewDatabase(ctx context.Context, log *zap.Logger, cfg *config.Config) (*Dat } func (d *Database) Migrate() error { - m := []interface{}{ - &models.Activity{}, - &models.Athlete{}, - &models.Gear{}, - &models.Config{}, - &models.Dashboard{}, - &models.Component{}, - } - return d.db.AutoMigrate(m...) + return d.mig.Migrate() } func (d *Database) BeginTransaction() *gorm.DB { diff --git a/database/migrations/202404171309_strava.go b/database/migrations/202404171309_strava.go new file mode 100644 index 0000000..e619c8a --- /dev/null +++ b/database/migrations/202404171309_strava.go @@ -0,0 +1,99 @@ +package migrations + +import ( + "time" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// createStravaTables returns the migrations for creating Strava-related tables. +func (m *Migration) createStravaTables() []*gormigrate.Migration { + return []*gormigrate.Migration{{ + ID: "202404171309", + Migrate: func(tx *gorm.DB) error { + type athlete struct { + Id int64 `gorm:"primaryKey;autoIncrement:false"` + FirstName string + LastName string + ProfileMedium string + Profile string + City string + State string + Country string + Gender string + Friend string + Follower string + Premium bool + CreatedAt time.Time + UpdatedAt time.Time + ApproveFollowers bool + BadgeTypeId int + Stats datatypes.JSON + } + type gear struct { + Id string `gorm:"primaryKey;autoIncrement:false"` + Name string + Primary bool + Distance float64 + BrandName string + ModelName string + Type string + Description string + AthleteID int64 + Athlete *athlete `gorm:"foreignkey:AthleteID"` + } + type activity struct { + Id int64 `gorm:"primaryKey;autoIncrement:false"` + ExternalId string + UploadId int64 + Name string + Distance float64 + MovingTime int + ElapsedTime int + TotalElevationGain float64 + Type string + StartDate time.Time + StartDateLocal time.Time + TimeZone string + StartLocation datatypes.JSON + EndLocation datatypes.JSON + City string + State string + Country string + AchievementCount int + KudosCount int + CommentCount int + AthleteCount int + PhotoCount int + Map datatypes.JSON + Trainer bool + Commute bool + Manual bool + Private bool + Flagged bool + AverageSpeed float64 + MaximumSpeed float64 + AverageCadence float64 + AverageTemperature float64 + AveragePower float64 + WeightedAveragePower int + Kilojoules float64 + DeviceWatts bool + AverageHeartRate float64 + MaximumHeartRate float64 + Truncated int + HasKudos bool + AthleteID uint + Athlete athlete `gorm:"foreignkey:AthleteID"` + GearID *string + Gear *athlete `gorm:"foreignkey:GearID"` + } + return tx.AutoMigrate(&activity{}, &athlete{}, &gear{}) + }, + Rollback: func(tx *gorm.DB) error { + return tx.Migrator().DropTable("activities", "gears", "athletes") + }, + }} +} diff --git a/database/migrations/202404171310_config.go b/database/migrations/202404171310_config.go new file mode 100644 index 0000000..478778a --- /dev/null +++ b/database/migrations/202404171310_config.go @@ -0,0 +1,31 @@ +package migrations + +import ( + "time" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// createConfigTable returns the migration for creating the Config table. +func (m *Migration) createConfigTable() []*gormigrate.Migration { + return []*gormigrate.Migration{{ + ID: "202404171310", + Migrate: func(tx *gorm.DB) error { + type config struct { + ID uint `gorm:"primarykey"` + CreatedAt time.Time + UpdatedAt time.Time + ClientId int + ClientSecret string + LoginType string + LoginUsername string + LoginPassword string + } + return tx.AutoMigrate(&config{}) + }, + Rollback: func(tx *gorm.DB) error { + return tx.Migrator().DropTable("configs") + }, + }} +} diff --git a/database/migrations/202404171311_dashboard.go b/database/migrations/202404171311_dashboard.go new file mode 100644 index 0000000..caf9415 --- /dev/null +++ b/database/migrations/202404171311_dashboard.go @@ -0,0 +1,39 @@ +package migrations + +import ( + "time" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// createDashboardTables returns the migrations for creating Dashboard-related tables. +func (m *Migration) createDashboardTables() []*gormigrate.Migration { + return []*gormigrate.Migration{{ + ID: "202404171311", + Migrate: func(tx *gorm.DB) error { + type dashboard struct { + ID uint `gorm:"primarykey"` + CreatedAt time.Time + UpdatedAt time.Time + Name string + } + type component struct { + ID uint `gorm:"primarykey"` + CreatedAt time.Time + UpdatedAt time.Time + DashboardID uint + Dashboard dashboard `gorm:"foreignkey:DashboardID"` + Name string + Query string + Type string + Configs datatypes.JSON + } + return tx.AutoMigrate(&dashboard{}, &component{}) + }, + Rollback: func(tx *gorm.DB) error { + return tx.Migrator().DropTable("dashboards", "components") + }, + }} +} diff --git a/database/migrations/migrations.go b/database/migrations/migrations.go new file mode 100644 index 0000000..3dc975f --- /dev/null +++ b/database/migrations/migrations.go @@ -0,0 +1,33 @@ +package migrations + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +type Migration struct { + migrations []*gormigrate.Migration + migrate *gormigrate.Gormigrate +} + +func NewMigration(db *gorm.DB) *Migration { + m := &Migration{} + m.migrate = gormigrate.New(db, gormigrate.DefaultOptions, m.Get()) + return m +} + +// Get returns the list of all migrations to be applied. +func (m *Migration) Get() []*gormigrate.Migration { + var migrations []*gormigrate.Migration + + migrations = append(migrations, m.createStravaTables()...) + migrations = append(migrations, m.createConfigTable()...) + migrations = append(migrations, m.createDashboardTables()...) + + return migrations +} + +// Migrate applies the migrations to the database. +func (m *Migration) Migrate() error { + return m.migrate.Migrate() +} diff --git a/go.mod b/go.mod index fce781f..e786e8a 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/caarlos0/env/v10 v10.0.0 + github.com/go-gormigrate/gormigrate/v2 v2.1.2 github.com/go-playground/validator v9.31.0+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/uuid v1.6.0 @@ -20,7 +21,7 @@ require ( gorm.io/driver/mysql v1.4.7 gorm.io/driver/postgres v1.5.0 gorm.io/driver/sqlite v1.4.4 - gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 + gorm.io/gorm v1.25.8 ) require ( diff --git a/go.sum b/go.sum index 6c374a4..0f24f2b 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ 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/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gormigrate/gormigrate/v2 v2.1.2 h1:F/d1hpHbRAvKezziV2CC5KUE82cVe9zTgHSBoOOZ4CY= +github.com/go-gormigrate/gormigrate/v2 v2.1.2/go.mod h1:9nHVX6z3FCMCQPA7PThGcA55t22yKQfK/Dnsf5i7hUo= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -191,5 +193,6 @@ gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2e gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo= +gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=