linstrom/storage-new/migrations.go
mstar dff031397e
Some checks failed
/ docker (push) Failing after 2m51s
More activity stuff
2025-05-05 17:33:34 +02:00

169 lines
4.5 KiB
Go

package storage
import (
"fmt"
"strings"
"git.mstar.dev/mstar/goutils/other"
"git.mstar.dev/mstar/goutils/sliceutils"
"github.com/rs/zerolog"
"gorm.io/gorm"
"git.mstar.dev/mstar/linstrom/storage-new/models"
)
// Auto-migrate all tables and types used
func Migrate(db *gorm.DB) error {
// Shut up gorm's queries during automigrate by setting log level to info during migration
// and then back to the previous value on exit
currentLogLevel := zerolog.GlobalLevel()
zerolog.SetGlobalLevel(zerolog.InfoLevel)
defer zerolog.SetGlobalLevel(currentLogLevel)
if err := createAccountAuthMethodType(db); err != nil {
return other.Error("storage", "Failed to create Auth Method type", err)
}
if err := createBeingType(db); err != nil {
return other.Error("storage", "Failed to create Being type", err)
}
if err := createAccountRelationType(db); err != nil {
return other.Error("storage", "Failed to create Account Relation type", err)
}
if err := createRemoteServerSoftwareType(db); err != nil {
return other.Error("storage", "Failed to create Server Software type", err)
}
if err := createActitiystreamsObjectType(db); err != nil {
return other.Error("storage", "Failed to create Activitystreams Object type", err)
}
if err := createActitiystreamsActivityType(db); err != nil {
return other.Error("storage", "Failed to create Activitystreams Activity type", err)
}
if err := createCollectionTarget(db); err != nil {
return other.Error("storage", "Failed t ocreate collections target type", err)
}
if err := migrateTypes(db); err != nil {
return other.Error("storage", "Failed to automigrate data structs", err)
}
return nil
}
// Returns the raw error created by gorm, with no wrapping
func migrateTypes(db *gorm.DB) error {
if err := db.AutoMigrate(models.AllTypes...); err != nil {
return err
}
return nil
}
// Ensure the being enum exists for the user
func createBeingType(db *gorm.DB) error {
return migrateEnum(
db,
"being_type",
sliceutils.Map(models.AllBeings, func(t models.BeingType) string { return string(t) }),
)
}
func createAccountRelationType(db *gorm.DB) error {
return migrateEnum(
db,
"relation_type",
sliceutils.Map(
models.AllRelations,
func(t models.RelationType) string { return string(t) },
),
)
}
func createAccountAuthMethodType(db *gorm.DB) error {
return migrateEnum(
db,
"auth_method_type",
sliceutils.Map(
models.AllAuthMethods,
func(t models.AuthenticationMethodType) string { return string(t) },
),
)
}
func createRemoteServerSoftwareType(db *gorm.DB) error {
return migrateEnum(
db,
"server_software_type",
sliceutils.Map(
models.AllServerSoftwareTypes,
func(t models.ServerSoftwareType) string { return string(t) },
),
)
}
func createActitiystreamsObjectType(db *gorm.DB) error {
return migrateEnum(
db,
"activitystreams_object_type",
sliceutils.Map(
models.AllActivitystreamsObjectTypes,
func(t models.ActivitystreamsObjectType) string { return string(t) },
),
)
}
func createActitiystreamsActivityType(db *gorm.DB) error {
return migrateEnum(
db,
"activitystreams_activity_type",
sliceutils.Map(
models.AllActivitystreamsActivityTypes,
func(t models.ActivitystreamsActivityType) string { return string(t) },
),
)
}
func createActitiystreamsActivityTargetType(db *gorm.DB) error {
return migrateEnum(
db,
"activitystreams_activity_target_type",
sliceutils.Map(
models.AllActivitystreamsActivityTargetTypes,
func(t models.ActivitystreamsActivityTargetType) string { return string(t) },
),
)
}
func createCollectionTarget(db *gorm.DB) error {
return migrateEnum(
db,
"collection_target_type",
sliceutils.Map(
models.AllCollectionTargetTypes,
func(t models.CollectionTargetType) string { return string(t) },
),
)
}
// Helper function for ensuring the existence of an enum with the given values
func migrateEnum(db *gorm.DB, name string, values []string) error {
if err := db.Exec("DROP TYPE IF EXISTS " + name + " CASCADE;").Error; err != nil {
return other.Error(
"storage",
fmt.Sprintf("Failed to remove old type %s (if it exists)", name),
err,
)
}
queryBuilder := strings.Builder{}
queryBuilder.WriteString("CREATE TYPE ")
queryBuilder.WriteString(name)
queryBuilder.WriteString(" AS ENUM (")
blen := len(values)
for i, btype := range values {
queryBuilder.WriteString("'" + string(btype) + "'")
// Append comma everywhere except last entry
if i+1 < blen {
queryBuilder.WriteString(",")
}
}
queryBuilder.WriteString(");")
if err := db.Exec(queryBuilder.String()).Error; err != nil {
return err
}
return nil
}