Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
Fail connector startup on migration failure
Browse files Browse the repository at this point in the history
Connector should abort starting up if it cannot setup the required schema.
  • Loading branch information
antekresic committed Apr 28, 2020
1 parent 988bf3c commit 9a78cbd
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
36 changes: 21 additions & 15 deletions cmd/timescale-prometheus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package main
import (
"database/sql"
"flag"
"fmt"
"io/ioutil"
"net/http"
_ "net/http/pprof"
Expand All @@ -31,8 +32,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
io_prometheus_client "github.com/prometheus/client_model/go"
"github.com/prometheus/prometheus/prompb"

"fmt"
)

type config struct {
Expand Down Expand Up @@ -140,17 +139,26 @@ func main() {
elector, err = initElector(cfg)

if err != nil {
log.Error("msg", err.Error())
log.Error("msg", "Aborting startup because of elector init error: %s", err.Error())
os.Exit(1)
}

if elector == nil {
log.Warn("msg", "No adapter leader election. Group lock id is not set. Possible duplicate write load if running adapter in high-availability mode")
log.Warn(
"msg",
"No adapter leader election. Group lock id is not set. "+
"Possible duplicate write load if running adapter in high-availability mode",
)
}

// migrate has to happen after elector started
if cfg.migrate {
migrate(&cfg.pgmodelCfg)
err = migrate(&cfg.pgmodelCfg)

if err != nil {
log.Error("msg", "Aborting startup because of migration error: %s", err.Error())
os.Exit(1)
}
}

// client has to be initiated after migrate since migrate
Expand Down Expand Up @@ -229,39 +237,37 @@ func initElector(cfg *config) (*util.Elector, error) {
return &scheduledElector.Elector, nil
}

func migrate(cfg *pgclient.Config) {
func migrate(cfg *pgclient.Config) error {
shouldWrite, err := isWriter()
if err != nil {
leaderGauge.Set(0)
log.Error("msg", "IsLeader check failed", "err", err)
return
return fmt.Errorf("isWriter check failed: %w", err)
}
if !shouldWrite {
leaderGauge.Set(0)
log.Debug("msg", fmt.Sprintf("Election id %v: Instance is not a leader. Won't update", elector.ID()))
return
return nil
}

leaderGauge.Set(1)
dbStd, err := sql.Open("pgx", cfg.GetConnectionStr())
if err != nil {
log.Error(err)
return
return fmt.Errorf("Error while trying to open DB connection: %w", err)
}
defer func() {
err := dbStd.Close()
if err != nil {
log.Error(err)
return
log.Error("msg", "Error while trying to close DB connection: %s", err)
}
}()

err = pgmodel.Migrate(dbStd)

if err != nil {
log.Error(err)
return
return fmt.Errorf("Error while trying to migrate DB: %w", err)
}

return nil
}

func write(writer pgmodel.DBInserter) http.Handler {
Expand Down
24 changes: 18 additions & 6 deletions cmd/timescale-prometheus/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (

"github.com/gogo/protobuf/proto"
"github.com/golang/snappy"

"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/prometheus/prompb"

"github.com/timescale/timescale-prometheus/pkg/log"
"github.com/timescale/timescale-prometheus/pkg/pgclient"
"github.com/timescale/timescale-prometheus/pkg/util"
Expand Down Expand Up @@ -521,18 +523,21 @@ func TestMigrate(t *testing.T) {
cfg *pgclient.Config
isLeader bool
electionErr error
shouldError bool
}{
{
name: "elector error",
electionErr: fmt.Errorf("some error"),
shouldError: true,
},
{
name: "not a leader",
},
{
name: "is leader",
isLeader: true,
cfg: &pgclient.Config{},
name: "is leader",
isLeader: true,
cfg: &pgclient.Config{},
shouldError: true,
},
}
for _, c := range testCases {
Expand All @@ -546,13 +551,20 @@ func TestMigrate(t *testing.T) {
mockGauge := &mockGauge{}
leaderGauge = mockGauge

migrate(c.cfg)
err := migrate(c.cfg)

switch {
case err != nil && !c.shouldError:
t.Errorf("Unexpected error returned:\ngot\n%s\nwanted nil\n", err)
case err == nil && c.shouldError:
t.Errorf("Expected error to be returned: got nil")
}

switch {
case c.isLeader && mockGauge.value != 1:
t.Errorf("leader gauge metric not set correctly: got %f when is leader", mockGauge.value)
t.Errorf("Leader gauge metric not set correctly: got %f when is leader", mockGauge.value)
case !c.isLeader && mockGauge.value != 0:
t.Errorf("leader gauge metric not set correctly: got %f when is not leader", mockGauge.value)
t.Errorf("Leader gauge metric not set correctly: got %f when is not leader", mockGauge.value)
}
})
}
Expand Down

0 comments on commit 9a78cbd

Please sign in to comment.