From ff136b6ba89fb37d45ef954bca6d95c2f62671b1 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Dec 2018 13:45:58 +0100 Subject: [PATCH 1/7] initial verison of server lock --- pkg/cmd/grafana-server/server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cmd/grafana-server/server.go b/pkg/cmd/grafana-server/server.go index d9fd1e62ce7..4781361b9b9 100644 --- a/pkg/cmd/grafana-server/server.go +++ b/pkg/cmd/grafana-server/server.go @@ -28,6 +28,7 @@ import ( // self registering services _ "github.com/grafana/grafana/pkg/extensions" + _ "github.com/grafana/grafana/pkg/infra/serverlock" _ "github.com/grafana/grafana/pkg/metrics" _ "github.com/grafana/grafana/pkg/plugins" _ "github.com/grafana/grafana/pkg/services/alerting" From dc49bebb003180f70d3f1f53973b99de8f147468 Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Dec 2018 14:00:09 +0100 Subject: [PATCH 2/7] adds server lock package --- pkg/infra/serverlock/migrations.go | 23 ++++ pkg/infra/serverlock/model.go | 8 ++ pkg/infra/serverlock/serverlock.go | 111 ++++++++++++++++++ .../serverlock/serverlock_integration_test.go | 75 ++++++++++++ pkg/infra/serverlock/serverlock_test.go | 57 +++++++++ 5 files changed, 274 insertions(+) create mode 100644 pkg/infra/serverlock/migrations.go create mode 100644 pkg/infra/serverlock/model.go create mode 100644 pkg/infra/serverlock/serverlock.go create mode 100644 pkg/infra/serverlock/serverlock_integration_test.go create mode 100644 pkg/infra/serverlock/serverlock_test.go diff --git a/pkg/infra/serverlock/migrations.go b/pkg/infra/serverlock/migrations.go new file mode 100644 index 00000000000..4b9f95053a2 --- /dev/null +++ b/pkg/infra/serverlock/migrations.go @@ -0,0 +1,23 @@ +package serverlock + +import "github.com/grafana/grafana/pkg/services/sqlstore/migrator" + +// AddMigration create database migrations for server lock +func (sl *ServerLockService) AddMigration(mg *migrator.Migrator) { + serverLock := migrator.Table{ + Name: "server_lock", + Columns: []*migrator.Column{ + {Name: "id", Type: migrator.DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "operation_uid", Type: migrator.DB_Text}, + {Name: "version", Type: migrator.DB_BigInt}, + {Name: "last_execution", Type: migrator.DB_BigInt, Nullable: false}, + }, + Indices: []*migrator.Index{ + {Cols: []string{"operation_uid"}, Type: migrator.UniqueIndex}, + }, + } + + mg.AddMigration("create server_lock table", migrator.NewAddTableMigration(serverLock)) + + mg.AddMigration("add index server_lock.operation_uid", migrator.NewAddIndexMigration(serverLock, serverLock.Indices[0])) +} diff --git a/pkg/infra/serverlock/model.go b/pkg/infra/serverlock/model.go new file mode 100644 index 00000000000..7e0ea7814b1 --- /dev/null +++ b/pkg/infra/serverlock/model.go @@ -0,0 +1,8 @@ +package serverlock + +type serverLock struct { + Id int64 + OperationUid string + LastExecution int64 + Version int64 +} diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go new file mode 100644 index 00000000000..08aededeba9 --- /dev/null +++ b/pkg/infra/serverlock/serverlock.go @@ -0,0 +1,111 @@ +package serverlock + +import ( + "context" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/registry" + "github.com/grafana/grafana/pkg/services/sqlstore" +) + +func init() { + registry.RegisterService(&ServerLockService{}) +} + +// ServerLockService allows servers in HA mode to execute function once over in the group +type ServerLockService struct { + SQLStore *sqlstore.SqlStore `inject:""` + log log.Logger +} + +// Init this service +func (sl *ServerLockService) Init() error { + return nil +} + +// OncePerServerGroup try to create a lock for this server and only executes the +// `fn` function when successful. This should not be used at low internal. But services +// that needs to be run once every ex 10m. +func (sl *ServerLockService) OncePerServerGroup(ctx context.Context, actionName string, maxEvery time.Duration, fn func()) error { + rowLock, err := sl.getOrCreate(ctx, actionName) + if err != nil { + return err + } + + if rowLock.LastExecution != 0 { + lastExeuctionTime := time.Unix(rowLock.LastExecution, 0) + if lastExeuctionTime.Unix() > time.Now().Add(-maxEvery).Unix() { + return nil + } + } + + acquiredLock, err := sl.acquireLock(ctx, rowLock, maxEvery) + if err != nil { + return err + } + + if acquiredLock { + fn() + } + + return nil +} + +func (sl *ServerLockService) acquireLock(ctx context.Context, serverLock *serverLock, maxEvery time.Duration) (bool, error) { + var result bool + + err := sl.SQLStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { + newVersion := serverLock.Version + 1 + sql := `UPDATE server_lock SET + version = ?, + last_execution = ? + WHERE + id = ? AND version = ?` + + res, err := dbSession.Exec(sql, newVersion, time.Now().Unix(), serverLock.Id, serverLock.Version) + if err != nil { + return err + } + + affected, err := res.RowsAffected() + result = affected == 1 + + return err + }) + + return result, err +} + +func (sl *ServerLockService) getOrCreate(ctx context.Context, actionName string) (*serverLock, error) { + var result *serverLock + + err := sl.SQLStore.WithTransactionalDbSession(ctx, func(dbSession *sqlstore.DBSession) error { + lockRows := []*serverLock{} + err := dbSession.Where("operation_uid = ?", actionName).Find(&lockRows) + if err != nil { + return err + } + + if len(lockRows) > 0 { + result = lockRows[0] + return nil + } + + lockRow := &serverLock{ + OperationUid: actionName, + LastExecution: 0, + } + + _, err = dbSession.Insert(lockRow) + if err != nil { + return err + } + + result = lockRow + + return nil + }) + + return result, err +} diff --git a/pkg/infra/serverlock/serverlock_integration_test.go b/pkg/infra/serverlock/serverlock_integration_test.go new file mode 100644 index 00000000000..0065651b8d7 --- /dev/null +++ b/pkg/infra/serverlock/serverlock_integration_test.go @@ -0,0 +1,75 @@ +// +build integration + +package serverlock + +import ( + "context" + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestServerLok(t *testing.T) { + sl := createTestableServerLock(t) + + Convey("Server lock integration test", t, func() { + + Convey("Check that we can call OncePerServerGroup multiple times without executing callback", func() { + counter := 0 + var err error + + //this time `fn` should be executed + err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) + So(err, ShouldBeNil) + + //this should not execute `fn` + err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) + So(err, ShouldBeNil) + + //this should not execute `fn` + err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) + So(err, ShouldBeNil) + + // wg := sync.WaitGroup{} + // for i := 0; i < 3; i++ { + // wg.Add(1) + // go func(index int) { + // defer wg.Done() + // //sl := createTestableServerLock(t) + // //<-time.After(time.Second) + + // j := 0 + // for { + // select { + // case <-time.Tick(time.Second): + // fmt.Printf("running worker %d loop %d\n", index, j) + // err := sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*2, func() { + // counter++ + // }) + + // if err != nil { + // t.Errorf("expected. err: %v", err) + // } + + // j++ + // if j > 3 { + // return + // } + // } + // } + // }(i) + // } + + // wg.Wait() + + // wait 5 second. + <-time.After(time.Second * 10) + + // now `fn` should be executed again + err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) + So(err, ShouldBeNil) + So(counter, ShouldEqual, 2) + }) + }) +} diff --git a/pkg/infra/serverlock/serverlock_test.go b/pkg/infra/serverlock/serverlock_test.go new file mode 100644 index 00000000000..e5166144e0b --- /dev/null +++ b/pkg/infra/serverlock/serverlock_test.go @@ -0,0 +1,57 @@ +package serverlock + +import ( + "context" + "testing" + "time" + + "github.com/grafana/grafana/pkg/log" + + "github.com/grafana/grafana/pkg/services/sqlstore" + . "github.com/smartystreets/goconvey/convey" +) + +func createTestableServerLock(t *testing.T) *ServerLockService { + t.Helper() + + sqlstore := sqlstore.InitTestDB(t) + + return &ServerLockService{ + SQLStore: sqlstore, + log: log.New("test-logger"), + } +} + +func TestServerLock(t *testing.T) { + Convey("Server lock", t, func() { + sl := createTestableServerLock(t) + operationUID := "test-operation" + + first, err := sl.getOrCreate(context.Background(), operationUID) + So(err, ShouldBeNil) + + lastExecution := first.LastExecution + Convey("trying to create three new row locks", func() { + for i := 0; i < 3; i++ { + first, err = sl.getOrCreate(context.Background(), operationUID) + So(err, ShouldBeNil) + So(first.OperationUid, ShouldEqual, operationUID) + So(first.Id, ShouldEqual, 1) + } + + Convey("Should not create new since lock already exist", func() { + So(lastExecution, ShouldEqual, first.LastExecution) + }) + }) + + Convey("Should be able to create lock on first row", func() { + gotLock, err := sl.acquireLock(context.Background(), first, time.Second*1) + So(err, ShouldBeNil) + So(gotLock, ShouldBeTrue) + + gotLock, err = sl.acquireLock(context.Background(), first, time.Second*1) + So(err, ShouldBeNil) + So(gotLock, ShouldBeFalse) + }) + }) +} From 823bba8d98eab3c0c3d082edf18046bd14b3203f Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Dec 2018 15:10:02 +0100 Subject: [PATCH 3/7] change from db_text to nvarchar --- pkg/infra/serverlock/migrations.go | 2 +- pkg/infra/serverlock/serverlock.go | 1 + pkg/services/cleanup/cleanup.go | 12 +++++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/infra/serverlock/migrations.go b/pkg/infra/serverlock/migrations.go index 4b9f95053a2..6498b3de550 100644 --- a/pkg/infra/serverlock/migrations.go +++ b/pkg/infra/serverlock/migrations.go @@ -8,7 +8,7 @@ func (sl *ServerLockService) AddMigration(mg *migrator.Migrator) { Name: "server_lock", Columns: []*migrator.Column{ {Name: "id", Type: migrator.DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, - {Name: "operation_uid", Type: migrator.DB_Text}, + {Name: "operation_uid", Type: migrator.DB_NVarchar, Length: 100}, {Name: "version", Type: migrator.DB_BigInt}, {Name: "last_execution", Type: migrator.DB_BigInt, Nullable: false}, }, diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go index 08aededeba9..7a92ef36c73 100644 --- a/pkg/infra/serverlock/serverlock.go +++ b/pkg/infra/serverlock/serverlock.go @@ -21,6 +21,7 @@ type ServerLockService struct { // Init this service func (sl *ServerLockService) Init() error { + sl.log = log.New("infra.lockservice") return nil } diff --git a/pkg/services/cleanup/cleanup.go b/pkg/services/cleanup/cleanup.go index c15ae8ef36c..9338e3afab3 100644 --- a/pkg/services/cleanup/cleanup.go +++ b/pkg/services/cleanup/cleanup.go @@ -7,6 +7,8 @@ import ( "path" "time" + "github.com/grafana/grafana/pkg/infra/serverlock" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" @@ -15,8 +17,9 @@ import ( ) type CleanUpService struct { - log log.Logger - Cfg *setting.Cfg `inject:""` + log log.Logger + Cfg *setting.Cfg `inject:""` + ServerLockService *serverlock.ServerLockService `inject:""` } func init() { @@ -38,7 +41,10 @@ func (srv *CleanUpService) Run(ctx context.Context) error { srv.cleanUpTmpFiles() srv.deleteExpiredSnapshots() srv.deleteExpiredDashboardVersions() - srv.deleteOldLoginAttempts() + srv.ServerLockService.OncePerServerGroup(ctx, "delete old login attempts", time.Minute*10, func() { + srv.deleteOldLoginAttempts() + }) + case <-ctx.Done(): return ctx.Err() } From c565b018c51548d48d28713d587b2c46c76d7b7d Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 12 Dec 2018 07:30:08 +0100 Subject: [PATCH 4/7] clean up integration tests --- pkg/infra/serverlock/serverlock.go | 11 ++- .../serverlock/serverlock_integration_test.go | 73 +++++-------------- pkg/infra/serverlock/serverlock_test.go | 6 +- 3 files changed, 28 insertions(+), 62 deletions(-) diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go index 7a92ef36c73..0cdb94ca627 100644 --- a/pkg/infra/serverlock/serverlock.go +++ b/pkg/infra/serverlock/serverlock.go @@ -28,20 +28,23 @@ func (sl *ServerLockService) Init() error { // OncePerServerGroup try to create a lock for this server and only executes the // `fn` function when successful. This should not be used at low internal. But services // that needs to be run once every ex 10m. -func (sl *ServerLockService) OncePerServerGroup(ctx context.Context, actionName string, maxEvery time.Duration, fn func()) error { +func (sl *ServerLockService) OncePerServerGroup(ctx context.Context, actionName string, maxInterval time.Duration, fn func()) error { + // gets or creates a lockable row rowLock, err := sl.getOrCreate(ctx, actionName) if err != nil { return err } + // avoid execution if last lock happened less than `matInterval` ago if rowLock.LastExecution != 0 { lastExeuctionTime := time.Unix(rowLock.LastExecution, 0) - if lastExeuctionTime.Unix() > time.Now().Add(-maxEvery).Unix() { + if lastExeuctionTime.Unix() > time.Now().Add(-maxInterval).Unix() { return nil } } - acquiredLock, err := sl.acquireLock(ctx, rowLock, maxEvery) + // try to get lock based on rowLow version + acquiredLock, err := sl.acquireLock(ctx, rowLock) if err != nil { return err } @@ -53,7 +56,7 @@ func (sl *ServerLockService) OncePerServerGroup(ctx context.Context, actionName return nil } -func (sl *ServerLockService) acquireLock(ctx context.Context, serverLock *serverLock, maxEvery time.Duration) (bool, error) { +func (sl *ServerLockService) acquireLock(ctx context.Context, serverLock *serverLock) (bool, error) { var result bool err := sl.SQLStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { diff --git a/pkg/infra/serverlock/serverlock_integration_test.go b/pkg/infra/serverlock/serverlock_integration_test.go index 0065651b8d7..335f540b2e3 100644 --- a/pkg/infra/serverlock/serverlock_integration_test.go +++ b/pkg/infra/serverlock/serverlock_integration_test.go @@ -13,63 +13,28 @@ import ( func TestServerLok(t *testing.T) { sl := createTestableServerLock(t) - Convey("Server lock integration test", t, func() { + Convey("Server lock integration tests", t, func() { + counter := 0 + var err error + incCounter := func() { counter++ } + atInterval := time.Second * 1 + ctx := context.Background() - Convey("Check that we can call OncePerServerGroup multiple times without executing callback", func() { - counter := 0 - var err error + //this time `fn` should be executed + So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) - //this time `fn` should be executed - err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) - So(err, ShouldBeNil) + //this should not execute `fn` + So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) - //this should not execute `fn` - err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) - So(err, ShouldBeNil) + // wait 5 second. + <-time.After(atInterval * 2) - //this should not execute `fn` - err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) - So(err, ShouldBeNil) - - // wg := sync.WaitGroup{} - // for i := 0; i < 3; i++ { - // wg.Add(1) - // go func(index int) { - // defer wg.Done() - // //sl := createTestableServerLock(t) - // //<-time.After(time.Second) - - // j := 0 - // for { - // select { - // case <-time.Tick(time.Second): - // fmt.Printf("running worker %d loop %d\n", index, j) - // err := sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*2, func() { - // counter++ - // }) - - // if err != nil { - // t.Errorf("expected. err: %v", err) - // } - - // j++ - // if j > 3 { - // return - // } - // } - // } - // }(i) - // } - - // wg.Wait() - - // wait 5 second. - <-time.After(time.Second * 10) - - // now `fn` should be executed again - err = sl.OncePerServerGroup(context.Background(), "test-operation", time.Second*5, func() { counter++ }) - So(err, ShouldBeNil) - So(counter, ShouldEqual, 2) - }) + // now `fn` should be executed again + err = sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter) + So(err, ShouldBeNil) + So(counter, ShouldEqual, 2) }) } diff --git a/pkg/infra/serverlock/serverlock_test.go b/pkg/infra/serverlock/serverlock_test.go index e5166144e0b..ccd1c252090 100644 --- a/pkg/infra/serverlock/serverlock_test.go +++ b/pkg/infra/serverlock/serverlock_test.go @@ -3,10 +3,8 @@ package serverlock import ( "context" "testing" - "time" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/services/sqlstore" . "github.com/smartystreets/goconvey/convey" ) @@ -45,11 +43,11 @@ func TestServerLock(t *testing.T) { }) Convey("Should be able to create lock on first row", func() { - gotLock, err := sl.acquireLock(context.Background(), first, time.Second*1) + gotLock, err := sl.acquireLock(context.Background(), first) So(err, ShouldBeNil) So(gotLock, ShouldBeTrue) - gotLock, err = sl.acquireLock(context.Background(), first, time.Second*1) + gotLock, err = sl.acquireLock(context.Background(), first) So(err, ShouldBeNil) So(gotLock, ShouldBeFalse) }) From 11cde7ed714414bed0cfe9b082352ce599bed47f Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 12 Dec 2018 13:44:06 +0100 Subject: [PATCH 5/7] renames main lock function --- pkg/infra/serverlock/serverlock.go | 9 ++++++--- pkg/infra/serverlock/serverlock_integration_test.go | 12 ++++++------ pkg/services/cleanup/cleanup.go | 5 ++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go index 0cdb94ca627..77d2d7173fc 100644 --- a/pkg/infra/serverlock/serverlock.go +++ b/pkg/infra/serverlock/serverlock.go @@ -13,7 +13,10 @@ func init() { registry.RegisterService(&ServerLockService{}) } -// ServerLockService allows servers in HA mode to execute function once over in the group +// DistributedLockService + +// ServerLockService allows servers in HA mode to claim a lock +// and execute an function if the server was granted the lock type ServerLockService struct { SQLStore *sqlstore.SqlStore `inject:""` log log.Logger @@ -25,10 +28,10 @@ func (sl *ServerLockService) Init() error { return nil } -// OncePerServerGroup try to create a lock for this server and only executes the +// LockAndExecute try to create a lock for this server and only executes the // `fn` function when successful. This should not be used at low internal. But services // that needs to be run once every ex 10m. -func (sl *ServerLockService) OncePerServerGroup(ctx context.Context, actionName string, maxInterval time.Duration, fn func()) error { +func (sl *ServerLockService) LockAndExecute(ctx context.Context, actionName string, maxInterval time.Duration, fn func()) error { // gets or creates a lockable row rowLock, err := sl.getOrCreate(ctx, actionName) if err != nil { diff --git a/pkg/infra/serverlock/serverlock_integration_test.go b/pkg/infra/serverlock/serverlock_integration_test.go index 335f540b2e3..8bcd9c2ca25 100644 --- a/pkg/infra/serverlock/serverlock_integration_test.go +++ b/pkg/infra/serverlock/serverlock_integration_test.go @@ -21,19 +21,19 @@ func TestServerLok(t *testing.T) { ctx := context.Background() //this time `fn` should be executed - So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) //this should not execute `fn` - So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) - So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) - So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) - So(sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) + So(sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter), ShouldBeNil) // wait 5 second. <-time.After(atInterval * 2) // now `fn` should be executed again - err = sl.OncePerServerGroup(ctx, "test-operation", atInterval, incCounter) + err = sl.LockAndExecute(ctx, "test-operation", atInterval, incCounter) So(err, ShouldBeNil) So(counter, ShouldEqual, 2) }) diff --git a/pkg/services/cleanup/cleanup.go b/pkg/services/cleanup/cleanup.go index 9338e3afab3..63d829bccec 100644 --- a/pkg/services/cleanup/cleanup.go +++ b/pkg/services/cleanup/cleanup.go @@ -7,9 +7,8 @@ import ( "path" "time" - "github.com/grafana/grafana/pkg/infra/serverlock" - "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/infra/serverlock" "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/registry" @@ -41,7 +40,7 @@ func (srv *CleanUpService) Run(ctx context.Context) error { srv.cleanUpTmpFiles() srv.deleteExpiredSnapshots() srv.deleteExpiredDashboardVersions() - srv.ServerLockService.OncePerServerGroup(ctx, "delete old login attempts", time.Minute*10, func() { + srv.ServerLockService.LockAndExecute(ctx, "delete old login attempts", time.Minute*10, func() { srv.deleteOldLoginAttempts() }) From dbcc2e868dcfd781fd0d2718c1d455c63e1bd6ff Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 12 Dec 2018 13:47:21 +0100 Subject: [PATCH 6/7] adds integration tests to ci build --- pkg/infra/serverlock/serverlock.go | 2 -- scripts/circle-test-backend.sh | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go index 77d2d7173fc..84dcaf25e93 100644 --- a/pkg/infra/serverlock/serverlock.go +++ b/pkg/infra/serverlock/serverlock.go @@ -13,8 +13,6 @@ func init() { registry.RegisterService(&ServerLockService{}) } -// DistributedLockService - // ServerLockService allows servers in HA mode to claim a lock // and execute an function if the server was granted the lock type ServerLockService struct { diff --git a/scripts/circle-test-backend.sh b/scripts/circle-test-backend.sh index d25506b9bc7..7f1e67dd5bb 100755 --- a/scripts/circle-test-backend.sh +++ b/scripts/circle-test-backend.sh @@ -19,5 +19,5 @@ exit_if_fail time go install ./pkg/cmd/grafana-server echo "running go test" set -e time for d in $(go list ./pkg/...); do - exit_if_fail go test -covermode=atomic $d + exit_if_fail go test -tags=integration -covermode=atomic $d done From 7aa84aeb61c2838aad358364b8387209f9424019 Mon Sep 17 00:00:00 2001 From: bergquist Date: Thu, 13 Dec 2018 09:52:13 +0100 Subject: [PATCH 7/7] moves migrations to /sqlstore/migrations --- pkg/infra/serverlock/serverlock.go | 2 +- pkg/services/sqlstore/migrations/migrations.go | 1 + .../sqlstore/migrations/serverlock_migrations.go} | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename pkg/{infra/serverlock/migrations.go => services/sqlstore/migrations/serverlock_migrations.go} (83%) diff --git a/pkg/infra/serverlock/serverlock.go b/pkg/infra/serverlock/serverlock.go index 84dcaf25e93..824fa0484b2 100644 --- a/pkg/infra/serverlock/serverlock.go +++ b/pkg/infra/serverlock/serverlock.go @@ -36,7 +36,7 @@ func (sl *ServerLockService) LockAndExecute(ctx context.Context, actionName stri return err } - // avoid execution if last lock happened less than `matInterval` ago + // avoid execution if last lock happened less than `maxInterval` ago if rowLock.LastExecution != 0 { lastExeuctionTime := time.Unix(rowLock.LastExecution, 0) if lastExeuctionTime.Unix() > time.Now().Add(-maxInterval).Unix() { diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index 58ac6256f41..36cd8e5ed62 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -31,6 +31,7 @@ func AddMigrations(mg *Migrator) { addTagMigration(mg) addLoginAttemptMigrations(mg) addUserAuthMigrations(mg) + addServerlockMigrations(mg) } func addMigrationLogMigrations(mg *Migrator) { diff --git a/pkg/infra/serverlock/migrations.go b/pkg/services/sqlstore/migrations/serverlock_migrations.go similarity index 83% rename from pkg/infra/serverlock/migrations.go rename to pkg/services/sqlstore/migrations/serverlock_migrations.go index 6498b3de550..bc817a90665 100644 --- a/pkg/infra/serverlock/migrations.go +++ b/pkg/services/sqlstore/migrations/serverlock_migrations.go @@ -1,9 +1,8 @@ -package serverlock +package migrations import "github.com/grafana/grafana/pkg/services/sqlstore/migrator" -// AddMigration create database migrations for server lock -func (sl *ServerLockService) AddMigration(mg *migrator.Migrator) { +func addServerlockMigrations(mg *migrator.Migrator) { serverLock := migrator.Table{ Name: "server_lock", Columns: []*migrator.Column{