Skip to content

Commit

Permalink
services/horizon/cmd: Check ingest flag before executing horizon db m…
Browse files Browse the repository at this point in the history
…igrate commands (#4664)

Only apply migrations in the horizon db migrate commands if the ingest flag is true.
  • Loading branch information
tamirms authored Oct 18, 2022
1 parent 11b0616 commit 012bfe5
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 12 deletions.
8 changes: 8 additions & 0 deletions services/horizon/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
All notable changes to this project will be documented in this
file. This project adheres to [Semantic Versioning](http://semver.org/).

## 2.22.1

**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.**

### Fixes

- `horizon db migrate` commands will not apply migrations if ingestion is disabled ([4664](https://github.com/stellar/go/pull/4664)).

## 2.22.0

**Upgrading to this version from <= v2.8.3 will trigger a state rebuild. During this process (which will take at least 10 minutes), Horizon will not ingest new ledgers.**
Expand Down
41 changes: 30 additions & 11 deletions services/horizon/cmd/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"log"
"os"
"strconv"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -32,23 +33,36 @@ var dbMigrateCmd = &cobra.Command{
Short: "commands to run schema migrations on horizon's postgres db",
}

func requireAndSetFlag(name string) error {
func requireAndSetFlags(names ...string) error {
set := map[string]bool{}
for _, name := range names {
set[name] = true
}
for _, flag := range flags {
if flag.Name == name {
if set[flag.Name] {
flag.Require()
flag.SetValue()
return nil
if err := flag.SetValue(); err != nil {
return err
}
delete(set, flag.Name)
}
}
return fmt.Errorf("could not find %s flag", name)
if len(set) == 0 {
return nil
}
var missing []string
for name := range set {
missing = append(missing, name)
}
return fmt.Errorf("could not find %s flags", strings.Join(missing, ","))
}

var dbInitCmd = &cobra.Command{
Use: "init",
Short: "install schema",
Long: "init initializes the postgres database used by horizon.",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil {
return err
}

Expand All @@ -72,6 +86,11 @@ var dbInitCmd = &cobra.Command{
}

func migrate(dir schema.MigrateDir, count int) error {
if !config.Ingest {
log.Println("Skipping migrations because ingest flag is not enabled")
return nil
}

dbConn, err := db.Open("postgres", config.DatabaseURL)
if err != nil {
return err
Expand All @@ -95,7 +114,7 @@ var dbMigrateDownCmd = &cobra.Command{
Short: "run downwards db schema migrations",
Long: "performs a downards schema migration command",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil {
return err
}

Expand All @@ -119,7 +138,7 @@ var dbMigrateRedoCmd = &cobra.Command{
Short: "redo db schema migrations",
Long: "performs a redo schema migration command",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil {
return err
}

Expand All @@ -143,7 +162,7 @@ var dbMigrateStatusCmd = &cobra.Command{
Short: "print current database migration status",
Long: "print current database migration status",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName); err != nil {
return err
}

Expand Down Expand Up @@ -173,7 +192,7 @@ var dbMigrateUpCmd = &cobra.Command{
Short: "run upwards db schema migrations",
Long: "performs an upwards schema migration command",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName, horizon.IngestFlagName); err != nil {
return err
}

Expand Down Expand Up @@ -453,7 +472,7 @@ var dbDetectGapsCmd = &cobra.Command{
Short: "detects ingestion gaps in Horizon's database",
Long: "detects ingestion gaps in Horizon's database and prints a list of reingest commands needed to fill the gaps",
RunE: func(cmd *cobra.Command, args []string) error {
if err := requireAndSetFlag(horizon.DatabaseURLFlagName); err != nil {
if err := requireAndSetFlags(horizon.DatabaseURLFlagName); err != nil {
return err
}

Expand Down
4 changes: 3 additions & 1 deletion services/horizon/internal/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
const (
// DatabaseURLFlagName is the command line flag for configuring the Horizon postgres URL
DatabaseURLFlagName = "db-url"
// IngestFlagName is the command line flag for enabling ingestion on the Horizon instance
IngestFlagName = "ingest"
// StellarCoreDBURLFlagName is the command line flag for configuring the postgres Stellar Core URL
StellarCoreDBURLFlagName = "stellar-core-db-url"
// StellarCoreURLFlagName is the command line flag for configuring the URL fore Stellar Core HTTP endpoint
Expand Down Expand Up @@ -456,7 +458,7 @@ func Flags() (*Config, support.ConfigOptions) {
Usage: "TLS private key file to use for securing connections to horizon",
},
&support.ConfigOption{
Name: "ingest",
Name: IngestFlagName,
ConfigKey: &config.Ingest,
OptType: types.Bool,
FlagDefault: true,
Expand Down
42 changes: 42 additions & 0 deletions services/horizon/internal/integration/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,48 @@ func command(horizonConfig horizon.Config, args ...string) []string {
}, args...)
}

func TestMigrateIngestIsTrueByDefault(t *testing.T) {
tt := assert.New(t)
// Create a fresh Horizon database
newDB := dbtest.Postgres(t)
freshHorizonPostgresURL := newDB.DSN

horizoncmd.RootCmd.SetArgs([]string{
// ingest is set to true by default
"--db-url", freshHorizonPostgresURL,
"db", "migrate", "up",
})
tt.NoError(horizoncmd.RootCmd.Execute())

dbConn, err := db.Open("postgres", freshHorizonPostgresURL)
tt.NoError(err)

status, err := schema.Status(dbConn.DB.DB)
tt.NoError(err)
tt.NotContains(status, "1_initial_schema.sql\t\t\t\t\t\tno")
}

func TestMigrateChecksIngestFlag(t *testing.T) {
tt := assert.New(t)
// Create a fresh Horizon database
newDB := dbtest.Postgres(t)
freshHorizonPostgresURL := newDB.DSN

horizoncmd.RootCmd.SetArgs([]string{
"--ingest=false",
"--db-url", freshHorizonPostgresURL,
"db", "migrate", "up",
})
tt.NoError(horizoncmd.RootCmd.Execute())

dbConn, err := db.Open("postgres", freshHorizonPostgresURL)
tt.NoError(err)

status, err := schema.Status(dbConn.DB.DB)
tt.NoError(err)
tt.Contains(status, "1_initial_schema.sql\t\t\t\t\t\tno")
}

func TestFillGaps(t *testing.T) {
itest, reachedLedger := initializeDBIntegrationTest(t)
tt := assert.New(t)
Expand Down

0 comments on commit 012bfe5

Please sign in to comment.