eintopf.info@v0.13.16/service/dbmigration/dbmigration.go (about)

     1  package dbmigration
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  )
     7  
     8  type Migration struct {
     9  	Name          string
    10  	MigrationFunc MigrationFunc
    11  	RollbackFunc  MigrationFunc
    12  }
    13  
    14  type MigrationFunc func(ctx context.Context) error
    15  
    16  func NewMigration(name string, migrationFunc, rollbackFunc MigrationFunc) Migration {
    17  	return Migration{Name: name, MigrationFunc: migrationFunc, RollbackFunc: rollbackFunc}
    18  }
    19  
    20  type Service interface {
    21  	RunMigration(ctx context.Context, migration Migration) error
    22  	RunMigrations(ctx context.Context, migrations []Migration) error
    23  }
    24  
    25  type Store interface {
    26  	AddMigration(ctx context.Context, name string) error
    27  	HasMigration(ctx context.Context, name string) (bool, error)
    28  }
    29  
    30  type MigrationService struct {
    31  	store Store
    32  }
    33  
    34  func NewService(store Store) *MigrationService {
    35  	return &MigrationService{store: store}
    36  }
    37  
    38  func (m *MigrationService) RunMigration(ctx context.Context, migration Migration) error {
    39  	hasMigrated, err := m.store.HasMigration(ctx, migration.Name)
    40  	if err != nil {
    41  		return fmt.Errorf("migration: %s: check for migration: %s", migration.Name, err)
    42  	}
    43  	if hasMigrated {
    44  		return nil
    45  	}
    46  	err = migration.MigrationFunc(ctx)
    47  	if err != nil {
    48  		return fmt.Errorf("migration: %s: %s", migration.Name, err)
    49  	}
    50  	err = m.store.AddMigration(ctx, migration.Name)
    51  	if err != nil {
    52  		if migration.RollbackFunc != nil {
    53  			rollbackErr := migration.RollbackFunc(ctx)
    54  			if rollbackErr != nil {
    55  				return fmt.Errorf("migration: %s: store: %s: failed rollback: %s", migration.Name, err, rollbackErr)
    56  			}
    57  			return fmt.Errorf("migration: %s: store: %s: rollaback succesfull", migration.Name, err)
    58  		}
    59  		return fmt.Errorf("migration: %s: store: %s: no rollback", migration.Name, err)
    60  	}
    61  	return nil
    62  }
    63  
    64  func (m *MigrationService) RunMigrations(ctx context.Context, migrations []Migration) error {
    65  	for _, migration := range migrations {
    66  		err := m.RunMigration(ctx, migration)
    67  		if err != nil {
    68  			return err
    69  		}
    70  	}
    71  	return nil
    72  }