Skip to content

Commit

Permalink
Require migration to run Horizon version successfully (fixes #778) (#808
Browse files Browse the repository at this point in the history
)

* first pass

* extracted data structures for set comparing migrations

* migration set differencing

* remove debug printing

* minor review comments

* simplified logic for down migrations

* further review comments

* fix out of date comment

* fix spacing
  • Loading branch information
ire-and-curses committed Jan 17, 2019
1 parent eac57a5 commit f931bc7
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
51 changes: 51 additions & 0 deletions services/horizon/internal/db2/schema/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package schema
import (
"database/sql"
"errors"
stdLog "log"

migrate "github.com/rubenv/sql-migrate"
"github.com/stellar/go/support/db"
Expand Down Expand Up @@ -68,3 +69,53 @@ func Migrate(db *sql.DB, dir MigrateDir, count int) (int, error) {
return 0, errors.New("Invalid migration direction")
}
}

// GetMigrationsUp returns a list of names of any migrations needed in the
// "up" direction (more recent schema versions).
func GetMigrationsUp(dbUrl string) (migrationIds []string) {
// Get a DB handle
db, dbErr := sql.Open("postgres", dbUrl)
if dbErr != nil {
stdLog.Fatal(dbErr)
}

// Get the possible migrations
possibleMigrations, _, migrateErr := migrate.PlanMigration(db, "postgres", Migrations, migrate.Up, 0)
if migrateErr != nil {
stdLog.Fatal(migrateErr)
}

// Extract a list of the possible migration names
for _, m := range possibleMigrations {
migrationIds = append(migrationIds, m.Id)
}

return migrationIds
}

// GetNumMigrationsDown returns the number of migrations to apply in the
// "down" direction to return to the older schema version expected by this
// version of Horizon. To keep the code simple, it does not provide a list of
// migration names.
func GetNumMigrationsDown(dbUrl string) (nMigrations int) {
// Get a DB handle
db, dbErr := sql.Open("postgres", dbUrl)
if dbErr != nil {
stdLog.Fatal(dbErr)
}

// Get the set of migrations recorded in the database
migrationRecords, recordErr := migrate.GetMigrationRecords(db, "postgres")
if recordErr != nil {
stdLog.Fatal(recordErr)
}

// Get the list of migrations needed by this version of Horizon
allNeededMigrations, _, migrateErr := migrate.PlanMigration(db, "postgres", Migrations, migrate.Down, 0)
if migrateErr != nil {
stdLog.Fatal(migrateErr)
}

// Return the size difference between the two sets of migrations
return len(migrationRecords) - len(allNeededMigrations)
}
19 changes: 18 additions & 1 deletion services/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stellar/go/network"
"github.com/stellar/go/services/horizon/internal"
horizon "github.com/stellar/go/services/horizon/internal"
"github.com/stellar/go/services/horizon/internal/db2/schema"
apkg "github.com/stellar/go/support/app"
"github.com/stellar/go/support/log"
"github.com/throttled/throttled"
)
Expand Down Expand Up @@ -244,6 +246,21 @@ func initConfig() {
stdLog.Fatal("Invalid config: network-passphrase is blank. Please specify --network-passphrase on the command line or set the NETWORK_PASSPHRASE environment variable.")
}

migrationsToApplyUp := schema.GetMigrationsUp(viper.GetString("db-url"))
if len(migrationsToApplyUp) > 0 {
stdLog.Printf(`There are %v migrations to apply in the "up" direction.`, len(migrationsToApplyUp))
stdLog.Printf("The necessary migrations are: %v", migrationsToApplyUp)
stdLog.Printf("A database migration is required to run this version (%v) of Horizon. Run \"horizon db migrate up\" to update your DB. Consult the Changelog (https://github.com/stellar/horizon/blob/master/CHANGELOG.md) for more information.", apkg.Version())
os.Exit(1)
}

nMigrationsDown := schema.GetNumMigrationsDown(viper.GetString("db-url"))
if nMigrationsDown > 0 {
stdLog.Printf("A database migration DOWN to an earlier version of the schema is required to run this version (%v) of Horizon. Consult the Changelog (https://github.com/stellar/horizon/blob/master/CHANGELOG.md) for more information.", apkg.Version())
stdLog.Printf("In order to migrate the database DOWN, using the HIGHEST version number of Horizon you have installed (not this binary), run \"horizon db migrate down %v\".", nMigrationsDown)
os.Exit(1)
}

ll, err := logrus.ParseLevel(viper.GetString("log-level"))

if err != nil {
Expand Down

0 comments on commit f931bc7

Please sign in to comment.