From ebf3a8d205ebd3633dd447d2bc66ec50eaaf9200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Sencer=20=C3=96zcan?= <32759850+mustafasencer@users.noreply.github.com> Date: Fri, 25 Apr 2025 13:43:35 +0200 Subject: [PATCH] fix: make data syncer run configurable on mode (2->3) change (#104401) --- go.mod | 2 +- pkg/apiserver/rest/dualwriter.go | 4 ++++ pkg/apiserver/rest/dualwriter_syncer.go | 1 + pkg/apiserver/rest/dualwriter_test.go | 9 +++++++++ pkg/services/apiserver/builder/helper.go | 3 +++ pkg/setting/setting.go | 1 + pkg/setting/setting_unified_storage.go | 4 ++++ 7 files changed, 23 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 054f66e485a..68709329747 100644 --- a/go.mod +++ b/go.mod @@ -455,7 +455,7 @@ require ( github.com/mithrandie/ternary v1.1.1 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect diff --git a/pkg/apiserver/rest/dualwriter.go b/pkg/apiserver/rest/dualwriter.go index 6cd37cb8740..3b4196935de 100644 --- a/pkg/apiserver/rest/dualwriter.go +++ b/pkg/apiserver/rest/dualwriter.go @@ -164,6 +164,10 @@ func SetDualWritingMode( return Mode0, errDualWriterSetCurrentMode } case cfg.Mode >= Mode3 && currentMode < Mode3: + if cfg.SkipDataSync { + return currentMode, nil + } + // Transitioning to Mode3 or higher requires data synchronization. cfgModeTmp := cfg.Mode // Before running the sync, set the syncer config to the current mode, as we have to run the syncer diff --git a/pkg/apiserver/rest/dualwriter_syncer.go b/pkg/apiserver/rest/dualwriter_syncer.go index b15cf5376ac..fb064370fc6 100644 --- a/pkg/apiserver/rest/dualwriter_syncer.go +++ b/pkg/apiserver/rest/dualwriter_syncer.go @@ -36,6 +36,7 @@ type SyncerConfig struct { LegacyStorage Storage Storage Storage ServerLockService ServerLockService + SkipDataSync bool DataSyncerInterval time.Duration DataSyncerRecordsLimit int diff --git a/pkg/apiserver/rest/dualwriter_test.go b/pkg/apiserver/rest/dualwriter_test.go index 3faf131424e..fa6fa7e5f4a 100644 --- a/pkg/apiserver/rest/dualwriter_test.go +++ b/pkg/apiserver/rest/dualwriter_test.go @@ -20,6 +20,7 @@ func TestSetDualWritingMode(t *testing.T) { kvStore *fakeNamespacedKV desiredMode DualWriterMode expectedMode DualWriterMode + skipDataSync bool serverLockError error } tests := @@ -61,6 +62,13 @@ func TestSetDualWritingMode(t *testing.T) { expectedMode: Mode2, serverLockError: fmt.Errorf("lock already exists"), }, + { + name: "should keep mode2 when trying to go from mode2 to mode3 and migration is disabled", + kvStore: &fakeNamespacedKV{data: map[string]string{"playlist.grafana.app/playlists": "2"}, namespace: "storage.dualwriting"}, + desiredMode: Mode3, + expectedMode: Mode2, + skipDataSync: true, + }, } for _, tt := range tests { @@ -86,6 +94,7 @@ func TestSetDualWritingMode(t *testing.T) { Storage: us, Kind: "playlist.grafana.app/playlists", Mode: tt.desiredMode, + SkipDataSync: tt.skipDataSync, ServerLockService: serverLockSvc, RequestInfo: &request.RequestInfo{}, Reg: p, diff --git a/pkg/services/apiserver/builder/helper.go b/pkg/services/apiserver/builder/helper.go index 49d399e3914..bfd9040e9c2 100644 --- a/pkg/services/apiserver/builder/helper.go +++ b/pkg/services/apiserver/builder/helper.go @@ -315,6 +315,7 @@ func InstallAPIs( var ( dualWriterPeriodicDataSyncJobEnabled bool + dualWriterMigrationDataSyncDisabled bool dataSyncerInterval = time.Hour dataSyncerRecordsLimit = 1000 ) @@ -323,6 +324,7 @@ func InstallAPIs( if resourceExists { mode = resourceConfig.DualWriterMode dualWriterPeriodicDataSyncJobEnabled = resourceConfig.DualWriterPeriodicDataSyncJobEnabled + dualWriterMigrationDataSyncDisabled = resourceConfig.DualWriterMigrationDataSyncDisabled dataSyncerInterval = resourceConfig.DataSyncerInterval dataSyncerRecordsLimit = resourceConfig.DataSyncerRecordsLimit } @@ -343,6 +345,7 @@ func InstallAPIs( Kind: key, RequestInfo: requestInfo, Mode: mode, + SkipDataSync: dualWriterMigrationDataSyncDisabled, LegacyStorage: legacy, Storage: storage, ServerLockService: serverLock, diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 4a77bfdbf04..f0cd2815fd6 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -556,6 +556,7 @@ type Cfg struct { type UnifiedStorageConfig struct { DualWriterMode rest.DualWriterMode DualWriterPeriodicDataSyncJobEnabled bool + DualWriterMigrationDataSyncDisabled bool // DataSyncerInterval defines how often the data syncer should run for a resource on the grafana instance. DataSyncerInterval time.Duration // DataSyncerRecordsLimit defines how many records will be processed at max during a sync invocation. diff --git a/pkg/setting/setting_unified_storage.go b/pkg/setting/setting_unified_storage.go index 5bc9fcf2ec1..c805f7a330f 100644 --- a/pkg/setting/setting_unified_storage.go +++ b/pkg/setting/setting_unified_storage.go @@ -30,6 +30,9 @@ func (cfg *Cfg) setUnifiedStorageConfig() { // parse dualWriter periodic data syncer config dualWriterPeriodicDataSyncJobEnabled := section.Key("dualWriterPeriodicDataSyncJobEnabled").MustBool(false) + // parse dualWriter migration data sync disabled from resource section + dualWriterMigrationDataSyncDisabled := section.Key("dualWriterMigrationDataSyncDisabled").MustBool(false) + // parse dataSyncerRecordsLimit from resource section dataSyncerRecordsLimit := section.Key("dataSyncerRecordsLimit").MustInt(1000) @@ -39,6 +42,7 @@ func (cfg *Cfg) setUnifiedStorageConfig() { storageConfig[resourceName] = UnifiedStorageConfig{ DualWriterMode: rest.DualWriterMode(dualWriterMode), DualWriterPeriodicDataSyncJobEnabled: dualWriterPeriodicDataSyncJobEnabled, + DualWriterMigrationDataSyncDisabled: dualWriterMigrationDataSyncDisabled, DataSyncerRecordsLimit: dataSyncerRecordsLimit, DataSyncerInterval: dataSyncerInterval, }