From b0b22c397fc4cbda2fb5536bf439a5bd359e3d64 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Tue, 30 Sep 2025 18:31:18 -0300 Subject: [PATCH 01/39] added logger mock --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index db1dfbcc..7ffe3ef2 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.18 require ( github.com/bits-and-blooms/bloom/v3 v3.3.1 - github.com/splitio/go-toolkit/v5 v5.4.0 - github.com/stretchr/testify v1.9.0 + github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99 + github.com/stretchr/testify v1.11.1 golang.org/x/sync v0.3.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 06b033a3..b5c1d4eb 100644 --- a/go.sum +++ b/go.sum @@ -19,12 +19,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/splitio/go-toolkit/v5 v5.4.0 h1:g5WFpRhQomnXCmvfsNOWV4s5AuUrWIZ+amM68G8NBKM= -github.com/splitio/go-toolkit/v5 v5.4.0/go.mod h1:xYhUvV1gga9/1029Wbp5pjnR6Cy8nvBpjw99wAbsMko= +github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99 h1:rQo355F9JbdyTMz2X5MU+FeRvkT6rvD1n+GnXdJr33A= +github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= From a139785e64956d2527a041becbb3b185cb8cb753 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 2 Oct 2025 14:18:33 -0300 Subject: [PATCH 02/39] Added ReplacedAll method in split storage --- storage/inmemory/mutexmap/splits.go | 19 ++++++ storage/inmemory/mutexmap/splits_test.go | 74 ++++++++++++++++++++++++ storage/interfaces.go | 2 + storage/mocks/split.go | 5 ++ storage/redis/splits.go | 4 ++ 5 files changed, 104 insertions(+) diff --git a/storage/inmemory/mutexmap/splits.go b/storage/inmemory/mutexmap/splits.go index b080e611..5de3f907 100644 --- a/storage/inmemory/mutexmap/splits.go +++ b/storage/inmemory/mutexmap/splits.go @@ -150,6 +150,10 @@ func (m *MMSplitStorage) addToFlagSets(name string, sets []string) { func (m *MMSplitStorage) Update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, till int64) { m.mutex.Lock() defer m.mutex.Unlock() + m.update(toAdd, toRemove, till) +} + +func (m *MMSplitStorage) update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, till int64) { for _, split := range toAdd { existing, thisIsAnUpdate := m.data[split.Name] if thisIsAnUpdate { @@ -266,5 +270,20 @@ func (m *MMSplitStorage) GetNamesByFlagSets(sets []string) map[string][]string { return toReturn } +func (m *MMSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { + // Get all current splits under read lock + m.mutex.RLock() + toRemove := make([]dtos.SplitDTO, 0) + for _, split := range m.data { + toRemove = append(toRemove, split) + } + m.mutex.RUnlock() + + // Now acquire write lock for the update + m.mutex.Lock() + defer m.mutex.Unlock() + m.update(toAdd, toRemove, changeNumber) +} + var _ storage.SplitStorageConsumer = (*MMSplitStorage)(nil) var _ storage.SplitStorageProducer = (*MMSplitStorage)(nil) diff --git a/storage/inmemory/mutexmap/splits_test.go b/storage/inmemory/mutexmap/splits_test.go index 1abc281a..41b76d3c 100644 --- a/storage/inmemory/mutexmap/splits_test.go +++ b/storage/inmemory/mutexmap/splits_test.go @@ -328,6 +328,80 @@ func TestGetNamesByFlagSets(t *testing.T) { } } +func TestReplaceAll(t *testing.T) { + // Initialize storage with some initial splits + splitStorage := NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) + initialSplits := []dtos.SplitDTO{ + {Name: "split1", TrafficTypeName: "tt1", Sets: []string{"set1"}, ChangeNumber: 1}, + {Name: "split2", TrafficTypeName: "tt2", Sets: []string{"set2"}, ChangeNumber: 2}, + } + splitStorage.Update(initialSplits, nil, 100) + + // Verify initial state + if len(splitStorage.All()) != 2 { + t.Error("Should have 2 initial splits") + } + if !splitStorage.TrafficTypeExists("tt1") || !splitStorage.TrafficTypeExists("tt2") { + t.Error("Initial traffic types should exist") + } + + // Prepare new splits for replacement + newSplits := []dtos.SplitDTO{ + {Name: "split3", TrafficTypeName: "tt3", Sets: []string{"set3"}, ChangeNumber: 3}, + {Name: "split4", TrafficTypeName: "tt4", Sets: []string{"set4"}, ChangeNumber: 4}, + {Name: "split5", TrafficTypeName: "tt4", Sets: []string{"set5"}, ChangeNumber: 5}, + } + + // Replace all splits + splitStorage.ReplaceAll(newSplits, 200) + + // Verify the replacement + allSplits := splitStorage.All() + if len(allSplits) != 3 { + t.Error("Should have 3 splits after replacement") + } + + // Verify old splits are removed + if splitStorage.Split("split1") != nil || splitStorage.Split("split2") != nil { + t.Error("Old splits should have been removed") + } + + // Verify new splits are present + for _, expectedSplit := range newSplits { + split := splitStorage.Split(expectedSplit.Name) + if split == nil { + t.Errorf("Split %s should exist", expectedSplit.Name) + } + if split.TrafficTypeName != expectedSplit.TrafficTypeName { + t.Errorf("Split %s should have traffic type %s", expectedSplit.Name, expectedSplit.TrafficTypeName) + } + } + + // Verify old traffic types are removed and new ones exist + if splitStorage.TrafficTypeExists("tt1") || splitStorage.TrafficTypeExists("tt2") { + t.Error("Old traffic types should not exist") + } + if !splitStorage.TrafficTypeExists("tt3") || !splitStorage.TrafficTypeExists("tt4") { + t.Error("New traffic types should exist") + } + + // Verify change number is updated + cn, _ := splitStorage.ChangeNumber() + if cn != 200 { + t.Error("Change number should be updated to 200") + } + + // Test replacing with empty list + splitStorage.ReplaceAll([]dtos.SplitDTO{}, 300) + if len(splitStorage.All()) != 0 { + t.Error("All splits should be removed when replacing with empty list") + } + cn, _ = splitStorage.ChangeNumber() + if cn != 300 { + t.Error("Change number should be updated to 300") + } +} + func TestLargeSegmentNames(t *testing.T) { splitStorage := NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) diff --git a/storage/interfaces.go b/storage/interfaces.go index 443b1ef2..8cb54e35 100644 --- a/storage/interfaces.go +++ b/storage/interfaces.go @@ -13,6 +13,7 @@ type SplitStorageProducer interface { Update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) KillLocally(splitName string, defaultTreatment string, changeNumber int64) SetChangeNumber(changeNumber int64) error + ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) } // SplitStorageConsumer should be implemented by structs that offer reading splits from storage @@ -211,6 +212,7 @@ type SplitStorage interface { TrafficTypeExists(trafficType string) bool GetNamesByFlagSets(sets []string) map[string][]string GetAllFlagSetNames() []string + ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) } // SegmentStorage wraps consumer and producer interfaces diff --git a/storage/mocks/split.go b/storage/mocks/split.go index cdb03171..124f5774 100644 --- a/storage/mocks/split.go +++ b/storage/mocks/split.go @@ -21,6 +21,7 @@ type MockSplitStorage struct { TrafficTypeExistsCall func(trafficType string) bool GetNamesByFlagSetsCall func(sets []string) map[string][]string GetAllFlagSetNamesCall func() []string + ReplaceAllCall func(toAdd []dtos.SplitDTO, changeNumber int64) } // All mock @@ -91,3 +92,7 @@ func (m MockSplitStorage) GetNamesByFlagSets(sets []string) map[string][]string func (m MockSplitStorage) GetAllFlagSetNames() []string { return m.GetAllFlagSetNamesCall() } + +func (m MockSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { + m.ReplaceAllCall(toAdd, changeNumber) +} diff --git a/storage/redis/splits.go b/storage/redis/splits.go index 9dd6dbc7..8688ee0d 100644 --- a/storage/redis/splits.go +++ b/storage/redis/splits.go @@ -493,4 +493,8 @@ func (r *SplitStorage) splitKeysClusterMode() ([]string, error) { return result, nil } +func (r *SplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { + //to do +} + var _ storage.SplitStorage = (*SplitStorage)(nil) From 1bb0526ed14ffb5e1e2304e7f0447d65c875a9d2 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 2 Oct 2025 14:39:03 -0300 Subject: [PATCH 03/39] Added asserts in test cases --- storage/inmemory/mutexmap/splits_test.go | 52 ++++++++---------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/storage/inmemory/mutexmap/splits_test.go b/storage/inmemory/mutexmap/splits_test.go index 41b76d3c..3430d700 100644 --- a/storage/inmemory/mutexmap/splits_test.go +++ b/storage/inmemory/mutexmap/splits_test.go @@ -7,6 +7,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-toolkit/v5/datastructures/set" + "github.com/stretchr/testify/assert" ) func TestMMSplitStorage(t *testing.T) { @@ -338,12 +339,8 @@ func TestReplaceAll(t *testing.T) { splitStorage.Update(initialSplits, nil, 100) // Verify initial state - if len(splitStorage.All()) != 2 { - t.Error("Should have 2 initial splits") - } - if !splitStorage.TrafficTypeExists("tt1") || !splitStorage.TrafficTypeExists("tt2") { - t.Error("Initial traffic types should exist") - } + assert.Equal(t, 2, len(splitStorage.All()), "Should have 2 initial splits") + assert.False(t, !splitStorage.TrafficTypeExists("tt1") || !splitStorage.TrafficTypeExists("tt2"), "Initial traffic types should exist") // Prepare new splits for replacement newSplits := []dtos.SplitDTO{ @@ -357,49 +354,34 @@ func TestReplaceAll(t *testing.T) { // Verify the replacement allSplits := splitStorage.All() - if len(allSplits) != 3 { - t.Error("Should have 3 splits after replacement") - } + assert.Equal(t, 3, len(allSplits), "Should have 3 splits after replacement") // Verify old splits are removed - if splitStorage.Split("split1") != nil || splitStorage.Split("split2") != nil { - t.Error("Old splits should have been removed") - } + assert.False(t, splitStorage.Split("split1") != nil || splitStorage.Split("split2") != nil, "Old splits should have been removed") // Verify new splits are present + assert.ElementsMatch(t, newSplits, allSplits, "All splits should match the new splits") for _, expectedSplit := range newSplits { split := splitStorage.Split(expectedSplit.Name) - if split == nil { - t.Errorf("Split %s should exist", expectedSplit.Name) - } - if split.TrafficTypeName != expectedSplit.TrafficTypeName { - t.Errorf("Split %s should have traffic type %s", expectedSplit.Name, expectedSplit.TrafficTypeName) - } + assert.NotNil(t, split, "Split %s should exist", expectedSplit.Name) + assert.Equal(t, expectedSplit.TrafficTypeName, split.TrafficTypeName, "Split %s should have traffic type %s", expectedSplit.Name, expectedSplit.TrafficTypeName) } // Verify old traffic types are removed and new ones exist - if splitStorage.TrafficTypeExists("tt1") || splitStorage.TrafficTypeExists("tt2") { - t.Error("Old traffic types should not exist") - } - if !splitStorage.TrafficTypeExists("tt3") || !splitStorage.TrafficTypeExists("tt4") { - t.Error("New traffic types should exist") - } + assert.False(t, splitStorage.TrafficTypeExists("tt1") || splitStorage.TrafficTypeExists("tt2"), "Old traffic types should not exist") + assert.True(t, splitStorage.TrafficTypeExists("tt3") && splitStorage.TrafficTypeExists("tt4"), "New traffic types should exist") // Verify change number is updated - cn, _ := splitStorage.ChangeNumber() - if cn != 200 { - t.Error("Change number should be updated to 200") - } + cn, err := splitStorage.ChangeNumber() + assert.NoError(t, err) + assert.Equal(t, int64(200), cn, "Change number should be updated to 200") // Test replacing with empty list splitStorage.ReplaceAll([]dtos.SplitDTO{}, 300) - if len(splitStorage.All()) != 0 { - t.Error("All splits should be removed when replacing with empty list") - } - cn, _ = splitStorage.ChangeNumber() - if cn != 300 { - t.Error("Change number should be updated to 300") - } + assert.Empty(t, splitStorage.All(), "All splits should be removed when replacing with empty list") + cn, err = splitStorage.ChangeNumber() + assert.NoError(t, err) + assert.Equal(t, int64(300), cn, "Change number should be updated to 300") } func TestLargeSegmentNames(t *testing.T) { From 2579b0cd4562ac87c3052479a19a19175ee47189 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 3 Oct 2025 13:59:35 -0300 Subject: [PATCH 04/39] updated tests --- healthcheck/mocks/applicationmonitor.go | 23 + service/api/specs/splitversionfilter_test.go | 2 +- service/mocks/split.go | 14 +- storage/mocks/event.go | 2 +- storage/mocks/impression.go | 2 +- storage/mocks/rulebasedsegment.go | 8 +- storage/mocks/split.go | 110 ++ synchronizer/local_test.go | 172 +-- synchronizer/synchronizer_test.go | 607 +++----- synchronizer/worker/split/split.go | 2 +- synchronizer/worker/split/split_test.go | 1325 ++++++------------ tasks/largesegmentsync_test.go | 45 +- tasks/splitsync_test.go | 88 +- 13 files changed, 878 insertions(+), 1522 deletions(-) diff --git a/healthcheck/mocks/applicationmonitor.go b/healthcheck/mocks/applicationmonitor.go index ba15ee67..a0ec38a4 100644 --- a/healthcheck/mocks/applicationmonitor.go +++ b/healthcheck/mocks/applicationmonitor.go @@ -1,5 +1,11 @@ package mocks +import ( + "github.com/splitio/go-split-commons/v7/healthcheck/application" + + "github.com/stretchr/testify/mock" +) + // MockApplicationMonitor mocked implementation of application monitor type MockApplicationMonitor struct { NotifyEventCall func(counterType int) @@ -15,3 +21,20 @@ func (m MockApplicationMonitor) NotifyEvent(counterType int) { func (m MockApplicationMonitor) Reset(counterType int, value int) { m.ResetCall(counterType, value) } + +// ApplicationMonitorMock is a mock for the ApplicationMonitor interface +type ApplicationMonitorMock struct { + mock.Mock +} + +// NotifyEvent mock +func (m *ApplicationMonitorMock) NotifyEvent(counterType int) { + m.Called(counterType) +} + +// Reset mock +func (m *ApplicationMonitorMock) Reset(counterType int, value int) { + m.Called(counterType, value) +} + +var _ application.MonitorProducerInterface = (*MockApplicationMonitor)(nil) diff --git a/service/api/specs/splitversionfilter_test.go b/service/api/specs/splitversionfilter_test.go index 8cd424b5..43680447 100644 --- a/service/api/specs/splitversionfilter_test.go +++ b/service/api/specs/splitversionfilter_test.go @@ -28,7 +28,7 @@ func TestParseAndValidate(t *testing.T) { } } -func TestsplitVersionFilter(t *testing.T) { +func TestSplitVersionFilter(t *testing.T) { filter := NewSplitVersionFilter() shouldFilter := filter.ShouldFilter(grammar.MatcherTypeBetweenSemver, FLAG_V1_0) if !shouldFilter { diff --git a/service/mocks/split.go b/service/mocks/split.go index b398554c..edf75de4 100644 --- a/service/mocks/split.go +++ b/service/mocks/split.go @@ -3,14 +3,22 @@ package mocks import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/service" + + "github.com/stretchr/testify/mock" ) // MockSplitFetcher mocked implementation of split fetcher type MockSplitFetcher struct { - FetchCall func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) + mock.Mock } // Fetch mock -func (m MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - return m.FetchCall(fetchOptions) +func (m *MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { + args := m.Called(fetchOptions) + if args.Get(0) == nil { + return nil, args.Error(1) + } + return args.Get(0).(*dtos.SplitChangesDTO), args.Error(1) } + +var _ service.SplitFetcher = (*MockSplitFetcher)(nil) diff --git a/storage/mocks/event.go b/storage/mocks/event.go index 6d24a5cf..c9d6c7e8 100644 --- a/storage/mocks/event.go +++ b/storage/mocks/event.go @@ -40,7 +40,7 @@ func (m MockEventStorage) Push(event dtos.EventDTO, size int) error { // Drop mock func (m MockEventStorage) Drop(size *int64) error { - return m.Drop(size) + return m.DropCall(size) } // PopNRaw mock diff --git a/storage/mocks/impression.go b/storage/mocks/impression.go index 2161f284..691341c3 100644 --- a/storage/mocks/impression.go +++ b/storage/mocks/impression.go @@ -40,7 +40,7 @@ func (m MockImpressionStorage) PopNWithMetadata(n int64) ([]dtos.ImpressionQueue // Drop mock func (m MockImpressionStorage) Drop(size *int64) error { - return m.Drop(size) + return m.DropCall(size) } // PopNRaw mock diff --git a/storage/mocks/rulebasedsegment.go b/storage/mocks/rulebasedsegment.go index 4987c94c..0f36bd63 100644 --- a/storage/mocks/rulebasedsegment.go +++ b/storage/mocks/rulebasedsegment.go @@ -15,7 +15,7 @@ type MockRuleBasedSegmentStorage struct { // ChangeNumber mock func (m *MockRuleBasedSegmentStorage) ChangeNumber() int64 { args := m.Called() - return int64(args.Int(0)) + return args.Get(0).(int64) } // All mock @@ -56,20 +56,18 @@ func (m *MockRuleBasedSegmentStorage) GetRuleBasedSegmentByName(name string) (*d // SetChangeNumber mock func (m *MockRuleBasedSegmentStorage) SetChangeNumber(till int64) error { - m.Called(till) - return nil + args := m.Called(till) + return args.Error(0) } // Update mock func (m *MockRuleBasedSegmentStorage) Update(toAdd []dtos.RuleBasedSegmentDTO, toRemove []dtos.RuleBasedSegmentDTO, till int64) { m.Called(toAdd, toRemove, till) - return } // Clear mock func (m *MockRuleBasedSegmentStorage) Clear() { m.Called() - return } var _ storage.RuleBasedSegmentsStorage = (*MockRuleBasedSegmentStorage)(nil) diff --git a/storage/mocks/split.go b/storage/mocks/split.go index cdb03171..315c9ef0 100644 --- a/storage/mocks/split.go +++ b/storage/mocks/split.go @@ -2,7 +2,9 @@ package mocks import ( "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" + "github.com/stretchr/testify/mock" ) // MockSplitStorage is a mocked implementation of Split Storage @@ -91,3 +93,111 @@ func (m MockSplitStorage) GetNamesByFlagSets(sets []string) map[string][]string func (m MockSplitStorage) GetAllFlagSetNames() []string { return m.GetAllFlagSetNamesCall() } + +// SplitStorageMock is a mocked implementation of Split Storage with testify +type SplitStorageMock struct { + mock.Mock +} + +// All mock +func (m *SplitStorageMock) All() []dtos.SplitDTO { + args := m.Called() + return args.Get(0).([]dtos.SplitDTO) +} + +// ChangeNumber mock +func (m *SplitStorageMock) ChangeNumber() (int64, error) { + args := m.Called() + return args.Get(0).(int64), args.Error(1) +} + +// FetchMany mock +func (m *SplitStorageMock) FetchMany(splitNames []string) map[string]*dtos.SplitDTO { + args := m.Called(splitNames) + if args.Get(0) == nil { + return nil + } + return args.Get(0).(map[string]*dtos.SplitDTO) +} + +// KillLocally mock +func (m *SplitStorageMock) KillLocally(splitName string, defaultTreatment string, changeNumber int64) { + m.Called(splitName, defaultTreatment, changeNumber) +} + +// Update mock +func (m *SplitStorageMock) Update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { + m.Called(toAdd, toRemove, changeNumber) +} + +// Remove mock +func (m *SplitStorageMock) Remove(splitname string) { + m.Called(splitname) +} + +// SegmentNames mock +func (m *SplitStorageMock) SegmentNames() *set.ThreadUnsafeSet { + args := m.Called() + if args.Get(0) == nil { + return nil + } + return args.Get(0).(*set.ThreadUnsafeSet) +} + +// LargeSegmentNames mock +func (m *SplitStorageMock) LargeSegmentNames() *set.ThreadUnsafeSet { + args := m.Called() + if args.Get(0) == nil { + return nil + } + return args.Get(0).(*set.ThreadUnsafeSet) +} + +// SetChangeNumber mock +func (m *SplitStorageMock) SetChangeNumber(changeNumber int64) error { + args := m.Called(changeNumber) + return args.Error(0) +} + +// Split mock +func (m *SplitStorageMock) Split(splitName string) *dtos.SplitDTO { + args := m.Called(splitName) + if args.Get(0) == nil { + return nil + } + return args.Get(0).(*dtos.SplitDTO) +} + +// SplitNames mock +func (m *SplitStorageMock) SplitNames() []string { + args := m.Called() + if args.Get(0) == nil { + return nil + } + return args.Get(0).([]string) +} + +// TrafficTypeExists mock +func (m *SplitStorageMock) TrafficTypeExists(trafficType string) bool { + args := m.Called(trafficType) + return args.Bool(0) +} + +// GetNamesByFLagSets mock +func (m *SplitStorageMock) GetNamesByFlagSets(sets []string) map[string][]string { + args := m.Called(sets) + if args.Get(0) == nil { + return nil + } + return args.Get(0).(map[string][]string) +} + +func (m *SplitStorageMock) GetAllFlagSetNames() []string { + args := m.Called() + if args.Get(0) == nil { + return nil + } + return args.Get(0).([]string) +} + +var _ storage.SplitStorage = (*SplitStorageMock)(nil) diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 51de0a51..25d83f82 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -2,7 +2,6 @@ package synchronizer import ( "errors" - "sync/atomic" "testing" "time" @@ -15,7 +14,10 @@ import ( httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" + "github.com/splitio/go-toolkit/v5/logging" + + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -29,33 +31,19 @@ var goClientRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar grammar.MatcherTypeInRuleBasedSegment} func TestLocalSyncAllError(t *testing.T) { - var splitFetchCalled int64 - var notifyEventCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return nil, errors.New("Some") - }, - }, - } - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - } + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(nil, errors.New("Some")).Once() + splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) telemetryMockStorage := mocks.MockTelemetryStorage{} - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() flagSetFilter := flagsets.NewFlagSetFilter(nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) splitUpdater := split.NewSplitUpdater( @@ -81,131 +69,85 @@ func TestLocalSyncAllError(t *testing.T) { } err := syncForTest.SyncAll() - if err == nil { - t.Error("It should return error") - } - if atomic.LoadInt64(&splitFetchCalled) != 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Errorf("It should be called once. Actual %d", notifyEventCalled) - } + assert.NotNil(t, err) + + splitFetcher.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestLocalSyncAllOk(t *testing.T) { - var splitFetchCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil - }, - }, - } - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - }, - } - var notifyEventCalled int64 + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", + mock.MatchedBy(func(req *service.FlagRequestParams) bool { + return req.ChangeNumber() == -1 + })).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3}, + }, nil).Once() + splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) + splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{}, int64(3)).Once() segmentMockStorage := mocks.MockSegmentStorage{} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, RecordSuccessfulSyncCall: func(resource int, when time.Time) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() largeSegmentStorage := &mocks.MockLargeSegmentStorage{} syncForTest := NewLocal(&LocalConfig{}, &splitAPI, splitMockStorage, segmentMockStorage, largeSegmentStorage, ruleBasedSegmentMockStorage, logger, telemetryMockStorage, appMonitorMock) err := syncForTest.SyncAll() - if err != nil { - t.Error("It should not return error") - } - if splitFetchCalled != 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Errorf("It should be called once. Actual %d", notifyEventCalled) - } + assert.Nil(t, err) + + splitFetcher.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestLocalPeriodicFetching(t *testing.T) { - var splitFetchCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil - }, - }, - } - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - }, - } + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3}, + }, nil).Once() + splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) + splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{}, int64(3)).Once() segmentMockStorage := mocks.MockSegmentStorage{} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, RecordSuccessfulSyncCall: func(resource int, when time.Time) {}, } - var notifyEventCalled int64 - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() largeSegmentStorage := &mocks.MockLargeSegmentStorage{} syncForTest := NewLocal(&LocalConfig{RefreshEnabled: true, SplitPeriod: 1}, &splitAPI, splitMockStorage, segmentMockStorage, largeSegmentStorage, ruleBasedSegmentMockStorage, logger, telemetryMockStorage, appMonitorMock) syncForTest.StartPeriodicFetching() time.Sleep(time.Millisecond * 1500) - if atomic.LoadInt64(&splitFetchCalled) != 1 { - t.Error("It should be called once", splitFetchCalled) - } syncForTest.StopPeriodicFetching() - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Errorf("It should be called once. Actual %d", notifyEventCalled) - } + + splitFetcher.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index da4712ea..6b9d58fe 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -16,9 +16,11 @@ import ( "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api" httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory" "github.com/splitio/go-split-commons/v7/storage/mocks" storageMock "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + syncMocks "github.com/splitio/go-split-commons/v7/synchronizer/mocks" "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" @@ -26,12 +28,23 @@ import ( "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" "github.com/splitio/go-split-commons/v7/tasks" "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" - "github.com/stretchr/testify/mock" ) +// func createSplitUpdater(splitMockStorage storageMock.MockSplitStorage, splitAPI api.SplitAPI, logger logging.LoggerInterface, telemetryMockStorage storageMock.MockTelemetryStorage, appMonitorMock hcMock.MockApplicationMonitor) split.Updater { +// ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} +// ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) +// ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) + +// largeSegmentStorage := &mocks.MockLargeSegmentStorage{} +// ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) +// splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) +// return splitUpdater +// } + func validReqParams(t *testing.T, fetchOptions service.RequestParams) { req, _ := http.NewRequest("GET", "test", nil) fetchOptions.Apply(req) @@ -43,44 +56,21 @@ func validReqParams(t *testing.T, fetchOptions service.RequestParams) { } } -func createSplitUpdater(splitMockStorage storageMock.MockSplitStorage, splitAPI api.SplitAPI, logger logging.LoggerInterface, telemetryMockStorage storageMock.MockTelemetryStorage, appMonitorMock hcMock.MockApplicationMonitor) split.Updater { - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) - ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) - - largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) - return splitUpdater -} - func TestSyncAllErrorSplits(t *testing.T) { - var splitFetchCalled int64 - var notifyEventCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - validReqParams(t, fetchOptions) - return nil, errors.New("Some") - }, - }, - } - splitMockStorage := storageMock.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - } + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(nil, errors.New("some")) + splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) telemetryMockStorage := storageMock.MockTelemetryStorage{ RecordSuccessfulSyncCall: func(resource int, time time.Time) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)).Times(2) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -103,36 +93,27 @@ func TestSyncAllErrorSplits(t *testing.T) { } syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) err := syncForTest.SyncAll() - if err == nil { - t.Error("It should return error") - } - if atomic.LoadInt64(&splitFetchCalled) != 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called once") - } + assert.NotNil(t, err) + + splitFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestSyncAllErrorInSegments(t *testing.T) { - var splitFetchCalled int64 var segmentFetchCalled int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3}, + }, nil) splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - validReqParams(t, fetchOptions) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil - }, - }, + SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ FetchCall: func(name string, fetchOptions *service.SegmentRequestParams) (*dtos.SegmentChangesDTO, error) { atomic.AddInt64(&segmentFetchCalled, 1) @@ -144,18 +125,10 @@ func TestSyncAllErrorInSegments(t *testing.T) { }, }, } - splitMockStorage := storageMock.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - }, - SegmentNamesCall: func() *set.ThreadUnsafeSet { return set.NewSet("segment1", "segment2") }, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) + splitMockStorage.On("Update", mock.Anything, []dtos.SplitDTO{}, int64(3)).Return().Once() + splitMockStorage.On("SegmentNames").Return(set.NewSet("segment1", "segment2")).Once() segmentMockStorage := storageMock.MockSegmentStorage{ ChangeNumberCall: func(segmentName string) (int64, error) { return -1, nil }, } @@ -163,16 +136,18 @@ func TestSyncAllErrorInSegments(t *testing.T) { RecordSuccessfulSyncCall: func(resource int, time time.Time) {}, RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(4) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ - SplitUpdater: createSplitUpdater(splitMockStorage, splitAPI, logger, telemetryMockStorage, appMonitorMock), + SplitUpdater: splitUpdater, SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), ImpressionRecorder: impression.NewRecorderSingle(storageMock.MockImpressionStorage{}, splitAPI.ImpressionRecorder, logger, dtos.Metadata{}, conf.ImpressionsModeDebug, telemetryMockStorage), @@ -187,39 +162,28 @@ func TestSyncAllErrorInSegments(t *testing.T) { } syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) err := syncForTest.SyncAll() - if err == nil { - t.Error("It should return error") - } - if atomic.LoadInt64(&splitFetchCalled) != 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(&segmentFetchCalled) != 2 { - t.Error("It should be called twice") - } - if atomic.LoadInt64(¬ifyEventCalled) < 1 { - t.Error("It should be called at least once") - } + assert.NotNil(t, err) + assert.Equal(t, int64(2), atomic.LoadInt64(&segmentFetchCalled)) + + splitFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestSyncAllOk(t *testing.T) { - var splitFetchCalled int64 var segmentFetchCalled int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3}, + }, nil) splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - validReqParams(t, fetchOptions) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil - }, - }, + SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ FetchCall: func(name string, fetchOptions *service.SegmentRequestParams) (*dtos.SegmentChangesDTO, error) { atomic.AddInt64(&segmentFetchCalled, 1) @@ -237,18 +201,10 @@ func TestSyncAllOk(t *testing.T) { }, }, } - splitMockStorage := storageMock.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - }, - SegmentNamesCall: func() *set.ThreadUnsafeSet { return set.NewSet("segment1", "segment2") }, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) + splitMockStorage.On("Update", mock.Anything, []dtos.SplitDTO{}, int64(3)).Return().Once() + splitMockStorage.On("SegmentNames").Return(set.NewSet("segment1", "segment2")).Once() segmentMockStorage := storageMock.MockSegmentStorage{ ChangeNumberCall: func(segmentName string) (int64, error) { return -1, nil }, KeysCall: func(segmentName string) *set.ThreadUnsafeSet { @@ -268,17 +224,18 @@ func TestSyncAllOk(t *testing.T) { RecordSuccessfulSyncCall: func(resource int, time time.Time) {}, RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(4) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) - + ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ - SplitUpdater: createSplitUpdater(splitMockStorage, splitAPI, logger, telemetryMockStorage, appMonitorMock), + SplitUpdater: splitUpdater, SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), ImpressionRecorder: impression.NewRecorderSingle(storageMock.MockImpressionStorage{}, splitAPI.ImpressionRecorder, logger, dtos.Metadata{}, conf.ImpressionsModeDebug, telemetryMockStorage), @@ -293,39 +250,27 @@ func TestSyncAllOk(t *testing.T) { } syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) err := syncForTest.SyncAll() - if err != nil { - t.Error("It should not return error") - } - if splitFetchCalled != 1 { - t.Error("It should be called once") - } - if segmentFetchCalled != 2 { - t.Error("It should be called twice") - } - if atomic.LoadInt64(¬ifyEventCalled) < 1 { - t.Error("It should be called at least once") - } + assert.Nil(t, err) + assert.Equal(t, int64(2), atomic.LoadInt64(&segmentFetchCalled)) + splitFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestPeriodicFetching(t *testing.T) { - var splitFetchCalled int64 var segmentFetchCalled int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) + splitFetcher := &httpMocks.MockSplitFetcher{} + splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3}, + }).Once() splitAPI := api.SplitAPI{ - SplitFetcher: httpMocks.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&splitFetchCalled, 1) - validReqParams(t, fetchOptions) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil - }, - }, + SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ FetchCall: func(name string, fetchOptions *service.SegmentRequestParams) (*dtos.SegmentChangesDTO, error) { atomic.AddInt64(&segmentFetchCalled, 1) @@ -343,18 +288,10 @@ func TestPeriodicFetching(t *testing.T) { }, }, } - splitMockStorage := storageMock.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - }, - SegmentNamesCall: func() *set.ThreadUnsafeSet { return set.NewSet("segment1", "segment2") }, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) + // splitMockStorage.On("Update", mock.Anything, []dtos.SplitDTO{}, int64(3)).Return().Twice() + splitMockStorage.On("SegmentNames").Return(set.NewSet("segment1", "segment2")).Twice() segmentMockStorage := storageMock.MockSegmentStorage{ ChangeNumberCall: func(segmentName string) (int64, error) { return -1, nil }, KeysCall: func(segmentName string) *set.ThreadUnsafeSet { @@ -374,16 +311,16 @@ func TestPeriodicFetching(t *testing.T) { RecordSuccessfulSyncCall: func(resource int, time time.Time) {}, RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - ResetCall: func(counterType, value int) {}, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ - SplitUpdater: createSplitUpdater(splitMockStorage, splitAPI, logger, telemetryMockStorage, appMonitorMock), + SplitUpdater: splitUpdater, SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), ImpressionRecorder: impression.NewRecorderSingle(storageMock.MockImpressionStorage{}, splitAPI.ImpressionRecorder, logger, dtos.Metadata{}, conf.ImpressionsModeDebug, telemetryMockStorage), @@ -399,15 +336,11 @@ func TestPeriodicFetching(t *testing.T) { syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) syncForTest.StartPeriodicFetching() time.Sleep(time.Millisecond * 2200) - if atomic.LoadInt64(&splitFetchCalled) < 2 { - t.Error("It should be called twice") - } - if atomic.LoadInt64(&segmentFetchCalled) < 2 { - t.Error("It should be called twice") - } - if atomic.LoadInt64(¬ifyEventCalled) < 1 { - t.Error("It should be called at least once") - } + assert.Equal(t, int64(4), atomic.LoadInt64(&segmentFetchCalled)) + splitFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) syncForTest.StopPeriodicFetching() } @@ -415,24 +348,19 @@ func TestPeriodicRecording(t *testing.T) { var impressionsCalled int64 var eventsCalled int64 var statsCalled int64 - var notifyEventCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) splitAPI := api.SplitAPI{ EventRecorder: httpMocks.MockEventRecorder{ RecordCall: func(events []dtos.EventDTO, metadata dtos.Metadata) error { atomic.AddInt64(&eventsCalled, 1) - if len(events) != 1 { - t.Error("Wrong length") - } + assert.Len(t, events, 1) return nil }, }, ImpressionRecorder: httpMocks.MockImpressionRecorder{ RecordCall: func(impressions []dtos.ImpressionsDTO, metadata dtos.Metadata, extraHeaders map[string]string) error { atomic.AddInt64(&impressionsCalled, 1) - if len(impressions) != 1 { - t.Error("Wrong length") - } + assert.Len(t, impressions, 1) return nil }, }, @@ -445,9 +373,7 @@ func TestPeriodicRecording(t *testing.T) { } impressionMockStorage := storageMock.MockImpressionStorage{ PopNCall: func(n int64) ([]dtos.Impression, error) { - if n != 100 { - t.Error("It should be 100") - } + assert.Equal(t, int64(100), n) return []dtos.Impression{{ BucketingKey: "someBucketingKey", ChangeNumber: 123456789, @@ -458,13 +384,11 @@ func TestPeriodicRecording(t *testing.T) { Treatment: "someTreatment", }}, nil }, - EmptyCall: func() bool { return impressionsCalled >= 3 }, + EmptyCall: func() bool { return atomic.LoadInt64(&impressionsCalled) >= 3 }, } eventMockStorage := storageMock.MockEventStorage{ PopNCall: func(n int64) ([]dtos.EventDTO, error) { - if n != 100 { - t.Error("It should be 100") - } + assert.Equal(t, int64(100), n) return []dtos.EventDTO{{ EventTypeID: "someEvent", Key: "someKey", @@ -474,7 +398,7 @@ func TestPeriodicRecording(t *testing.T) { Value: nil, }}, nil }, - EmptyCall: func() bool { return eventsCalled >= 4 }, + EmptyCall: func() bool { return atomic.LoadInt64(&eventsCalled) >= 4 }, } telemetryMockStorage := storageMock.MockTelemetryStorage{ PopLatenciesCall: func() dtos.MethodLatencies { return dtos.MethodLatencies{} }, @@ -493,23 +417,15 @@ func TestPeriodicRecording(t *testing.T) { RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, PopUpdatesFromSSECall: func() dtos.UpdatesFromSSE { return dtos.UpdatesFromSSE{} }, } - splitMockStorage := storageMock.MockSplitStorage{ - SplitNamesCall: func() []string { return []string{} }, - SegmentNamesCall: func() *set.ThreadUnsafeSet { return set.NewSet() }, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("SplitNames").Return([]string{}) + splitMockStorage.On("SegmentNames").Return(set.NewSet()) segmentMockStorage := storageMock.MockSegmentStorage{ SegmentKeysCountCall: func() int64 { return 30 }, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + appMonitorMock := &hcMock.ApplicationMonitorMock{} advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ - SplitUpdater: createSplitUpdater(splitMockStorage, splitAPI, logger, telemetryMockStorage, appMonitorMock), - SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(eventMockStorage, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), ImpressionRecorder: impression.NewRecorderSingle(impressionMockStorage, splitAPI.ImpressionRecorder, logger, dtos.Metadata{}, conf.ImpressionsModeDebug, telemetryMockStorage), TelemetryRecorder: telemetry.NewTelemetrySynchronizer(telemetryMockStorage, splitAPI.TelemetryRecorder, splitMockStorage, segmentMockStorage, logger, dtos.Metadata{}, telemetryMockStorage), @@ -517,39 +433,64 @@ func TestPeriodicRecording(t *testing.T) { splitTasks := SplitTasks{ EventSyncTask: tasks.NewRecordEventsTask(workers.EventRecorder, advanced.EventsBulkSize, 1, logger), ImpressionSyncTask: tasks.NewRecordImpressionsTask(workers.ImpressionRecorder, 1, logger, advanced.ImpressionsBulkSize), - SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentUpdater, 1, advanced.SegmentWorkers, advanced.SegmentQueueSize, logger, appMonitorMock), - SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), TelemetrySyncTask: tasks.NewRecordTelemetryTask(workers.TelemetryRecorder, 1, logger), } - workers.TelemetryRecorder.SynchronizeStats() syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) syncForTest.StartPeriodicDataRecording() - time.Sleep(time.Second * 2) - if atomic.LoadInt64(&impressionsCalled) < 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(&eventsCalled) < 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(&statsCalled) < 1 { - t.Error("It should be called once") - } + time.Sleep(time.Millisecond * 1200) + assert.Equal(t, int64(1), atomic.LoadInt64(&impressionsCalled)) + assert.Equal(t, int64(1), atomic.LoadInt64(&eventsCalled)) + assert.Equal(t, int64(1), atomic.LoadInt64(&statsCalled)) syncForTest.StopPeriodicDataRecording() - time.Sleep(time.Second * 1) - if atomic.LoadInt64(&impressionsCalled) < 2 { - t.Error("It should be called two times") - } - if atomic.LoadInt64(&eventsCalled) < 2 { - t.Error("It should be called two times") - } - if atomic.LoadInt64(&statsCalled) < 2 { - t.Error("It should be called two times") + assert.Equal(t, int64(2), atomic.LoadInt64(&impressionsCalled)) + assert.Equal(t, int64(2), atomic.LoadInt64(&eventsCalled)) + assert.Equal(t, int64(2), atomic.LoadInt64(&statsCalled)) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) +} + +func TestSplitUpdateWorkerCNGreaterThanFFChange(t *testing.T) { + logger := logging.NewLogger(&logging.LoggerOptions{}) + splitFetcher := &httpMocks.MockSplitFetcher{} + splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(2), nil).Once() + segmentMockStorage := storageMock.MockSegmentStorage{} + telemetryMockStorage := storageMock.MockTelemetryStorage{} + appMonitorMock := &hcMock.ApplicationMonitorMock{} + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) + workers := Workers{ + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder), + SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), } - if atomic.LoadInt64(¬ifyEventCalled) != 0 { - t.Error("It should not be called") + splitTasks := SplitTasks{ + SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentUpdater, 1, 1, 500, logger, appMonitorMock), + SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), } + syncForTest := NewSynchronizer(conf.AdvancedConfig{}, splitTasks, workers, logger, nil) + + splitQueue := make(chan dtos.SplitChangeUpdate, 5000) + splitWorker, _ := push.NewSplitUpdateWorker(splitQueue, syncForTest, logger) + splitWorker.Start() + + // Testing Storage With Changenumber Greater Than FF + splitQueue <- *dtos.NewSplitChangeUpdate( + dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 1), nil, nil, + ) + + time.Sleep(100 * time.Millisecond) + assert.True(t, splitWorker.IsRunning(), "It should be running") + + splitFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } +/* func TestSplitUpdateWorkerCNGreaterThanFFChange(t *testing.T) { var splitFetchCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) @@ -969,26 +910,14 @@ func TestSplitUpdateWorkerFFPcnDifferentStorageCN(t *testing.T) { t.Error("should have been called once. got: ", u) } } +*/ func TestLocalKill(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) splitAPI := api.SplitAPI{} - splitMockStorage := storageMock.MockSplitStorage{ - KillLocallyCall: func(splitName, defaultTreatment string, changeNumber int64) { - if splitName != "split" { - t.Error("Wrong splitName") - } - if defaultTreatment != "default_treatment" { - t.Error("Wrong defaultTreatment") - } - if changeNumber != 123456789 { - t.Error("Wrong changeNumber") - } - }, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("KillLocally", "split", "default_treatment", int64(123456789)).Return(nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) - largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) @@ -1000,44 +929,34 @@ func TestLocalKill(t *testing.T) { } syncForTest := NewSynchronizer(conf.AdvancedConfig{}, splitTasks, workers, logger, nil) syncForTest.LocalKill("split", "default_treatment", 123456789) + + splitMockStorage.AssertExpectations(t) } + func TestSplitUpdateWithReferencedSegments(t *testing.T) { - var ffUpdateCalled int64 + // Should we move to Split Worker var segmentUpdateCalled int64 var segmentFetchCalled int64 var recordUpdateCall int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - splitAPI := api.SplitAPI{SegmentFetcher: httpMocks.MockSegmentFetcher{ - FetchCall: func(name string, fetchOptions *service.SegmentRequestParams) (*dtos.SegmentChangesDTO, error) { - atomic.AddInt64(&segmentFetchCalled, 1) - if name != "segment1" { - t.Error("Wrong name") - } - validReqParams(t, fetchOptions) - return &dtos.SegmentChangesDTO{ - Name: name, - Added: []string{"some"}, - Removed: []string{}, - Since: 123, - Till: 123, - }, nil - }, - }} - splitMockStorage := storageMock.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return 1, nil - }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if len(toAdd) != 1 { - t.Error("toAdd should have one feature flag") - } - if len(toRemove) != 0 { - t.Error("toRemove should be empty") - } - atomic.AddInt64(&ffUpdateCalled, 1) - }, - SegmentNamesCall: func() *set.ThreadUnsafeSet { return set.NewSet("segment1") }, - } + splitAPI := api.SplitAPI{ + SegmentFetcher: httpMocks.MockSegmentFetcher{ + FetchCall: func(name string, fetchOptions *service.SegmentRequestParams) (*dtos.SegmentChangesDTO, error) { + atomic.AddInt64(&segmentFetchCalled, 1) + assert.Equal(t, "segment1", name) + validReqParams(t, fetchOptions) + return &dtos.SegmentChangesDTO{ + Name: name, + Added: []string{"some"}, + Removed: []string{}, + Since: 123, + Till: 123, + }, nil + }, + }} + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(1), nil).Once() + splitMockStorage.On("Update", mock.Anything, mock.Anything, int64(2)).Return().Once() segmentMockStorage := storageMock.MockSegmentStorage{ ChangeNumberCall: func(segmentName string) (int64, error) { if segmentName != "segment1" { @@ -1048,9 +967,7 @@ func TestSplitUpdateWithReferencedSegments(t *testing.T) { }, UpdateCall: func(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, changeNumber int64) error { atomic.AddInt64(&segmentUpdateCalled, 1) - if name != "segment1" { - t.Error("Wrong name") - } + assert.Equal(t, "segment1", name) return nil }, } @@ -1061,12 +978,9 @@ func TestSplitUpdateWithReferencedSegments(t *testing.T) { RecordSuccessfulSyncCall: func(resource int, time time.Time) {}, RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } - + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -1095,41 +1009,28 @@ func TestSplitUpdateWithReferencedSegments(t *testing.T) { ) time.Sleep(300 * time.Millisecond) - - if u := atomic.LoadInt64(&ffUpdateCalled); u != 1 { - t.Error("should haven been called. got: ", u) - } - if s := atomic.LoadInt64(&segmentFetchCalled); s != 1 { - t.Error("should haven been called. got: ", s) - } - if s := atomic.LoadInt64(&segmentUpdateCalled); s != 1 { - t.Error("should haven been called. got: ", s) - } - if r := atomic.LoadInt64(&recordUpdateCall); r != 1 { - t.Error("should haven been called. got: ", r) - } + assert.Equal(t, int64(1), atomic.LoadInt64(&segmentFetchCalled)) + assert.Equal(t, int64(1), atomic.LoadInt64(&segmentUpdateCalled)) + assert.Equal(t, int64(1), atomic.LoadInt64(&recordUpdateCall)) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } -// Large Segment test cases func TestSyncAllWithLargeSegmentLazyLoad(t *testing.T) { - // Updaters - var segmentUpdater syncMocks.SegmentUpdaterMock + segmentUpdater := &syncMocks.SegmentUpdaterMock{} segmentUpdater.On("SynchronizeSegments").Return(map[string]segment.UpdateResult{}, nil).Once() - - var splitUpdater syncMocks.SplitUpdaterMock + splitUpdater := &syncMocks.SplitUpdaterMock{} splitUpdater.On("SynchronizeSplits", (*int64)(nil)).Return(&split.UpdateResult{}, nil).Once() - - var lsUpdater syncMocks.LargeSegmentUpdaterMock + lsUpdater := &syncMocks.LargeSegmentUpdaterMock{} lsUpdater.On("SynchronizeLargeSegments").Return(map[string]*int64{}, nil).Once() - // Workers workers := Workers{ - SegmentUpdater: &segmentUpdater, - SplitUpdater: &splitUpdater, - LargeSegmentUpdater: &lsUpdater, + SegmentUpdater: segmentUpdater, + SplitUpdater: splitUpdater, + LargeSegmentUpdater: lsUpdater, } - // Config cfn := conf.AdvancedConfig{ LargeSegment: &conf.LargeSegmentConfig{ Enable: true, @@ -1137,37 +1038,27 @@ func TestSyncAllWithLargeSegmentLazyLoad(t *testing.T) { }, } - // Sync sync := NewSynchronizer(cfn, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) sync.SyncAll() - - time.Sleep(time.Millisecond * 1000) - + time.Sleep(100 * time.Millisecond) segmentUpdater.AssertExpectations(t) splitUpdater.AssertExpectations(t) lsUpdater.AssertExpectations(t) } func TestSyncAllWithLargeSegmentLazyLoadFalse(t *testing.T) { - var segmentUpdater syncMocks.SegmentUpdaterMock + segmentUpdater := &syncMocks.SegmentUpdaterMock{} segmentUpdater.On("SynchronizeSegments").Return(map[string]segment.UpdateResult{}, nil).Once() - - var splitUpdater syncMocks.SplitUpdaterMock + splitUpdater := &syncMocks.SplitUpdaterMock{} splitUpdater.On("SynchronizeSplits", (*int64)(nil)).Return(&split.UpdateResult{}, nil).Once() - - var lsUpdater syncMocks.LargeSegmentUpdaterMock + lsUpdater := &syncMocks.LargeSegmentUpdaterMock{} lsUpdater.On("SynchronizeLargeSegments").Return(map[string]*int64{}, nil).Once() - - // Workers workers := Workers{ - SegmentUpdater: &segmentUpdater, - SplitUpdater: &splitUpdater, - LargeSegmentUpdater: &lsUpdater, + SegmentUpdater: segmentUpdater, + SplitUpdater: splitUpdater, + LargeSegmentUpdater: lsUpdater, } - - // Tasks splitTasks := SplitTasks{} - cfn := conf.AdvancedConfig{ LargeSegment: &conf.LargeSegmentConfig{ Enable: true, @@ -1185,109 +1076,68 @@ func TestSyncAllWithLargeSegmentLazyLoadFalse(t *testing.T) { func TestSynchronizeLargeSegment(t *testing.T) { lsName := "ls_test" - // Updaters var cn *int64 var lsUpdater syncMocks.LargeSegmentUpdaterMock lsUpdater.On("SynchronizeLargeSegment", lsName, (*int64)(nil)).Return(cn, nil).Once() - // Workers workers := Workers{LargeSegmentUpdater: &lsUpdater} - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) err := sync.SynchronizeLargeSegment(lsName, nil) - if err != nil { - t.Error("Error should be nil") - } + assert.Nil(t, err) lsUpdater.AssertExpectations(t) } func TestSynchronizeLargeSegmentWithoutUpdaters(t *testing.T) { lsName := "ls_test" - - // Updaters var lsUpdater syncMocks.LargeSegmentUpdaterMock - - // Workers workers := Workers{} - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) - err := sync.SynchronizeLargeSegment(lsName, nil) - if err != nil { - t.Error("Error should be nil") - } - + assert.Nil(t, err) lsUpdater.AssertExpectations(t) } func TestSynchronizeLargeSegmentsWithoutUpdaters(t *testing.T) { - // Updaters var lsUpdater syncMocks.LargeSegmentUpdaterMock - - // Workers workers := Workers{} - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) - err := sync.(*SynchronizerImpl).synchronizeLargeSegments() - if err != nil { - t.Error("Error should be nil") - } - + assert.Nil(t, err) lsUpdater.AssertExpectations(t) } func TestFilterCachedLargeSegmentsWithoutUpdater(t *testing.T) { lsNames := []string{"ls1", "ls2", "ls3"} - - // Updaters var lsUpdater syncMocks.LargeSegmentUpdaterMock - - // Workers workers := Workers{} - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) - filtered := sync.(*SynchronizerImpl).filterCachedLargeSegments(lsNames) - if len(filtered) != 0 { - t.Error("filtered len should be 0. Actual: ", len(filtered)) - } - + assert.Empty(t, filtered) lsUpdater.AssertExpectations(t) } func TestFilterCachedLargeSegments(t *testing.T) { lsNames := []string{"ls1", "ls2", "ls3"} - - // Updaters var lsUpdater syncMocks.LargeSegmentUpdaterMock lsUpdater.On("IsCached", "ls1").Return(true).Once() lsUpdater.On("IsCached", "ls2").Return(false).Once() lsUpdater.On("IsCached", "ls3").Return(true).Once() - // Workers workers := Workers{ LargeSegmentUpdater: &lsUpdater, } - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) filtered := sync.(*SynchronizerImpl).filterCachedLargeSegments(lsNames) - if len(filtered) != 1 { - t.Error("filtered len should be 1. Actual: ", len(filtered)) - } - if filtered[0] != "ls2" { - t.Error("Filtered name should be ls2. Actual: ", filtered[0]) - } + assert.Len(t, filtered, 1) + assert.Equal(t, "ls2", filtered[0]) lsUpdater.AssertExpectations(t) } func TestSynchronizeLargeSegmentsAfterSplitSync(t *testing.T) { lsNames := []string{"ls1", "ls2", "ls3"} - - // Updaters var cn *int64 var lsUpdater syncMocks.LargeSegmentUpdaterMock lsUpdater.On("SynchronizeLargeSegment", "ls1", (*int64)(nil)).Return(cn, nil).Once() @@ -1296,17 +1146,12 @@ func TestSynchronizeLargeSegmentsAfterSplitSync(t *testing.T) { lsUpdater.On("IsCached", "ls1").Return(false).Once() lsUpdater.On("IsCached", "ls2").Return(false).Once() lsUpdater.On("IsCached", "ls3").Return(false).Once() - - // Workers workers := Workers{ LargeSegmentUpdater: &lsUpdater, } - sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) sync.(*SynchronizerImpl).synchronizeLargeSegmentsAfterSplitSync(lsNames) - time.Sleep(time.Millisecond * 1000) - lsUpdater.AssertExpectations(t) } @@ -1341,14 +1186,10 @@ func TestStartAndStopFetchingWithLargeSegmentTask(t *testing.T) { SplitUpdater: &splitUpdater, SegmentUpdater: &segmentUpdater, } - splitMockStorage := storageMock.MockSplitStorage{ - LargeSegmentNamesCall: func() *set.ThreadUnsafeSet { - return set.NewSet("ls1", "ls2", "ls3") - }, - } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } + splitMockStorage := &storageMock.SplitStorageMock{} + splitMockStorage.On("LargeSegmentNames").Return(set.NewSet("ls1", "ls2", "ls3")).Once() + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything) splitTasks := SplitTasks{ SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentUpdater, 1, advanced.SegmentWorkers, advanced.SegmentQueueSize, logger, appMonitorMock), SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), @@ -1362,6 +1203,8 @@ func TestStartAndStopFetchingWithLargeSegmentTask(t *testing.T) { segmentUpdater.AssertExpectations(t) splitUpdater.AssertExpectations(t) lsUpdater.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) sync.StopPeriodicFetching() } @@ -1409,9 +1252,7 @@ func TestSynchronizeLargeSegmentUpdate(t *testing.T) { sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) err := sync.SynchronizeLargeSegmentUpdate(dto) - if err != nil { - t.Error("Error should be nil. Actual:", err) - } + assert.Nil(t, err) lsUpdater.AssertExpectations(t) } @@ -1430,9 +1271,7 @@ func TestSynchronizeLargeSegmentUpdateNotCached(t *testing.T) { sync := NewSynchronizer(conf.AdvancedConfig{}, SplitTasks{}, workers, logging.NewLogger(&logging.LoggerOptions{}), nil) err := sync.SynchronizeLargeSegmentUpdate(dto) - if err != nil { - t.Error("Error should be nil. Actual:", err) - } + assert.Nil(t, err) lsUpdater.AssertExpectations(t) } diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index e6f6c560..6c149b09 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -385,7 +385,7 @@ func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitCha return &UpdateResult{ ReferencedSegments: segments, - NewChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), + NewRBChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), RequiresFetch: false, } } diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index b9fcb328..85330a58 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -2,8 +2,6 @@ package split import ( "errors" - "net/http" - "sync/atomic" "testing" "time" @@ -17,8 +15,11 @@ import ( "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" "github.com/splitio/go-split-commons/v7/storage/mocks" "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" + + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -31,114 +32,68 @@ var syncProxyRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, gramma grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, grammar.MatcherTypeInRuleBasedSegment} -func validReqParams(t *testing.T, fetchOptions service.RequestParams, till string) { - req, _ := http.NewRequest("GET", "test", nil) - fetchOptions.Apply(req) - if req.Header.Get("Cache-Control") != "no-cache" { - t.Error("Wrong header") - } - if req.URL.Query().Get("till") != till { - t.Error("Wrong till") - } -} - func TestSplitSynchronizerError(t *testing.T) { - var notifyEventCalled int64 - - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - } + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return nil, &dtos.HTTPError{Code: 500, Message: "some"} - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.MatchedBy(func(req *service.FlagRequestParams) bool { + return req.ChangeNumber() == -1 + })).Return(nil, &dtos.HTTPError{Code: 500, Message: "some"}).Once() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSyncErrorCall: func(resource, status int) { - if resource != telemetry.SplitSync { - t.Error("It should be splits") - } - if status != 500 { - t.Error("Status should be 500") - } + assert.Equal(t, telemetry.SplitSync, resource) + assert.Equal(t, 500, status) }, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) _, err := splitUpdater.SynchronizeSplits(nil) - if err == nil { - t.Error("It should return err") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called once") - } + assert.NotNil(t, err) + + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestSplitSynchronizerErrorScRequestURITooLong(t *testing.T) { - var notifyEventCalled int64 - var fetchCall int64 + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - } - - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCall, 1) - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return nil, &dtos.HTTPError{Code: 414, Message: "some"} - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.MatchedBy(func(req *service.FlagRequestParams) bool { + return req.ChangeNumber() == -1 + })).Return(nil, &dtos.HTTPError{Code: 414, Message: "some"}).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSyncErrorCall: func(resource, status int) { - if resource != telemetry.SplitSync { - t.Error("It should be splits") - } - if status != 414 { - t.Error("Status should be 414") - } + assert.Equal(t, telemetry.SplitSync, resource) + assert.Equal(t, 414, status) }, } ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) _, err := splitUpdater.SynchronizeSplits(nil) - if err == nil { - t.Error("It should return err") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called once") - } - if atomic.LoadInt64(&fetchCall) != 1 { - t.Error("fetchCall should be called once") - } + assert.NotNil(t, err) + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestSplitSynchronizer(t *testing.T) { @@ -146,73 +101,33 @@ func TestSplitSynchronizer(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: true, Status: "INACTIVE", TrafficTypeName: "one"} - var notifyEventCalled int64 - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return -1, nil - }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - s1 := toAdd[0] - if s1.Name != "split1" || s1.Killed { - t.Error("split1 stored/retrieved incorrectly") - t.Error(s1) - } - s2 := toAdd[1] - if s2.Name != "split2" || !s2.Killed { - t.Error("split2 stored/retrieved incorrectly") - t.Error(s2) - } - }, - RemoveCall: func(splitname string) { - if splitname != "split3" { - t.Error("It should remove split3") - } - }, - } + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) + splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong since") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3, + }}, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSuccessfulSyncCall: func(resource int, tm time.Time) { - if resource != telemetry.SplitSync { - t.Error("Resource should be splits") - } - if tm.Before(before) { - t.Error("It should be higher than before") - } + assert.Equal(t, telemetry.SplitSync, resource) + assert.True(t, tm.After(before)) }, RecordSyncLatencyCall: func(resource int, tm time.Duration) { - if resource != telemetry.SplitSync { - t.Error("Resource should be splits") - } + assert.Equal(t, telemetry.SplitSync, resource) }, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -221,17 +136,15 @@ func TestSplitSynchronizer(t *testing.T) { splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) _, err := splitUpdater.SynchronizeSplits(nil) - if err != nil { - t.Error("It should not return err") - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called once") - } + assert.Nil(t, err) + + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestSplitSyncProcess(t *testing.T) { - var call int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: true, Status: "INACTIVE", TrafficTypeName: "one"} @@ -243,48 +156,28 @@ func TestSplitSyncProcess(t *testing.T) { }}}}, } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - switch call { - case 1: - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil - case 2: - if fetchOptions.ChangeNumber() != 3 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit4, mockedSplit5}, - Since: 3, - Till: 3}, - }, nil - default: - t.Error("Wrong calls") - return nil, errors.New("some") - } - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3}, + }, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit4, mockedSplit5}, + Since: 3, + Till: 3}, + }, nil).Once() - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(2) splitStorage := mutexmap.NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) splitStorage.Update([]dtos.SplitDTO{{}}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(-1) - ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(3).Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(2).Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -292,99 +185,52 @@ func TestSplitSyncProcess(t *testing.T) { splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) res, err := splitUpdater.SynchronizeSplits(nil) - if err != nil { - t.Error("It should not return err") - } - - if len(res.ReferencedSegments) != 0 { - t.Error("invalid referenced segment names. Got: ", res.ReferencedSegments) - } - - if !splitStorage.TrafficTypeExists("one") { - t.Error("It should exists") - } - - if !splitStorage.TrafficTypeExists("two") { - t.Error("It should exists") - } + assert.Nil(t, err) + assert.Len(t, res.ReferencedSegments, 0) + assert.True(t, splitStorage.TrafficTypeExists("one")) + assert.True(t, splitStorage.TrafficTypeExists("two")) res, err = splitUpdater.SynchronizeSplits(nil) - if err != nil { - t.Error("It should not return err") - } - - if len(res.ReferencedSegments) != 1 || res.ReferencedSegments[0] != "someSegment" { - t.Error("invalid referenced segment names. Got: ", res.ReferencedSegments) - } - - s1 := splitStorage.Split("split1") - if s1 != nil { - t.Error("split1 should have been removed") - } - - s2 := splitStorage.Split("split2") - if s2 == nil || s2.Name != "split2" || !s2.Killed { - t.Error("split2 stored/retrieved incorrectly") - t.Error(s2) - } - - s3 := splitStorage.Split("split3") - if s3 != nil { - t.Error("split3 should have been removed") - } - - s4 := splitStorage.Split("split4") - if s4 == nil || s4.Name != "split4" || s4.Killed { - t.Error("split4 stored/retrieved incorrectly") - t.Error(s4) - } - - if splitStorage.TrafficTypeExists("one") { - t.Error("It should not exists") - } - - if !splitStorage.TrafficTypeExists("two") { - t.Error("It should exists") - } - - if atomic.LoadInt64(¬ifyEventCalled) != 2 { - t.Error("It should be called twice") - } + assert.Nil(t, err) + assert.Len(t, res.ReferencedSegments, 1) + assert.Equal(t, res.ReferencedSegments[0], "someSegment") + + assert.Nil(t, splitStorage.Split("split1")) + assert.Equal(t, mockedSplit2, *splitStorage.Split("split2")) + assert.Nil(t, splitStorage.Split("split3")) + assert.Equal(t, mockedSplit5, *splitStorage.Split("split4")) + assert.False(t, splitStorage.TrafficTypeExists("one")) + assert.True(t, splitStorage.TrafficTypeExists("two")) + + appMonitorMock.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } func TestSplitTill(t *testing.T) { - var call int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, - Since: 2, - Till: 2}, - }, nil - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2}, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, + Since: 2, + Till: 2}, + }, nil).Twice() - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(2) splitStorage := mutexmap.NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) splitStorage.Update([]dtos.SplitDTO{{}}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Times(12).Return(-1) - ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(12).Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Times(4).Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(2).Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -392,73 +238,45 @@ func TestSplitTill(t *testing.T) { var till int64 = 1 _, err := splitUpdater.SynchronizeSplits(&till) - if err != nil { - t.Error("It should not return err") - } + assert.Nil(t, err) _, err = splitUpdater.SynchronizeSplits(&till) - if err != nil { - t.Error("It should not return err") - } - if atomic.LoadInt64(&call) != 2 { - t.Error("It should be called once") - } - if atomic.LoadInt64(¬ifyEventCalled) != 2 { - t.Error("It should be called twice") - } + assert.Nil(t, err) + + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestByPassingCDN(t *testing.T) { - var call int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - switch called := atomic.LoadInt64(&call); { - case called == 1: - validReqParams(t, fetchOptions, "") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 1, - Till: 2}, - }, nil - case called >= 2 && called <= 11: - validReqParams(t, fetchOptions, "") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil - case called == 12: - validReqParams(t, fetchOptions, "2") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 3, - Till: 3}, - }, nil - } - - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil - }, - } - - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 1, + Till: 2}, + }, nil).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2}, + }, nil).Times(10) + splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { + return *params.Till() == 2 + })).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 3, + Till: 3}, + }, nil).Once() + + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() splitStorage := mutexmap.NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) splitStorage.Update([]dtos.SplitDTO{{}}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Times(13).Return(-1) - ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(13).Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Times(13).Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(12).Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -468,70 +286,44 @@ func TestByPassingCDN(t *testing.T) { var till int64 = 3 _, err := splitUpdater.SynchronizeSplits(&till) - if err != nil { - t.Error("It should not return err") - } - if atomic.LoadInt64(&call) != 12 { - t.Error("It should be called twelve times instead of", atomic.LoadInt64(&call)) - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called twice instead of", atomic.LoadInt64(¬ifyEventCalled)) - } + assert.Nil(t, err) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestByPassingCDNLimit(t *testing.T) { - var call int64 - var notifyEventCalled int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - switch called := atomic.LoadInt64(&call); { - case called == 1: - validReqParams(t, fetchOptions, "") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 1, - Till: 2}, - }, nil - case called >= 2 && called <= 11: - validReqParams(t, fetchOptions, "") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil - case called >= 12: - validReqParams(t, fetchOptions, "2") - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil - } - - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil - }, - } - - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 1, + Till: 2}, + }, nil).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2}, + }, nil).Times(10) + splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { + return *params.Till() == 2 + })).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2}, + }, nil).Times(10) + + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() splitStorage := mutexmap.NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) splitStorage.Update([]dtos.SplitDTO{{}}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Times(22).Return(-1) - ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(22).Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Times(22).Return(int64(-1)) + ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Times(21).Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -541,38 +333,21 @@ func TestByPassingCDNLimit(t *testing.T) { var till int64 = 3 _, err := splitUpdater.SynchronizeSplits(&till) - if err != nil { - t.Error("It should not return err") - } - if atomic.LoadInt64(&call) != 21 { - t.Error("It should be called twenty one times instead of", atomic.LoadInt64(&call)) - } - if atomic.LoadInt64(¬ifyEventCalled) != 1 { - t.Error("It should be called twice instead of", atomic.LoadInt64(¬ifyEventCalled)) - } + assert.Nil(t, err) + + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestProcessFFChange(t *testing.T) { - var fetchCallCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - ffStorageMock := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return 43, nil - }, - } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCallCalled, 1) - return nil, nil - }, - } - + ffStorageMock := &mocks.SplitStorageMock{} + ffStorageMock.On("ChangeNumber").Return(int64(43), nil) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) - telemetryStorage, _ := inmemory.NewTelemetryStorage() - appMonitorMock := hcMock.MockApplicationMonitor{} - + appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -581,138 +356,73 @@ func TestProcessFFChange(t *testing.T) { result, _ := fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 12), nil, nil, )) - if result.RequiresFetch { - t.Error("should be false") - } - if atomic.LoadInt64(&fetchCallCalled) != 0 { - t.Error("Fetch should not be called") - } + assert.False(t, result.RequiresFetch) + splitMockFetcher.AssertExpectations(t) + ffStorageMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestAddOrUpdateFeatureFlagNil(t *testing.T) { - var fetchCallCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - ffStorageMock := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return -1, nil - }, - UpdateCall: func(toAdd, toRemove []dtos.SplitDTO, changeNumber int64) {}, - } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCallCalled, 1) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, - Since: 2, - Splits: []dtos.SplitDTO{}}, - }, nil - }, - } + ffStorageMock := &mocks.SplitStorageMock{} + ffStorageMock.On("ChangeNumber").Return(int64(-1), nil).Times(3) + ffStorageMock.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(-1).Once() + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, + Since: 2, + Splits: []dtos.SplitDTO{}}, + }, nil).Once() telemetryStorage, _ := inmemory.NewTelemetryStorage() - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } - + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) - fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, )) - if atomic.LoadInt64(&fetchCallCalled) != 1 { - t.Error("Fetch should be called once") - } + + ffStorageMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestAddOrUpdateFeatureFlagPcnEquals(t *testing.T) { - var fetchCallCalled int64 - var updateCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - ffStorageMock := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return 2, nil - }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - atomic.AddInt64(&updateCalled, 1) - if changeNumber != 4 { - t.Error("changenumber should be the one incomed from dto") - } - if len(toAdd) == 0 { - t.Error("toAdd should have a feature flag") - } - if len(toRemove) != 0 { - t.Error("toRemove shouldn't have a feature flag") - } - }, - } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCallCalled, 1) - return nil, nil - }, - } - + ffStorageMock := &mocks.SplitStorageMock{} + ffStorageMock.On("ChangeNumber").Return(int64(2), nil) + ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(4)) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) - telemetryStorage, _ := inmemory.NewTelemetryStorage() - appMonitorMock := hcMock.MockApplicationMonitor{} + appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) - featureFlag := dtos.SplitDTO{ChangeNumber: 4, Status: Active} - fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 4), common.Int64Ref(2), &featureFlag, )) - if atomic.LoadInt64(&fetchCallCalled) != 0 { - t.Error("It should not fetch splits") - } - if atomic.LoadInt64(&updateCalled) != 1 { - t.Error("It should update the storage") - } + ffStorageMock.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestAddOrUpdateFeatureFlagArchive(t *testing.T) { - var fetchCallCalled int64 - var updateCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - ffStorageMock := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return 2, nil - }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - atomic.AddInt64(&updateCalled, 1) - if changeNumber != 4 { - t.Error("changenumber should be the one incomed from dto") - } - if len(toRemove) == 0 { - t.Error("toRemove should have a feature flag") - } - if len(toAdd) != 0 { - t.Error("toAdd shouldn't have a feature flag") - } - }, - } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCallCalled, 1) - return nil, nil - }, - } - + ffStorageMock := &mocks.SplitStorageMock{} + ffStorageMock.On("ChangeNumber").Return(int64(2), nil).Once() + ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(4)).Return().Once() + splitMockFetcher := &fetcherMock.MockSplitFetcher{} ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) - telemetryStorage, _ := inmemory.NewTelemetryStorage() - appMonitorMock := hcMock.MockApplicationMonitor{} + appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, nil) fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) @@ -721,46 +431,30 @@ func TestAddOrUpdateFeatureFlagArchive(t *testing.T) { fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 4), common.Int64Ref(2), &featureFlag, )) - if atomic.LoadInt64(&fetchCallCalled) != 0 { - t.Error("It should not fetch splits") - } - if atomic.LoadInt64(&updateCalled) != 1 { - t.Error("It should update the storage") - } + + splitMockFetcher.AssertExpectations(t) + ffStorageMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { - var fetchCallCalled int64 - var updateCalled int64 logger := logging.NewLogger(&logging.LoggerOptions{}) - ffStorageMock := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { - return 0, errors.New("error geting change number") - }, - UpdateCall: func(toAdd, toRemove []dtos.SplitDTO, changeNumber int64) { - atomic.AddInt64(&updateCalled, 1) - if changeNumber != 2 { - t.Error("It should be 2") - } - }, - } - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&fetchCallCalled, 1) - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, - Since: 2, - Splits: []dtos.SplitDTO{}}, - }, nil - }, - } + ffStorageMock := &mocks.SplitStorageMock{} + ffStorageMock.On("ChangeNumber").Return(int64(0), errors.New("error geting change number")).Times(3) + ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(2)).Return().Once() + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, + Since: 2, + Splits: []dtos.SplitDTO{}}, + }, nil) telemetryStorage, _ := inmemory.NewTelemetryStorage() - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -770,120 +464,66 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, )) - if atomic.LoadInt64(&fetchCallCalled) != 1 { - t.Error("It should fetch splits") - } - if atomic.LoadInt64(&updateCalled) != 1 { - t.Error("It should update the storage") - } } func TestGetActiveFF(t *testing.T) { - var featureFlags []dtos.SplitDTO - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Active}) - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Active}) + featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Active}} featureFlagChanges := &dtos.SplitChangesDTO{FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) - - if len(actives) != 2 { - t.Error("active length should be 2") - } - - if len(inactives) != 0 { - t.Error("incative length should be 0") - } + assert.Len(t, actives, 2) + assert.Len(t, inactives, 0) } func TestGetInactiveFF(t *testing.T) { - var featureFlags []dtos.SplitDTO - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Archived}) - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Archived}) + featureFlags := []dtos.SplitDTO{{Status: Archived}, {Status: Archived}} featureFlagChanges := &dtos.SplitChangesDTO{FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) - - if len(actives) != 0 { - t.Error("active length should be 2") - } - - if len(inactives) != 2 { - t.Error("incative length should be 0") - } + assert.Len(t, actives, 0) + assert.Len(t, inactives, 2) } func TestGetActiveAndInactiveFF(t *testing.T) { - var featureFlags []dtos.SplitDTO - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Active}) - featureFlags = append(featureFlags, dtos.SplitDTO{Status: Archived}) + featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Archived}} featureFlagChanges := &dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) - - if len(actives) != 1 { - t.Error("active length should be 2") - } - - if len(inactives) != 1 { - t.Error("incative length should be 0") - } + assert.Len(t, actives, 1) + assert.Len(t, inactives, 1) } func TestSplitSyncWithSets(t *testing.T) { - var call int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set1", "set2"}} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set1"}} - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - switch call { - case 1: - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil - default: - t.Error("Wrong calls") - return nil, errors.New("some") - } - }, - } - - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3}, + }, nil).Once() + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() splitStorage := mutexmap.NewMMSplitStorage(flagsets.NewFlagSetFilter(nil)) splitStorage.Update([]dtos.SplitDTO{}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -891,63 +531,38 @@ func TestSplitSyncWithSets(t *testing.T) { splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter([]string{"set1", "set2", "set3"}), ruleBuilder) res, err := splitUpdater.SynchronizeSplits(nil) - if err != nil { - t.Error("It should not return err") - } - - if len(res.ReferencedSegments) != 0 { - t.Error("invalid referenced segment names. Got: ", res.ReferencedSegments) - } - - if splitStorage.Split("split1") == nil { - t.Error("split1 should be present") - } - if splitStorage.Split("split2") != nil { - t.Error("split2 should not be present") - } - if splitStorage.Split("split3") == nil { - t.Error("split3 should be present") - } + assert.Nil(t, err) + assert.Len(t, res.ReferencedSegments, 0) + assert.NotNil(t, splitStorage.Split("split1")) + assert.Nil(t, splitStorage.Split("split2")) + assert.NotNil(t, splitStorage.Split("split3")) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestSplitSyncWithSetsInConfig(t *testing.T) { - var call int64 mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set1"}} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set2"}} mockedSplit4 := dtos.SplitDTO{Name: "split4", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set2"}} - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - switch call { - case 1: - if fetchOptions.ChangeNumber() != -1 { - t.Error("Wrong changenumber passed") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, - Since: 3, - Till: 3}, - }, nil - default: - t.Error("Wrong calls") - return nil, errors.New("some") - } - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, + Since: 3, + Till: 3}, + }, nil).Once() - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() flagSetFilter := flagsets.NewFlagSetFilter([]string{"set2", "set4"}) splitStorage := mutexmap.NewMMSplitStorage(flagSetFilter) splitStorage.Update([]dtos.SplitDTO{}, nil, -1) telemetryStorage, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -955,65 +570,31 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagSetFilter, ruleBuilder) res, err := splitUpdater.SynchronizeSplits(nil) - if err != nil { - t.Error("It should not return err") - } - - if len(res.ReferencedSegments) != 0 { - t.Error("invalid referenced segment names. Got: ", res.ReferencedSegments) - } - - s1 := splitStorage.Split("split1") - if s1 != nil { - t.Error("split1 should not be present") - } - s2 := splitStorage.Split("split2") - if s2 == nil { - t.Error("split2 should be present") - } - s3 := splitStorage.Split("split3") - if s3 == nil { - t.Error("split3 should be present") - } - s4 := splitStorage.Split("split4") - if s4 == nil { - t.Error("split4 should be present") - } + assert.Nil(t, err) + assert.Len(t, res.ReferencedSegments, 0) + assert.Nil(t, splitStorage.Split("split1")) + assert.NotNil(t, splitStorage.Split("split2")) + assert.NotNil(t, splitStorage.Split("split3")) + assert.NotNil(t, splitStorage.Split("split4")) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) } func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Mock split storage with higher change number - currentSince := int64(100) - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return currentSince, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) {}, - } + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(100), nil) + splitMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Return() // Mock rule based segment storage with higher change number - currentRBSince := int64(150) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int(currentRBSince)) + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(150)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Return() // Mock fetcher - var fetchCalled bool - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(requestParams *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - fetchCalled = true - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: currentSince, - Till: currentSince, - Splits: []dtos.SplitDTO{}, - }, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ - Since: currentRBSince, - Till: currentRBSince, - RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, - }, - }, nil - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} // Mock telemetry storage telemetryMockStorage := mocks.MockTelemetryStorage{ @@ -1022,9 +603,8 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { } // Mock app monitor - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) // Create split updater @@ -1042,223 +622,152 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 1: till is less than both currentSince and currentRBSince till := int64(50) result, err := splitUpdater.SynchronizeSplits(&till) - - if err != nil { - t.Error("Expected no error, got:", err) - } - - if result == nil { - t.Error("Expected non-nil result") - } - - if fetchCalled { - t.Error("Fetcher should not have been called when till is less than both currentSince and currentRBSince") - } + assert.Nil(t, err) + assert.NotNil(t, result) + assert.Equal(t, &UpdateResult{}, result) // Test case 2: till is equal to currentSince but less than currentRBSince - till = currentSince + till = 100 + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Since: 100, + Till: 100, + Splits: []dtos.SplitDTO{}, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + Since: 150, + Till: 150, + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + }, + }, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) - - if err != nil { - t.Error("Expected no error when till equals currentSince, got:", err) - } - - if !fetchCalled { - t.Error("Fetcher should have been called when till equals currentSince (since currentRBSince is higher)") - } + assert.Nil(t, err) + assert.NotNil(t, result) + assert.Equal(t, int64(100), result.NewChangeNumber) + assert.Equal(t, int64(150), result.NewRBChangeNumber) // Test case 3: till is equal to currentRBSince but greater than currentSince - till = currentRBSince + till = 150 + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Since: 100, + Till: 100, + Splits: []dtos.SplitDTO{}, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + Since: 150, + Till: 150, + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + }, + }, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) - - if err != nil { - t.Error("Expected no error when till equals currentRBSince, got:", err) - } - - if !fetchCalled { - t.Error("Fetcher should have been called when till equals currentRBSince") - } + assert.Nil(t, err) + assert.NotNil(t, result) + assert.Equal(t, int64(100), result.NewChangeNumber) + assert.Equal(t, int64(150), result.NewRBChangeNumber) + + splitMockFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) } func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { - // Mock rule based segment storage with testify/mock - ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - - // Mock split storage - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return 200, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) {}, - AllCall: func() []dtos.SplitDTO { return []dtos.SplitDTO{} }, - } - - // Mock fetcher - var fetchCalled bool - var fetchCount int - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(requestParams *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - fetchCalled = true - fetchCount++ - if fetchCount == 1 { - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: 100, - Till: 200, - Splits: []dtos.SplitDTO{}, + t.Run("Rule-based segment change number lower than current", func(t *testing.T) { + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(200), nil).Times(1) + + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, + RecordSuccessfulSyncCall: func(resource int, timestamp time.Time) {}, + RecordSyncErrorCall: func(resource, status int) {}, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() + + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + + lowerChangeNumber := int64(100) + ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ + Name: "test-segment", + ChangeNumber: lowerChangeNumber, + Conditions: []dtos.RuleBasedConditionDTO{ + { + ConditionType: "WHITELIST", + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{}, }, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ - Since: 100, - Till: 200, - RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, - }, - }, nil - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: 200, - Till: 200, - Splits: []dtos.SplitDTO{}, - }, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ - Since: 200, - Till: 200, - RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, - }, - }, nil - }, - } - - // Mock telemetry storage - telemetryMockStorage := mocks.MockTelemetryStorage{ - RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, - RecordSuccessfulSyncCall: func(resource int, timestamp time.Time) {}, - RecordSyncErrorCall: func(resource, status int) {}, - } - - // Mock app monitor - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) {}, - } - - largeSegmentStorage := &mocks.MockLargeSegmentStorage{} - ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - - // Create split updater - splitUpdater := NewSplitUpdater( - splitMockStorage, - ruleBasedSegmentMockStorage, - splitMockFetcher, - logging.NewLogger(&logging.LoggerOptions{}), - telemetryMockStorage, - appMonitorMock, - flagsets.NewFlagSetFilter(nil), - ruleBuilder, - ) - - // Test case 1: When rule-based segment change number is lower than current - lowerChangeNumber := int64(100) - ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ - Name: "test-segment", - ChangeNumber: lowerChangeNumber, - Conditions: []dtos.RuleBasedConditionDTO{ - { - ConditionType: "WHITELIST", - MatcherGroup: dtos.MatcherGroupDTO{ - Matchers: []dtos.MatcherDTO{}, }, }, - }, - } - baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") - baseUpdate := dtos.NewBaseUpdate(baseMessage, lowerChangeNumber) - ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, nil, ruleBasedSegment) - - // Reset fetchCalled - fetchCalled = false - - // Set up expectations for the first test case - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int(200)) - ruleBasedSegmentMockStorage.On("Update", - mock.MatchedBy(func(toAdd []dtos.RuleBasedSegmentDTO) bool { return len(toAdd) == 0 }), - mock.MatchedBy(func(toRemove []dtos.RuleBasedSegmentDTO) bool { return len(toRemove) == 0 }), - int64(200)).Return() - - result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) - - if err != nil { - t.Error("Expected no error, got:", err) - } - - if result.RequiresFetch { - t.Error("Expected RequiresFetch to be false when change number is lower than current") - } - - if fetchCalled { - t.Error("Fetcher should not have been called when change number is lower than current") - } - - // Test case 2: When rule-based segment change number is higher than current - higherChangeNumber := int64(300) - ruleBasedSegment = &dtos.RuleBasedSegmentDTO{ - Name: "test-segment", - ChangeNumber: higherChangeNumber, - Conditions: []dtos.RuleBasedConditionDTO{ - { - ConditionType: "WHITELIST", - MatcherGroup: dtos.MatcherGroupDTO{ - Matchers: []dtos.MatcherDTO{}, + } + baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") + baseUpdate := dtos.NewBaseUpdate(baseMessage, lowerChangeNumber) + ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, nil, ruleBasedSegment) + + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200)).Times(2) + + result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) + assert.Nil(t, err) + assert.False(t, result.RequiresFetch) + splitMockFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) + + t.Run("Rule-based segment change number higher than current", func(t *testing.T) { + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, + RecordSuccessfulSyncCall: func(resource int, timestamp time.Time) {}, + RecordSyncErrorCall: func(resource, status int) {}, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + + changeNumber := int64(300) + ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ + Name: "test-segment", + ChangeNumber: changeNumber, + Conditions: []dtos.RuleBasedConditionDTO{ + { + ConditionType: "WHITELIST", + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{}, + }, }, }, - }, - } - baseMessage = dtos.NewBaseMessage(time.Now().Unix(), "test-channel") - baseUpdate = dtos.NewBaseUpdate(baseMessage, higherChangeNumber) - ffChange = *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, nil, ruleBasedSegment) - - // Reset fetchCalled - fetchCalled = false - - // Set up expectations for the second test case - ruleBasedSegmentMockStorage = &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int(100)) - ruleBasedSegmentMockStorage.On("Update", - mock.MatchedBy(func(toAdd []dtos.RuleBasedSegmentDTO) bool { - return len(toAdd) == 1 && toAdd[0].ChangeNumber == higherChangeNumber - }), - mock.MatchedBy(func(toRemove []dtos.RuleBasedSegmentDTO) bool { return len(toRemove) == 0 }), - higherChangeNumber).Return() - - // Create a new split updater for the second test case - splitUpdater = NewSplitUpdater( - splitMockStorage, - ruleBasedSegmentMockStorage, - splitMockFetcher, - logging.NewLogger(&logging.LoggerOptions{}), - telemetryMockStorage, - appMonitorMock, - flagsets.NewFlagSetFilter(nil), - ruleBuilder, - ) - - result, err = splitUpdater.SynchronizeFeatureFlags(&ffChange) - - if err != nil { - t.Error("Expected no error, got:", err) - } - - if result.RequiresFetch { - t.Error("Expected RequiresFetch to be false when change number is higher than current") - } - - if fetchCalled { - t.Error("Fetcher should not have been called when change number is higher than current") - } - - if result.NewChangeNumber != higherChangeNumber { - t.Errorf("Expected NewChangeNumber to be %d, got %d", higherChangeNumber, result.NewChangeNumber) - } - - // Verify that the rule-based segment storage was updated with the higher change number - ruleBasedSegmentMockStorage.AssertCalled(t, "Update", mock.Anything, mock.Anything, higherChangeNumber) + } + baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") + baseUpdate := dtos.NewBaseUpdate(baseMessage, changeNumber) + ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, nil, ruleBasedSegment) + + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200)).Once() + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{*ruleBasedSegment}, []dtos.RuleBasedSegmentDTO{}, changeNumber).Return().Once() + + result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) + assert.Nil(t, err) + assert.False(t, result.RequiresFetch) + assert.Equal(t, changeNumber, result.NewRBChangeNumber) + + splitMockFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) } func TestProcessMatchers(t *testing.T) { @@ -1267,7 +776,7 @@ func TestProcessMatchers(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) splitChange := &dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Till: 1, Since: 1, Splits: []dtos.SplitDTO{ { @@ -1302,18 +811,8 @@ func TestProcessMatchers(t *testing.T) { }, }}} toAdd, _ := splitUpdater.processFeatureFlagChanges(splitChange) - - if toAdd[0].Conditions[0].ConditionType != grammar.ConditionTypeWhitelist { - t.Error("ConditionType should be WHITELIST") - } - if toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeAllKeys { - t.Error("MatcherType should be ALL_KEYS") - } - - if toAdd[1].Conditions[0].ConditionType != grammar.ConditionTypeRollout { - t.Error("ConditionType should be ROLLOUT") - } - if toAdd[1].Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeAllKeys { - t.Error("MatcherType should be ALL_KEYS") - } + assert.Equal(t, grammar.ConditionTypeWhitelist, toAdd[0].Conditions[0].ConditionType) + assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) + assert.Equal(t, grammar.ConditionTypeRollout, toAdd[1].Conditions[0].ConditionType) + assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[1].Conditions[0].MatcherGroup.Matchers[0].MatcherType) } diff --git a/tasks/largesegmentsync_test.go b/tasks/largesegmentsync_test.go index df860b1b..58e2ef76 100644 --- a/tasks/largesegmentsync_test.go +++ b/tasks/largesegmentsync_test.go @@ -1,56 +1,41 @@ package tasks import ( - "sync/atomic" "testing" "time" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" syncMocks "github.com/splitio/go-split-commons/v7/synchronizer/mocks" + "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" ) func TestLargeSegmentSyncTaskHappyPath(t *testing.T) { - var updater syncMocks.LargeSegmentUpdaterMock + updater := &syncMocks.LargeSegmentUpdaterMock{} updater.On("SynchronizeLargeSegment", "ls1", (*int64)(nil)).Return(nil).Once() updater.On("SynchronizeLargeSegment", "ls2", (*int64)(nil)).Return(nil).Once() updater.On("SynchronizeLargeSegment", "ls3", (*int64)(nil)).Return(nil).Once() - var lsNamesCall int64 - splitSorage := mocks.MockSplitStorage{ - LargeSegmentNamesCall: func() *set.ThreadUnsafeSet { - atomic.AddInt64(&lsNamesCall, 1) - return set.NewSet("ls1", "ls2", "ls3") - }, - } - - var notifyEventCalled int64 - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } - task := NewFetchLargeSegmentsTask(&updater, splitSorage, 1, 10, 10, logging.NewLogger(&logging.LoggerOptions{}), appMonitorMock) + splitSorage := &mocks.SplitStorageMock{} + splitSorage.On("LargeSegmentNames").Return(set.NewSet("ls1", "ls2", "ls3")).Once() + + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything) + task := NewFetchLargeSegmentsTask(updater, splitSorage, 2, 10, 10, logging.NewLogger(&logging.LoggerOptions{}), appMonitorMock) task.Start() time.Sleep(3 * time.Second) - if !task.IsRunning() { - t.Error("Large Segment fetching task should be running") - } + assert.True(t, task.IsRunning(), "Large Segment fetching task should be running") task.Stop(true) - if task.IsRunning() { - t.Error("Large Segment fetching task should be stopped") - } - - if lsNamesCall != 2 { - t.Error("Large Segment Call should be 2. Actual: ", lsNamesCall) - } - if atomic.LoadInt64(¬ifyEventCalled) < 1 { - t.Error("It should be called at least once") - } + assert.False(t, task.IsRunning(), "Large Segment fetching task should be stopped") + splitSorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) updater.AssertExpectations(t) } diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8cb304bc..8481d04f 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -1,8 +1,6 @@ package tasks import ( - "net/http" - "sync/atomic" "testing" "time" @@ -10,12 +8,13 @@ import ( "github.com/splitio/go-split-commons/v7/engine/grammar" "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" "github.com/splitio/go-split-commons/v7/telemetry" "github.com/splitio/go-toolkit/v5/logging" + + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -29,58 +28,20 @@ var goClientRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar grammar.MatcherTypeInRuleBasedSegment} func TestSplitSyncTask(t *testing.T) { - var call int64 - var notifyEventCalled int64 - mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: true, Status: "INACTIVE", TrafficTypeName: "one"} - splitMockStorage := mocks.MockSplitStorage{ - ChangeNumberCall: func() (int64, error) { return -1, nil }, - UpdateCall: func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) { - if changeNumber != 3 { - t.Error("Wrong changenumber") - } - if len(toAdd) != 2 { - t.Error("Wrong length of passed splits") - } - s1 := toAdd[0] - if s1.Name != "split1" || s1.Killed { - t.Error("split1 stored/retrieved incorrectly") - t.Error(s1) - } - s2 := toAdd[1] - if s2.Name != "split2" || !s2.Killed { - t.Error("split2 stored/retrieved incorrectly") - t.Error(s2) - } - }, - RemoveCall: func(splitname string) { - if splitname != "split3" { - t.Error("It should remove split3") - } - }, - } + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) + splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() - splitMockFetcher := fetcherMock.MockSplitFetcher{ - FetchCall: func(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - atomic.AddInt64(&call, 1) - req, _ := http.NewRequest("GET", "test", nil) - fetchOptions.Apply(req) - if req.Header.Get("Cache-Control") != "no-cache" { - t.Error("Wrong header") - } - if req.URL.Query().Get("since") != "-1" { - t.Error("Wrong since") - } - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil - }, - } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3}, + }, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSuccessfulSyncCall: func(resource int, tm time.Time) { @@ -95,14 +56,11 @@ func TestSplitSyncTask(t *testing.T) { }, } - appMonitorMock := hcMock.MockApplicationMonitor{ - NotifyEventCall: func(counterType int) { - atomic.AddInt64(¬ifyEventCalled, 1) - }, - } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(-1) + ruleBasedSegmentMockStorage.On("ChangeNumber").Twice().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -116,19 +74,13 @@ func TestSplitSyncTask(t *testing.T) { splitTask.Start() time.Sleep(2 * time.Second) - if !splitTask.IsRunning() { - t.Error("Split fetching task should be running") - } + assert.True(t, splitTask.IsRunning(), "Split fetching task should be running") splitTask.Stop(false) - if atomic.LoadInt64(&call) < 1 { - t.Error("Request not received") - } + assert.False(t, splitTask.IsRunning(), "Split fetching task should be stopped") - if splitTask.IsRunning() { - t.Error("Task should be stopped") - } - if atomic.LoadInt64(¬ifyEventCalled) < 1 { - t.Error("It should be called at least once") - } + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) } From fc10566ba0522af84298c06dd29fa70962cd7b88 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 3 Oct 2025 14:09:23 -0300 Subject: [PATCH 05/39] fixed test --- synchronizer/synchronizer_test.go | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 6b9d58fe..534e5893 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -34,17 +34,6 @@ import ( "github.com/splitio/go-toolkit/v5/logging" ) -// func createSplitUpdater(splitMockStorage storageMock.MockSplitStorage, splitAPI api.SplitAPI, logger logging.LoggerInterface, telemetryMockStorage storageMock.MockTelemetryStorage, appMonitorMock hcMock.MockApplicationMonitor) split.Updater { -// ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} -// ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(-1) -// ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) - -// largeSegmentStorage := &mocks.MockLargeSegmentStorage{} -// ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) -// splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) -// return splitUpdater -// } - func validReqParams(t *testing.T, fetchOptions service.RequestParams) { req, _ := http.NewRequest("GET", "test", nil) fetchOptions.Apply(req) @@ -268,7 +257,7 @@ func TestPeriodicFetching(t *testing.T) { FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, Since: 3, Till: 3}, - }).Once() + }, nil).Once() splitAPI := api.SplitAPI{ SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ @@ -290,7 +279,7 @@ func TestPeriodicFetching(t *testing.T) { } splitMockStorage := &storageMock.SplitStorageMock{} splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) - // splitMockStorage.On("Update", mock.Anything, []dtos.SplitDTO{}, int64(3)).Return().Twice() + splitMockStorage.On("Update", mock.Anything, []dtos.SplitDTO{}, int64(3)).Return().Once() splitMockStorage.On("SegmentNames").Return(set.NewSet("segment1", "segment2")).Twice() segmentMockStorage := storageMock.MockSegmentStorage{ ChangeNumberCall: func(segmentName string) (int64, error) { return -1, nil }, @@ -320,18 +309,12 @@ func TestPeriodicFetching(t *testing.T) { splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ - SplitUpdater: splitUpdater, - SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), - EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), - ImpressionRecorder: impression.NewRecorderSingle(storageMock.MockImpressionStorage{}, splitAPI.ImpressionRecorder, logger, dtos.Metadata{}, conf.ImpressionsModeDebug, telemetryMockStorage), - TelemetryRecorder: telemetry.NewTelemetrySynchronizer(telemetryMockStorage, nil, nil, nil, nil, dtos.Metadata{}, telemetryMockStorage), + SplitUpdater: splitUpdater, + SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), } splitTasks := SplitTasks{ - EventSyncTask: tasks.NewRecordEventsTask(workers.EventRecorder, advanced.EventsBulkSize, 1, logger), - ImpressionSyncTask: tasks.NewRecordImpressionsTask(workers.ImpressionRecorder, 1, logger, advanced.ImpressionsBulkSize), - SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentUpdater, 1, advanced.SegmentWorkers, advanced.SegmentQueueSize, logger, appMonitorMock), - SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), - TelemetrySyncTask: tasks.NewRecordTelemetryTask(workers.TelemetryRecorder, 10, logger), + SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentUpdater, 1, advanced.SegmentWorkers, advanced.SegmentQueueSize, logger, appMonitorMock), + SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), } syncForTest := NewSynchronizer(advanced, splitTasks, workers, logger, nil) syncForTest.StartPeriodicFetching() From 752196080ba7f290b1fb3ff7ea64b60d01ba0cbf Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 3 Oct 2025 14:31:34 -0300 Subject: [PATCH 06/39] fixed pop test --- synchronizer/synchronizer_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 534e5893..539470fd 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -367,7 +367,7 @@ func TestPeriodicRecording(t *testing.T) { Treatment: "someTreatment", }}, nil }, - EmptyCall: func() bool { return atomic.LoadInt64(&impressionsCalled) >= 3 }, + EmptyCall: func() bool { return atomic.LoadInt64(&impressionsCalled) != 1 }, } eventMockStorage := storageMock.MockEventStorage{ PopNCall: func(n int64) ([]dtos.EventDTO, error) { @@ -381,7 +381,7 @@ func TestPeriodicRecording(t *testing.T) { Value: nil, }}, nil }, - EmptyCall: func() bool { return atomic.LoadInt64(&eventsCalled) >= 4 }, + EmptyCall: func() bool { return atomic.LoadInt64(&eventsCalled) != 1 }, } telemetryMockStorage := storageMock.MockTelemetryStorage{ PopLatenciesCall: func() dtos.MethodLatencies { return dtos.MethodLatencies{} }, From ef4bc94838a07e1f6c7523c66a43297522255917 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 6 Oct 2025 17:39:10 -0300 Subject: [PATCH 07/39] decoupled logic --- synchronizer/worker/split/split.go | 74 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 6c149b09..dd106087 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -114,6 +114,48 @@ func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges *dtos.SplitChangesDTO) return segments } +type fetchResult struct { + segmentReferences []string + largeSegmentReferences []string + updatedSplitNames []string + ffCurrentSince int64 + rbCurrentSince int64 + ffSince int64 + rbSince int64 +} + +func (s *UpdaterImpl) performFetch(fetchOptions *service.FlagRequestParams) (fetchResult, error) { + currentSince, _ := s.splitStorage.ChangeNumber() + currentRBSince := s.ruleBasedSegmentStorage.ChangeNumber() + before := time.Now() + splitChanges, err := s.splitFetcher.Fetch(fetchOptions.WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + if err != nil { + if httpError, ok := err.(*dtos.HTTPError); ok { + if httpError.Code == scRequestURITooLong { + s.logger.Error("SDK Initialization, the amount of flag sets provided are big causing uri length error.") + } + s.runtimeTelemetry.RecordSyncError(telemetry.SplitSync, httpError.Code) + } + return fetchResult{ + ffCurrentSince: currentSince, + rbCurrentSince: currentRBSince, + }, err + } + s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) + s.processUpdate(splitChanges) + segmentReferences := s.processRuleBasedUpdate(splitChanges) + segmentReferences = appendSegmentNames(segmentReferences, splitChanges) + return fetchResult{ + segmentReferences: segmentReferences, + largeSegmentReferences: appendLargeSegmentNames([]string{}, splitChanges), + updatedSplitNames: appendSplitNames([]string{}, splitChanges), + ffCurrentSince: splitChanges.FeatureFlags.Till, + rbCurrentSince: splitChanges.RuleBasedSegments.Till, + ffSince: splitChanges.FeatureFlags.Since, + rbSince: splitChanges.RuleBasedSegments.Since, + }, nil +} + // fetchUntil Hit endpoint, update storage and return when since==till. func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*UpdateResult, error) { // just guessing sizes so the we don't realloc immediately @@ -121,33 +163,17 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda updatedSplitNames := make([]string, 0, 10) largeSegmentReferences := make([]string, 0, 10) var err error - var currentSince int64 - var currentRBSince int64 + var fetchResult fetchResult for { // Fetch until since==till - currentSince, _ = s.splitStorage.ChangeNumber() - currentRBSince = s.ruleBasedSegmentStorage.ChangeNumber() - before := time.Now() - var splitChanges *dtos.SplitChangesDTO - splitChanges, err = s.splitFetcher.Fetch(fetchOptions.WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + fetchResult, err = s.performFetch(fetchOptions) if err != nil { - if httpError, ok := err.(*dtos.HTTPError); ok { - if httpError.Code == scRequestURITooLong { - s.logger.Error("SDK Initialization, the amount of flag sets provided are big causing uri length error.") - } - s.runtimeTelemetry.RecordSyncError(telemetry.SplitSync, httpError.Code) - } break } - currentSince = splitChanges.FeatureFlags.Till - currentRBSince = splitChanges.RuleBasedSegments.Till - s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) - s.processUpdate(splitChanges) - segmentReferences = s.processRuleBasedUpdate(splitChanges) - segmentReferences = appendSegmentNames(segmentReferences, splitChanges) - updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges) - largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges) - if currentSince == splitChanges.FeatureFlags.Since && currentRBSince == splitChanges.RuleBasedSegments.Since { + segmentReferences = append(segmentReferences, fetchResult.segmentReferences...) + largeSegmentReferences = append(largeSegmentReferences, fetchResult.largeSegmentReferences...) + updatedSplitNames = append(updatedSplitNames, fetchResult.updatedSplitNames...) + if fetchResult.ffCurrentSince == fetchResult.ffSince && fetchResult.rbCurrentSince == fetchResult.rbSince { s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC()) break } @@ -155,8 +181,8 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda return &UpdateResult{ UpdatedSplits: common.DedupeStringSlice(updatedSplitNames), ReferencedSegments: common.DedupeStringSlice(segmentReferences), - NewChangeNumber: currentSince, - NewRBChangeNumber: currentRBSince, + NewChangeNumber: fetchResult.ffCurrentSince, + NewRBChangeNumber: fetchResult.rbCurrentSince, ReferencedLargeSegments: common.DedupeStringSlice(largeSegmentReferences), }, err } From b8df5632151d2ddf21e6398bc0b75754de56bcaf Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 7 Oct 2025 14:47:35 -0300 Subject: [PATCH 08/39] Add response interface for split change --- .vscode/launch.json | 7 + dtos/split.go | 6 + dtos/splitchangewrapper.go | 163 ++++++++++++++++ service/api/http_fetchers.go | 14 +- service/api/http_fetchers_test.go | 75 +++++++- service/interfaces.go | 2 +- service/local/sanitizer.go | 32 ++-- service/local/splitFetcher.go | 46 +++-- service/local/splitFetcher_test.go | 190 +++++++++---------- service/mocks/split.go | 4 +- synchronizer/local_test.go | 19 +- synchronizer/synchronizer_test.go | 29 ++- synchronizer/worker/split/split.go | 76 ++++---- synchronizer/worker/split/split_test.go | 236 +++++++++++------------- tasks/splitsync_test.go | 9 +- testdata/old_splits_mock.json | 5 + 16 files changed, 567 insertions(+), 346 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 dtos/splitchangewrapper.go create mode 100644 testdata/old_splits_mock.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..5c7247b4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/dtos/split.go b/dtos/split.go index 6b8dc6e0..bc567f43 100644 --- a/dtos/split.go +++ b/dtos/split.go @@ -16,6 +16,12 @@ type FeatureFlagsDTO struct { Splits []SplitDTO `json:"d"` } +type SplitsDTO struct { + Since int64 `json:"since"` + Till int64 `json:"till"` + Splits []SplitDTO `json:"splits"` +} + type RuleBasedSegmentsDTO struct { Since int64 `json:"s"` Till int64 `json:"t"` diff --git a/dtos/splitchangewrapper.go b/dtos/splitchangewrapper.go new file mode 100644 index 00000000..915fb8b8 --- /dev/null +++ b/dtos/splitchangewrapper.go @@ -0,0 +1,163 @@ +package dtos + +import ( + "encoding/json" +) + +type FFResponse interface { + NeedsAnotherFetch() bool + RuleBasedSegments() []RuleBasedSegmentDTO + FeatureFlags() []SplitDTO + FFTill() int64 + RBTill() int64 + FFSince() int64 + RBSince() int64 + SetFFTill(till int64) + SetFFSince(since int64) + SetRBTill(till int64) + SetRBSince(since int64) + ReplaceFF(featureFlags []SplitDTO) + ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) +} + +type FFResponseV12 struct { + SplitChanges SplitsDTO +} + +func NewFFResponseV12(data []byte) (FFResponse, error) { + var splitChangesDto SplitsDTO + err := json.Unmarshal(data, &splitChangesDto) + if err == nil { + return &FFResponseV12{ + SplitChanges: splitChangesDto, + }, nil + } + return nil, err +} + +func (f12 *FFResponseV12) NeedsAnotherFetch() bool { + return f12.SplitChanges.Since == f12.SplitChanges.Till +} + +func (f12 *FFResponseV12) FeatureFlags() []SplitDTO { + return f12.SplitChanges.Splits +} + +func (wf12 *FFResponseV12) RuleBasedSegments() []RuleBasedSegmentDTO { + return []RuleBasedSegmentDTO{} +} + +func (f12 *FFResponseV12) FFTill() int64 { + return f12.SplitChanges.Till +} + +func (f12 *FFResponseV12) RBTill() int64 { + return 0 +} + +func (f12 *FFResponseV12) FFSince() int64 { + return f12.FFSince() +} + +func (f12 *FFResponseV12) RBSince() int64 { + return 0 +} + +func (f12 *FFResponseV12) SetFFTill(till int64) { + f12.SplitChanges.Till = till +} + +func (f12 *FFResponseV12) SetFFSince(since int64) { + f12.SplitChanges.Since = since +} + +func (f12 *FFResponseV12) SetRBTill(till int64) { + //no op +} + +func (f12 *FFResponseV12) SetRBSince(since int64) { + //no op +} + +func (f12 *FFResponseV12) ReplaceFF(featureFlags []SplitDTO) { + f12.SplitChanges.Splits = featureFlags +} + +func (f12 *FFResponseV12) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { + //no op +} + +type FFResponseV13 struct { + SplitChanges SplitChangesDTO +} + +func NewFFResponseV13(data []byte) (FFResponse, error) { + var splitChangesDto SplitChangesDTO + err := json.Unmarshal(data, &splitChangesDto) + if err == nil { + return &FFResponseV13{ + SplitChanges: splitChangesDto, + }, nil + } + return nil, err +} + +func NewFFResponseWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO) FFResponse { + featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs}, + RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs}} + return &FFResponseV13{ + SplitChanges: featureFlagChange, + } +} + +func (f13 *FFResponseV13) FeatureFlags() []SplitDTO { + return f13.SplitChanges.FeatureFlags.Splits +} + +func (f13 *FFResponseV13) RuleBasedSegments() []RuleBasedSegmentDTO { + return f13.SplitChanges.RuleBasedSegments.RuleBasedSegments +} + +func (f13 FFResponseV13) NeedsAnotherFetch() bool { + return f13.SplitChanges.FeatureFlags.Since == f13.SplitChanges.FeatureFlags.Till && f13.SplitChanges.RuleBasedSegments.Since == f13.SplitChanges.RuleBasedSegments.Till +} + +func (f13 *FFResponseV13) FFTill() int64 { + return f13.SplitChanges.FeatureFlags.Till +} + +func (f13 *FFResponseV13) RBTill() int64 { + return f13.SplitChanges.RuleBasedSegments.Till +} + +func (f13 *FFResponseV13) RBSince() int64 { + return f13.SplitChanges.RuleBasedSegments.Since +} + +func (f13 *FFResponseV13) SetFFTill(till int64) { + f13.SplitChanges.FeatureFlags.Till = till +} + +func (f13 *FFResponseV13) SetFFSince(since int64) { + f13.SplitChanges.FeatureFlags.Since = since +} + +func (f13 *FFResponseV13) SetRBTill(till int64) { + f13.SplitChanges.RuleBasedSegments.Till = till +} + +func (f13 *FFResponseV13) FFSince() int64 { + return f13.SplitChanges.FeatureFlags.Since +} + +func (f13 *FFResponseV13) SetRBSince(since int64) { + f13.SplitChanges.RuleBasedSegments.Since = since +} + +func (f13 *FFResponseV13) ReplaceFF(featureFlags []SplitDTO) { + f13.SplitChanges.FeatureFlags.Splits = featureFlags +} + +func (f13 *FFResponseV13) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { + f13.SplitChanges.RuleBasedSegments.RuleBasedSegments = ruleBasedSegments +} diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 630e0607..c6bdcf1b 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -11,6 +11,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) @@ -47,7 +48,7 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. } // Fetch makes an http call to the split backend and returns the list of updated splits -func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { +func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos.FFResponse, error) { fetchOptions.WithFlagSetsFilter(f.flagSetsFilter).WithSpecVersion(f.specVersion) data, err := f.fetchRaw("/splitChanges", fetchOptions) if err != nil { @@ -55,14 +56,19 @@ func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos return nil, err } - var splitChangesDto dtos.SplitChangesDTO - err = json.Unmarshal(data, &splitChangesDto) + var splitChangesDto dtos.FFResponse + + if common.StringFromRef(f.specVersion) == specs.FLAG_V1_3 { + splitChangesDto, err = dtos.NewFFResponseV13(data) + } else { + splitChangesDto, err = dtos.NewFFResponseV12(data) + } if err != nil { f.logger.Error("Error parsing split changes JSON ", err) return nil, err } - return &splitChangesDto, nil + return splitChangesDto, nil } // HTTPSegmentFetcher struct is responsible for fetching segment by name from the API via HTTP method diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index 0d380bdb..ce654114 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -21,10 +21,11 @@ import ( ) var splitsMock, _ = ioutil.ReadFile("../../testdata/splits_mock.json") +var oldSplitMock, _ = ioutil.ReadFile("../../testdata/old_splits_mock.json") var splitMock, _ = ioutil.ReadFile("../../testdata/split_mock.json") var segmentMock, _ = ioutil.ReadFile("../../testdata/segment_mock.json") -func TestSpitChangesFetch(t *testing.T) { +func TestSpitChangesFetch11(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -46,7 +47,7 @@ func TestSpitChangesFetch(t *testing.T) { if r.URL.RawQuery != "s=1.1&since=123456&rbSince=123456" { t.Error("wrong query params") } - fmt.Fprintln(w, fmt.Sprintf(string(splitsMock), splitMock)) + fmt.Fprintln(w, fmt.Sprintf(string(oldSplitMock), splitMock)) })) defer ts.Close() @@ -66,20 +67,80 @@ func TestSpitChangesFetch(t *testing.T) { t.Error(err) } - if splitChangesDTO.FeatureFlags.Till != 1491244291288 || - splitChangesDTO.FeatureFlags.Splits[0].Name != "DEMO_MURMUR2" { + if splitChangesDTO.FFTill() != 1491244291288 || + splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2" { + t.Error("DTO mal formed") + } + + if splitChangesDTO.FeatureFlags()[0].Configurations == nil { + t.Error("DTO mal formed") + } + + if splitChangesDTO.FeatureFlags()[0].Configurations["of"] != "" { + t.Error("DTO mal formed") + } + + if splitChangesDTO.FeatureFlags()[0].Configurations["on"] != "{\"color\": \"blue\",\"size\": 13}" { + t.Error("DTO mal formed") + } +} + +func TestSpitChangesFetch(t *testing.T) { + logger := logging.NewLogger(&logging.LoggerOptions{}) + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get(CacheControlHeader) != CacheControlNoCache { + t.Error("wrong cache control header") + } + if r.URL.Query().Get("since") != "123456" { + t.Error("wrong since") + } + if r.URL.Query().Get("till") != "" { + t.Error("wrong till") + } + if r.URL.Query().Get("sets") != "" { + t.Error("wrong sets") + } + if r.URL.Query().Get("s") != specs.FLAG_V1_3 { + t.Error("wrong spec") + } + if r.URL.RawQuery != "s=1.3&since=123456&rbSince=123456" { + t.Error("wrong query params") + } + fmt.Fprintln(w, fmt.Sprintf(string(splitsMock), splitMock)) + })) + defer ts.Close() + + splitFetcher := NewHTTPSplitFetcher( + "", + conf.AdvancedConfig{ + EventsURL: ts.URL, + SdkURL: ts.URL, + FlagsSpecVersion: specs.FLAG_V1_3, + }, + logger, + dtos.Metadata{}, + ) + + splitChangesDTO, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithChangeNumberRB(123456)) + if err != nil { + t.Error(err) + } + + if splitChangesDTO.FFTill() != 1491244291288 || + splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2" { t.Error("DTO mal formed") } - if splitChangesDTO.FeatureFlags.Splits[0].Configurations == nil { + if splitChangesDTO.FeatureFlags()[0].Configurations == nil { t.Error("DTO mal formed") } - if splitChangesDTO.FeatureFlags.Splits[0].Configurations["of"] != "" { + if splitChangesDTO.FeatureFlags()[0].Configurations["of"] != "" { t.Error("DTO mal formed") } - if splitChangesDTO.FeatureFlags.Splits[0].Configurations["on"] != "{\"color\": \"blue\",\"size\": 13}" { + if splitChangesDTO.FeatureFlags()[0].Configurations["on"] != "{\"color\": \"blue\",\"size\": 13}" { t.Error("DTO mal formed") } } diff --git a/service/interfaces.go b/service/interfaces.go index 52a1c56f..699958ac 100644 --- a/service/interfaces.go +++ b/service/interfaces.go @@ -9,7 +9,7 @@ type AuthClient interface { // SplitFetcher interface to be implemented by Split Fetchers type SplitFetcher interface { - Fetch(fetchOptions *FlagRequestParams) (*dtos.SplitChangesDTO, error) + Fetch(fetchOptions *FlagRequestParams) (dtos.FFResponse, error) } // SegmentFetcher interface to be implemented by Split Fetchers diff --git a/service/local/sanitizer.go b/service/local/sanitizer.go index d8d28308..9737c704 100644 --- a/service/local/sanitizer.go +++ b/service/local/sanitizer.go @@ -7,22 +7,22 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" ) -func splitSanitization(splitChange dtos.SplitChangesDTO) *dtos.SplitChangesDTO { - if splitChange.FeatureFlags.Till < -1 { - splitChange.FeatureFlags.Till = -1 +func splitSanitization(splitChange dtos.FFResponse) dtos.FFResponse { + if splitChange.FFTill() < -1 { + splitChange.SetFFTill(-1) } - if splitChange.RuleBasedSegments.Till < -1 { - splitChange.RuleBasedSegments.Till = -1 + if splitChange.RBTill() < -1 { + splitChange.SetRBTill(-1) } - if splitChange.FeatureFlags.Since < -1 || splitChange.FeatureFlags.Since > splitChange.FeatureFlags.Till { - splitChange.FeatureFlags.Since = splitChange.FeatureFlags.Till + if splitChange.FFSince() < -1 || splitChange.FFSince() > splitChange.FFTill() { + splitChange.SetFFSince(splitChange.FFTill()) } - if splitChange.RuleBasedSegments.Since < -1 || splitChange.RuleBasedSegments.Since > splitChange.RuleBasedSegments.Till { - splitChange.RuleBasedSegments.Since = splitChange.RuleBasedSegments.Till + if splitChange.RBSince() < -1 || splitChange.RBSince() > splitChange.RBTill() { + splitChange.SetRBSince(splitChange.RBTill()) } var splitResult []dtos.SplitDTO - for i := 0; i < len(splitChange.FeatureFlags.Splits); i++ { - split := splitChange.FeatureFlags.Splits[i] + for i := 0; i < len(splitChange.FeatureFlags()); i++ { + split := splitChange.FeatureFlags()[i] if split.Name == "" { continue } @@ -61,8 +61,8 @@ func splitSanitization(splitChange dtos.SplitChangesDTO) *dtos.SplitChangesDTO { splitResult = append(splitResult, split) } var ruleBasedSegmentResult []dtos.RuleBasedSegmentDTO - for i := 0; i < len(splitChange.RuleBasedSegments.RuleBasedSegments); i++ { - ruleBased := splitChange.RuleBasedSegments.RuleBasedSegments[i] + for i := 0; i < len(splitChange.RuleBasedSegments()); i++ { + ruleBased := splitChange.RuleBasedSegments()[i] if ruleBased.Name == "" { continue } @@ -78,9 +78,9 @@ func splitSanitization(splitChange dtos.SplitChangesDTO) *dtos.SplitChangesDTO { ruleBasedSegmentResult = append(ruleBasedSegmentResult, ruleBased) } - splitChange.FeatureFlags.Splits = splitResult - splitChange.RuleBasedSegments.RuleBasedSegments = ruleBasedSegmentResult - return &splitChange + splitChange.ReplaceFF(splitResult) + splitChange.ReplaceRB(ruleBasedSegmentResult) + return splitChange } func segmentSanitization(segmentChange dtos.SegmentChangesDTO, segmentName string) (*dtos.SegmentChangesDTO, error) { diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index 64b5a342..e4927b63 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -217,9 +217,8 @@ func (f *FileSplitFetcher) parseSplitsYAML(data string) (d []dtos.SplitDTO) { return splits } -func (f *FileSplitFetcher) parseSplitsJson(data string) (*dtos.SplitChangesDTO, error) { - var splitChangesDto dtos.SplitChangesDTO - err := json.Unmarshal([]byte(data), &splitChangesDto) +func (f *FileSplitFetcher) parseSplitsJson(data string) (dtos.FFResponse, error) { + splitChangesDto, err := dtos.NewFFResponseV13([]byte(data)) if err != nil { f.logger.Error(fmt.Sprintf("error: %v", err)) @@ -228,18 +227,18 @@ func (f *FileSplitFetcher) parseSplitsJson(data string) (*dtos.SplitChangesDTO, return splitSanitization(splitChangesDto), nil } -func (s *FileSplitFetcher) processSplitJson(data string, changeNumber int64) (*dtos.SplitChangesDTO, error) { +func (s *FileSplitFetcher) processSplitJson(data string, changeNumber int64) (dtos.FFResponse, error) { splitChange, err := s.parseSplitsJson(data) if err != nil { s.logger.Error(fmt.Sprintf("could not find the splitChange file. error: %v", err)) return nil, err } // if the till is less than storage CN and different from the default till ignore the change - if splitChange.FeatureFlags.Till < changeNumber && splitChange.FeatureFlags.Till != defaultTill || - splitChange.RuleBasedSegments.Since != 0 && splitChange.RuleBasedSegments.Till < changeNumber && splitChange.RuleBasedSegments.Till != defaultTill { + if splitChange.FFTill() < changeNumber && splitChange.FFTill() != defaultTill || + splitChange.RBTill() != 0 && splitChange.RBTill() < changeNumber && splitChange.RBTill() != defaultTill { return nil, fmt.Errorf("ignoring change, the till is less than storage change number") } - splitsJson, _ := json.Marshal(splitChange.FeatureFlags.Splits) + splitsJson, _ := json.Marshal(splitChange.FeatureFlags()) currH := sha1.New() currH.Write(splitsJson) // calculate the json sha @@ -247,17 +246,17 @@ func (s *FileSplitFetcher) processSplitJson(data string, changeNumber int64) (*d s.mutexFF.Lock() defer s.mutexFF.Unlock() //if sha exist and is equal to before sha, or if till is equal to default till returns the same splitChange with till equals to storage CN - if bytes.Equal(currSum, s.lastHash) || splitChange.FeatureFlags.Till == defaultTill { + if bytes.Equal(currSum, s.lastHash) || splitChange.FFTill() == defaultTill { s.lastHash = currSum - splitChange.FeatureFlags.Till = changeNumber - splitChange.FeatureFlags.Since = changeNumber + splitChange.SetFFTill(changeNumber) + splitChange.SetFFSince(changeNumber) return splitChange, nil } // In the last case, the sha is different and till upper or equal to storage CN s.lastHash = currSum - if splitChange.RuleBasedSegments.RuleBasedSegments != nil { - ruleBasedJson, _ := json.Marshal(splitChange.RuleBasedSegments.RuleBasedSegments) + if splitChange.RuleBasedSegments() != nil { + ruleBasedJson, _ := json.Marshal(splitChange.RuleBasedSegments()) currHRB := sha1.New() currHRB.Write(ruleBasedJson) // calculate the json sha @@ -265,24 +264,24 @@ func (s *FileSplitFetcher) processSplitJson(data string, changeNumber int64) (*d s.mutexRB.Lock() defer s.mutexRB.Unlock() //if sha exist and is equal to before sha, or if till is equal to default till returns the same splitChange with till equals to storage CN - if bytes.Equal(currSumRB, s.lastHashRB) || splitChange.RuleBasedSegments.Till == defaultTill { + if bytes.Equal(currSumRB, s.lastHashRB) || splitChange.RBTill() == defaultTill { s.lastHashRB = currSumRB - splitChange.RuleBasedSegments.Till = changeNumber - splitChange.RuleBasedSegments.Since = changeNumber + splitChange.SetRBTill(changeNumber) + splitChange.SetRBSince(changeNumber) return splitChange, nil } s.lastHashRB = currSumRB - splitChange.RuleBasedSegments.Since = splitChange.RuleBasedSegments.Till + splitChange.SetRBSince(splitChange.RBTill()) } // In the last case, the sha is different and till upper or equal to storage CN s.lastHash = currSum - splitChange.FeatureFlags.Since = splitChange.FeatureFlags.Till + splitChange.SetFFSince(splitChange.FFTill()) return splitChange, nil } // Fetch parses the file and returns the appropriate structures -func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { +func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos.FFResponse, error) { fileContents, err := s.reader.ReadFile(s.splitFile) if err != nil { return nil, err @@ -315,13 +314,10 @@ func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos } s.lastHash = currSum - return &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Splits: splits, - Since: fetchOptions.ChangeNumber(), - Till: till, - }, - }, nil + responseToReturn := dtos.NewFFResponseWithFFRBV13(splits, nil) + responseToReturn.SetFFSince(fetchOptions.ChangeNumber()) + responseToReturn.SetFFTill(till) + return responseToReturn, nil } var _ service.SplitFetcher = &FileSplitFetcher{} diff --git a/service/local/splitFetcher_test.go b/service/local/splitFetcher_test.go index e445d828..8e68e9b8 100644 --- a/service/local/splitFetcher_test.go +++ b/service/local/splitFetcher_test.go @@ -67,8 +67,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has defaultTill, both since/till should be updated to changeNumber - if res.RuleBasedSegments.Since != 25 || res.RuleBasedSegments.Till != 25 { - t.Error("Expected RBS since/till to be 25 (change number), got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 25 || res.RBTill() != 25 { + t.Error("Expected RBS since/till to be 25 (change number), got:", res.RBSince(), res.RBTill()) } // Test case 2: RBS with different hash and till = 50 @@ -84,8 +84,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has different hash and till > changeNumber, since should be updated to till - if res.RuleBasedSegments.Since != 50 || res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS since/till to be 50/50, got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 50 || res.RBTill() != 50 { + t.Error("Expected RBS since/till to be 50/50, got:", res.RBSince(), res.RBTill()) } // Test case 3: RBS with same hash and till = 50 @@ -113,8 +113,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has same hash and till = changeNumber, since should be updated to till - if res.RuleBasedSegments.Since != 50 || res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS since/till to be 50/50, got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 50 || res.RBTill() != 50 { + t.Error("Expected RBS since/till to be 50/50, got:", res.RBSince(), res.RBTill()) } // Test case 5: RBS with empty segments @@ -130,8 +130,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has empty segments, since should be updated to till - if res.RuleBasedSegments.Since != 50 || res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS since/till to be 50/50, got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 50 || res.RBTill() != 50 { + t.Error("Expected RBS since/till to be 50/50, got:", res.RBSince(), res.RBTill()) } // Test case 6: RBS with nil segments @@ -147,8 +147,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has nil segments, since should be updated to till - if res.RuleBasedSegments.Since != 50 || res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS since/till to be 50/50, got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 50 || res.RBTill() != 50 { + t.Error("Expected RBS since/till to be 50/50, got:", res.RBSince(), res.RBTill()) } // Test case 7: RBS with different segments @@ -164,8 +164,8 @@ func TestProcessSplitJson(t *testing.T) { } // Since RBS has different segments, since should be updated to till - if res.RuleBasedSegments.Since != 50 || res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS since/till to be 50/50, got:", res.RuleBasedSegments.Since, res.RuleBasedSegments.Till) + if res.RBSince() != 50 || res.RBTill() != 50 { + t.Error("Expected RBS since/till to be 50/50, got:", res.RBSince(), res.RBTill()) } } @@ -192,12 +192,12 @@ func TestLocalSplitFetcher(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != -1 || res.FeatureFlags.Till != 0 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != -1 || res.FFTill() != 0 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 2 { - t.Error("should have 2 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 2 { + t.Error("should have 2 splits. has: ", len(res.FeatureFlags())) } // second call -- no change -- since == till @@ -207,12 +207,12 @@ func TestLocalSplitFetcher(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != 0 || res.FeatureFlags.Till != 0 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != 0 || res.FFTill() != 0 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 2 { - t.Error("should have 2 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 2 { + t.Error("should have 2 splits. has: ", len(res.FeatureFlags())) } if _, err := file.Write([]byte("feature3 yes\n")); err != nil { @@ -226,12 +226,12 @@ func TestLocalSplitFetcher(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != 0 || res.FeatureFlags.Till != 1 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != 0 || res.FFTill() != 1 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 3 { - t.Error("should have 2 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 3 { + t.Error("should have 2 splits. has: ", len(res.FeatureFlags())) } // fourth call -- no change -- till != since @@ -241,12 +241,12 @@ func TestLocalSplitFetcher(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != 1 || res.FeatureFlags.Till != 1 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != 1 || res.FFTill() != 1 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 3 { - t.Error("should have 2 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 3 { + t.Error("should have 2 splits. has: ", len(res.FeatureFlags())) } } @@ -260,19 +260,19 @@ func TestLocalSplitFetcherJson(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != 1660326991072 || res.FeatureFlags.Till != 1660326991072 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != 1660326991072 || res.FFTill() != 1660326991072 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 7 { - t.Error("should have 7 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 7 { + t.Error("should have 7 splits. has: ", len(res.FeatureFlags())) } - if res.FeatureFlags.Splits[0].Name != "split_1" { + if res.FeatureFlags()[0].Name != "split_1" { t.Error("DTO mal formed") } - if res.FeatureFlags.Splits[0].Configurations == nil { + if res.FeatureFlags()[0].Configurations == nil { t.Error("DTO mal formed") } } @@ -287,19 +287,19 @@ func TestLocalSplitFetcherJsonWithRbs(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Since != 10 || res.FeatureFlags.Till != 10 { - t.Error("Wrong since/till. Got: ", res.FeatureFlags.Since, res.FeatureFlags.Till) + if res.FFSince() != 10 || res.FFTill() != 10 { + t.Error("Wrong since/till. Got: ", res.FFSince(), res.FFTill()) } - if len(res.FeatureFlags.Splits) != 1 { - t.Error("should have 1 splits. has: ", res.FeatureFlags.Splits) + if len(res.FeatureFlags()) != 1 { + t.Error("should have 1 splits. has: ", len(res.FeatureFlags())) } - if res.FeatureFlags.Splits[0].Name != "rbs_split" { + if res.FeatureFlags()[0].Name != "rbs_split" { t.Error("DTO mal formed") } - if res.FeatureFlags.Splits[0].Configurations == nil { + if res.FeatureFlags()[0].Configurations == nil { t.Error("DTO mal formed") } } @@ -359,61 +359,61 @@ func TestFetchSomeSplits(t *testing.T) { } // 0) The CN from storage is -1, till and since are -1, and sha doesn't exist in the hash. It's going to return a split change with updates. splitChange, _ := mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(-1)) - if splitChange.FeatureFlags.Since != -1 || splitChange.FeatureFlags.Till != -1 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != -1 || splitChange.FFTill() != -1 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 1 { - t.Error("should have 1 split. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 1 { + t.Error("should have 1 split. has: ", splitChange.FeatureFlags()) } fetches++ // 1) The CN from storage is -1, till and since are -1, and sha is different than before. It's going to return a split change with updates. splitChange, _ = mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(-1)) - if splitChange.FeatureFlags.Since != -1 || splitChange.FeatureFlags.Till != -1 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != -1 || splitChange.FFTill() != -1 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 2 { - t.Error("should have 1 split. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 2 { + t.Error("should have 1 split. has: ", splitChange.FeatureFlags()) } fetches++ // 2) The CN from storage is -1, till is 2323, and since is -1, and sha is the same as before. It's going to return a split change with the same data. splitChange, _ = mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(-1)) - if splitChange.FeatureFlags.Since != -1 || splitChange.FeatureFlags.Till != -1 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != -1 || splitChange.FFTill() != -1 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 2 { - t.Error("should have 2 splits. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 2 { + t.Error("should have 2 splits. has: ", splitChange.FeatureFlags()) } fetches++ // 3) The CN from storage is -1, till is 2323, and since is -1, sha is different than before. It's going to return a split change with updates. splitChange, _ = mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(-1)) - if splitChange.FeatureFlags.Since != 2323 || splitChange.FeatureFlags.Till != 2323 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != 2323 || splitChange.FFTill() != 2323 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 1 { - t.Error("should have 1 split. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 1 { + t.Error("should have 1 split. has: ", splitChange.FeatureFlags()) } fetches++ // 4) The CN from storage is 2323, till is 445345, and since is -1, and sha is the same as before. It's going to return a split change with same data. splitChange, _ = mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(2323)) - if splitChange.FeatureFlags.Since != 2323 || splitChange.FeatureFlags.Till != 2323 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != 2323 || splitChange.FFTill() != 2323 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 1 { - t.Error("should have 1 split. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 1 { + t.Error("should have 1 split. has: ", splitChange.FeatureFlags()) } fetches++ // 5) The CN from storage is 2323, till and since are -1, and sha is different than before. It's going to return a split change with updates. splitChange, _ = mockedFetchers.Fetch(service.MakeFlagRequestParams().WithChangeNumber(2323)) - if splitChange.FeatureFlags.Since != 2323 || splitChange.FeatureFlags.Till != 2323 { - t.Error("Wrong since/till. Got: ", splitChange.FeatureFlags.Since, splitChange.FeatureFlags.Till) + if splitChange.FFSince() != 2323 || splitChange.FFTill() != 2323 { + t.Error("Wrong since/till. Got: ", splitChange.FFSince(), splitChange.FFTill()) } - if len(splitChange.FeatureFlags.Splits) != 2 { - t.Error("should have 2 splits. has: ", splitChange.FeatureFlags.Splits) + if len(splitChange.FeatureFlags()) != 2 { + t.Error("should have 2 splits. has: ", splitChange.FeatureFlags()) } } @@ -441,8 +441,8 @@ func TestSplitWithoutName(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if len(res.FeatureFlags.Splits) != 1 { - t.Error("Should has one split. Got: ", len(res.FeatureFlags.Splits)) + if len(res.FeatureFlags()) != 1 { + t.Error("Should has one split. Got: ", len(res.FeatureFlags())) } } @@ -470,11 +470,11 @@ func TestSplitMatchersEmpty(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if len(res.FeatureFlags.Splits) != 1 { - t.Error("should has one split. Got: ", len(res.FeatureFlags.Splits)) + if len(res.FeatureFlags()) != 1 { + t.Error("should has one split. Got: ", len(res.FeatureFlags())) } - split := res.FeatureFlags.Splits[0] + split := res.FeatureFlags()[0] if split.Conditions[0].MatcherGroup.Matchers[0].MatcherType != "ALL_KEYS" { t.Error("the matcher type should be all keys. Got: ", split.Conditions[0].MatcherGroup.Matchers[0].MatcherType) } @@ -508,12 +508,12 @@ func TestSplitWithRuleBasedSegment(t *testing.T) { return } - if len(res.FeatureFlags.Splits) != 1 { - t.Error("should have 1 split, got:", len(res.FeatureFlags.Splits)) + if len(res.FeatureFlags()) != 1 { + t.Error("should have 1 split, got:", len(res.FeatureFlags())) return } - split := res.FeatureFlags.Splits[0] + split := res.FeatureFlags()[0] if split.Name != "SPLIT_WITH_RULE" { t.Error("Expected split name SPLIT_WITH_RULE, got", split.Name) } @@ -557,12 +557,12 @@ func TestSplitWithRuleBasedSegment(t *testing.T) { } // Verify rule based segments - if len(res.RuleBasedSegments.RuleBasedSegments) != 1 { - t.Error("Expected 1 rule based segment, got", len(res.RuleBasedSegments.RuleBasedSegments)) + if len(res.RuleBasedSegments()) != 1 { + t.Error("Expected 1 rule based segment, got", len(res.RuleBasedSegments())) return } - ruleBasedSegment := res.RuleBasedSegments.RuleBasedSegments[0] + ruleBasedSegment := res.RuleBasedSegments()[0] if ruleBasedSegment.Name != "test-segment" { t.Error("Expected rule based segment name test-segment, got", ruleBasedSegment.Name) } @@ -623,8 +623,8 @@ func TestSplitWithOldTill(t *testing.T) { if err != nil { t.Error("Expected no error when till equals change number, got:", err) } - if res.FeatureFlags.Till != 50 { - t.Error("Expected till value 50, got:", res.FeatureFlags.Till) + if res.FFTill() != 50 { + t.Error("Expected till value 50, got:", res.FFTill()) } // Test with a change number less than the till value @@ -632,8 +632,8 @@ func TestSplitWithOldTill(t *testing.T) { if err != nil { t.Error("Expected no error when till is greater than change number, got:", err) } - if res.FeatureFlags.Till != 25 { - t.Error("Expected till value to match change number 25, got:", res.FeatureFlags.Till) + if res.FFTill() != 25 { + t.Error("Expected till value to match change number 25, got:", res.FFTill()) } } @@ -668,8 +668,8 @@ func TestSplitWithOldRBSTill(t *testing.T) { if err != nil { t.Error("Expected no error when RBS till equals change number, got:", err) } - if res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS till value 50, got:", res.RuleBasedSegments.Till) + if res.RBTill() != 50 { + t.Error("Expected RBS till value 50, got:", res.RBTill()) } // Test with a change number less than the RBS till value @@ -677,18 +677,18 @@ func TestSplitWithOldRBSTill(t *testing.T) { if err != nil { t.Error("Expected no error when RBS till is greater than change number, got:", err) } - if res.RuleBasedSegments.Till != 50 { - t.Error("Expected RBS till value to remain at 50, got:", res.RuleBasedSegments.Till) + if res.RBTill() != 50 { + t.Error("Expected RBS till value to remain at 50, got:", res.RBTill()) } - if res.RuleBasedSegments.Since != 50 { - t.Error("Expected RBS since value to be 50, got:", res.RuleBasedSegments.Since) + if res.RBSince() != 50 { + t.Error("Expected RBS since value to be 50, got:", res.RBSince()) } // Verify that the rule based segments are present - if len(res.RuleBasedSegments.RuleBasedSegments) != 1 { - t.Error("Expected 1 rule based segment, got", len(res.RuleBasedSegments.RuleBasedSegments)) + if len(res.RuleBasedSegments()) != 1 { + t.Error("Expected 1 rule based segment, got", len(res.RuleBasedSegments())) } - ruleBasedSegment := res.RuleBasedSegments.RuleBasedSegments[0] + ruleBasedSegment := res.RuleBasedSegments()[0] if ruleBasedSegment.Name != "test-segment" { t.Error("Expected rule based segment name test-segment, got", ruleBasedSegment.Name) } @@ -718,23 +718,23 @@ func TestSplitSanitization(t *testing.T) { t.Error("fetching should not fail. Got: ", err) } - if res.FeatureFlags.Splits[0].Algo != 2 { - t.Error("algo should be 2. Got: ", res.FeatureFlags.Splits[0].Algo) + if res.FeatureFlags()[0].Algo != 2 { + t.Error("algo should be 2. Got: ", res.FeatureFlags()[0].Algo) } - if res.FeatureFlags.Splits[0].TrafficAllocation != 100 { - t.Error("traffic allocation should be 100. Got: ", res.FeatureFlags.Splits[0].TrafficAllocation) + if res.FeatureFlags()[0].TrafficAllocation != 100 { + t.Error("traffic allocation should be 100. Got: ", res.FeatureFlags()[0].TrafficAllocation) } - if res.FeatureFlags.Splits[0].TrafficAllocationSeed == 0 { + if res.FeatureFlags()[0].TrafficAllocationSeed == 0 { t.Error("traffic allocation seed can't be 0") } - if res.FeatureFlags.Splits[0].Seed == 0 { + if res.FeatureFlags()[0].Seed == 0 { t.Error("seed can't be 0") } - if res.FeatureFlags.Splits[0].DefaultTreatment != "control" { + if res.FeatureFlags()[0].DefaultTreatment != "control" { t.Error("default treatment should be control") } } diff --git a/service/mocks/split.go b/service/mocks/split.go index edf75de4..4ee2fdf0 100644 --- a/service/mocks/split.go +++ b/service/mocks/split.go @@ -13,12 +13,12 @@ type MockSplitFetcher struct { } // Fetch mock -func (m *MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { +func (m *MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos.FFResponse, error) { args := m.Called(fetchOptions) if args.Get(0) == nil { return nil, args.Error(1) } - return args.Get(0).(*dtos.SplitChangesDTO), args.Error(1) + return args.Get(0).(dtos.FFResponse), args.Error(1) } var _ service.SplitFetcher = (*MockSplitFetcher)(nil) diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 25d83f82..52571722 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -82,14 +82,13 @@ func TestLocalSyncAllOk(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) + response.SetFFSince(3) + response.SetFFTill(3) splitFetcher.On("Fetch", mock.MatchedBy(func(req *service.FlagRequestParams) bool { return req.ChangeNumber() == -1 - })).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil).Once() + })).Return(response, nil).Once() splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} splitMockStorage := &mocks.SplitStorageMock{} splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) @@ -120,11 +119,11 @@ func TestLocalPeriodicFetching(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil).Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + + splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} splitMockStorage := &mocks.SplitStorageMock{} splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 539470fd..ccfab80d 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -96,11 +96,11 @@ func TestSyncAllErrorInSegments(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + + splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ @@ -165,12 +165,11 @@ func TestSyncAllOk(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) + response.SetFFSince(3) + response.SetFFTill(3) splitFetcher := &httpMocks.MockSplitFetcher{} - splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil) + splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ @@ -252,12 +251,12 @@ func TestPeriodicFetching(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) + + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) + response.SetFFSince(3) + response.SetFFTill(3) splitFetcher := &httpMocks.MockSplitFetcher{} - splitFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, - Since: 3, - Till: 3}, - }, nil).Once() + splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{ SplitFetcher: splitFetcher, SegmentFetcher: httpMocks.MockSegmentFetcher{ diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 6c149b09..451ce03a 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -101,16 +101,16 @@ func (s *UpdaterImpl) SetRuleBasedSegmentStorage(storage storage.RuleBasedSegmen s.ruleBasedSegmentStorage = storage } -func (s *UpdaterImpl) processUpdate(splitChanges *dtos.SplitChangesDTO) { +func (s *UpdaterImpl) processUpdate(splitChanges dtos.FFResponse) { activeSplits, inactiveSplits := s.processFeatureFlagChanges(splitChanges) // Add/Update active splits - s.splitStorage.Update(activeSplits, inactiveSplits, splitChanges.FeatureFlags.Till) + s.splitStorage.Update(activeSplits, inactiveSplits, splitChanges.FFTill()) } -func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges *dtos.SplitChangesDTO) []string { +func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges dtos.FFResponse) []string { activeRB, inactiveRB, segments := s.processRuleBasedSegmentChanges(splitChanges) // Add/Update active splits - s.ruleBasedSegmentStorage.Update(activeRB, inactiveRB, splitChanges.RuleBasedSegments.Till) + s.ruleBasedSegmentStorage.Update(activeRB, inactiveRB, splitChanges.RBTill()) return segments } @@ -128,7 +128,7 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda currentSince, _ = s.splitStorage.ChangeNumber() currentRBSince = s.ruleBasedSegmentStorage.ChangeNumber() before := time.Now() - var splitChanges *dtos.SplitChangesDTO + var splitChanges dtos.FFResponse splitChanges, err = s.splitFetcher.Fetch(fetchOptions.WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) if err != nil { if httpError, ok := err.(*dtos.HTTPError); ok { @@ -139,15 +139,15 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda } break } - currentSince = splitChanges.FeatureFlags.Till - currentRBSince = splitChanges.RuleBasedSegments.Till + currentSince = splitChanges.FFTill() + currentRBSince = splitChanges.RBTill() s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) s.processUpdate(splitChanges) segmentReferences = s.processRuleBasedUpdate(splitChanges) segmentReferences = appendSegmentNames(segmentReferences, splitChanges) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges) - if currentSince == splitChanges.FeatureFlags.Since && currentRBSince == splitChanges.RuleBasedSegments.Since { + if splitChanges.NeedsAnotherFetch() { s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC()) break } @@ -211,15 +211,16 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { return internalSyncResultCDNBypass.updateResult, nil } -func appendSplitNames(dst []string, splitChanges *dtos.SplitChangesDTO) []string { - for idx := range splitChanges.FeatureFlags.Splits { - dst = append(dst, splitChanges.FeatureFlags.Splits[idx].Name) +func appendSplitNames(dst []string, splitChanges dtos.FFResponse) []string { + featureFlags := splitChanges.FeatureFlags() + for idx := range featureFlags { + dst = append(dst, featureFlags[idx].Name) } return dst } -func appendSegmentNames(dst []string, splitChanges *dtos.SplitChangesDTO) []string { - for _, split := range splitChanges.FeatureFlags.Splits { +func appendSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { + for _, split := range splitChanges.FeatureFlags() { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInSegment && matcher.UserDefinedSegment != nil { @@ -231,8 +232,8 @@ func appendSegmentNames(dst []string, splitChanges *dtos.SplitChangesDTO) []stri return dst } -func appendLargeSegmentNames(dst []string, splitChanges *dtos.SplitChangesDTO) []string { - for _, split := range splitChanges.FeatureFlags.Splits { +func appendLargeSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { + for _, split := range splitChanges.FeatureFlags() { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInLargeSegment && matcher.UserDefinedLargeSegment != nil { @@ -252,14 +253,14 @@ func addIfNotExists(dst []string, seen map[string]struct{}, name string) []strin return dst } -func appendRuleBasedSegmentNames(dst []string, splitChanges *dtos.SplitChangesDTO) []string { +func appendRuleBasedSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { seen := make(map[string]struct{}) // Inicializamos el mapa con lo que ya tiene dst para no duplicar tampoco ahí for _, name := range dst { seen[name] = struct{}{} } - for _, split := range splitChanges.FeatureFlags.Splits { + for _, split := range splitChanges.FeatureFlags() { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInRuleBasedSegment && matcher.UserDefinedSegment != nil { @@ -271,15 +272,17 @@ func appendRuleBasedSegmentNames(dst []string, splitChanges *dtos.SplitChangesDT return dst } -func (s *UpdaterImpl) processFeatureFlagChanges(splitChanges *dtos.SplitChangesDTO) ([]dtos.SplitDTO, []dtos.SplitDTO) { - toRemove := make([]dtos.SplitDTO, 0, len(splitChanges.FeatureFlags.Splits)) - toAdd := make([]dtos.SplitDTO, 0, len(splitChanges.FeatureFlags.Splits)) - for idx := range splitChanges.FeatureFlags.Splits { - if splitChanges.FeatureFlags.Splits[idx].Status == Active && s.flagSetsFilter.Instersect(splitChanges.FeatureFlags.Splits[idx].Sets) { - s.validator.ProcessMatchers(&splitChanges.FeatureFlags.Splits[idx], s.logger) - toAdd = append(toAdd, splitChanges.FeatureFlags.Splits[idx]) +func (s *UpdaterImpl) processFeatureFlagChanges(splitChanges dtos.FFResponse) ([]dtos.SplitDTO, []dtos.SplitDTO) { + featureFlags := splitChanges.FeatureFlags() + toRemove := make([]dtos.SplitDTO, 0, len(featureFlags)) + toAdd := make([]dtos.SplitDTO, 0, len(featureFlags)) + + for idx := range featureFlags { + if featureFlags[idx].Status == Active && s.flagSetsFilter.Instersect(featureFlags[idx].Sets) { + s.validator.ProcessMatchers(&featureFlags[idx], s.logger) + toAdd = append(toAdd, featureFlags[idx]) } else { - toRemove = append(toRemove, splitChanges.FeatureFlags.Splits[idx]) + toRemove = append(toRemove, featureFlags[idx]) } } return toAdd, toRemove @@ -313,14 +316,14 @@ func (s *UpdaterImpl) processFFChange(ffChange dtos.SplitChangeUpdate) *UpdateRe s.logger.Debug(fmt.Sprintf("updating feature flag %s", ffChange.FeatureFlag().Name)) featureFlags := make([]dtos.SplitDTO, 0, 1) featureFlags = append(featureFlags, *ffChange.FeatureFlag()) - featureFlagChange := dtos.SplitChangesDTO{FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} - activeFFs, inactiveFFs := s.processFeatureFlagChanges(&featureFlagChange) + splitChanges := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + activeFFs, inactiveFFs := s.processFeatureFlagChanges(splitChanges) s.splitStorage.Update(activeFFs, inactiveFFs, ffChange.BaseUpdate.ChangeNumber()) s.runtimeTelemetry.RecordUpdatesFromSSE(telemetry.SplitUpdate) updatedSplitNames = append(updatedSplitNames, ffChange.FeatureFlag().Name) - segmentReferences = appendSegmentNames(segmentReferences, &featureFlagChange) - largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, &featureFlagChange) - ruleBasedSegmentReferences = appendRuleBasedSegmentNames(ruleBasedSegmentReferences, &featureFlagChange) + segmentReferences = appendSegmentNames(segmentReferences, splitChanges) + largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges) + ruleBasedSegmentReferences = appendRuleBasedSegmentNames(ruleBasedSegmentReferences, splitChanges) requiresFetch := false if len(ruleBasedSegmentReferences) > 0 && !s.ruleBasedSegmentStorage.Contains(ruleBasedSegmentReferences) { requiresFetch = true @@ -355,11 +358,12 @@ func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) [] return segments } -func (s *UpdaterImpl) processRuleBasedSegmentChanges(splitChanges *dtos.SplitChangesDTO) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO, []string) { - toRemove := make([]dtos.RuleBasedSegmentDTO, 0, len(splitChanges.RuleBasedSegments.RuleBasedSegments)) - toAdd := make([]dtos.RuleBasedSegmentDTO, 0, len(splitChanges.RuleBasedSegments.RuleBasedSegments)) +func (s *UpdaterImpl) processRuleBasedSegmentChanges(splitChanges dtos.FFResponse) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO, []string) { + ruleBasedSegments := splitChanges.RuleBasedSegments() + toRemove := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) + toAdd := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) segments := make([]string, 0) - for _, rbSegment := range splitChanges.RuleBasedSegments.RuleBasedSegments { + for _, rbSegment := range ruleBasedSegments { if rbSegment.Status == Active { s.validator.ProcessRBMatchers(&rbSegment, s.logger) toAdd = append(toAdd, rbSegment) @@ -379,8 +383,8 @@ func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitCha } ruleBasedSegments := make([]dtos.RuleBasedSegmentDTO, 0, 1) ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) - splitChanges := dtos.SplitChangesDTO{RuleBasedSegments: dtos.RuleBasedSegmentsDTO{RuleBasedSegments: ruleBasedSegments}} - toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(&splitChanges) + ffResponse := dtos.NewFFResponseWithFFRBV13(nil, ruleBasedSegments) + toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(ffResponse) s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) return &UpdateResult{ diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 85330a58..d790d788 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -106,12 +106,12 @@ func TestSplitSynchronizer(t *testing.T) { splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3, - }}, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSuccessfulSyncCall: func(resource int, tm time.Time) { @@ -156,17 +156,17 @@ func TestSplitSyncProcess(t *testing.T) { }}}}, } + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil).Once() - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit4, mockedSplit5}, - Since: 3, - Till: 3}, - }, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() + + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit4, mockedSplit5}, nil) + response1.SetFFSince(3) + response1.SetFFTill(3) + splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(2) @@ -211,15 +211,12 @@ func TestSplitTill(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, []dtos.RuleBasedSegmentDTO{mockedRuleBased1}) + response.SetFFSince(2) + response.SetFFTill(2) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, - Since: 2, - Till: 2}, - }, nil).Twice() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Twice() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(2) @@ -249,24 +246,22 @@ func TestSplitTill(t *testing.T) { func TestByPassingCDN(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response.SetFFSince(1) + response.SetFFTill(2) splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 1, - Till: 2}, - }, nil).Once() - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil).Times(10) + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() + + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response1.SetFFSince(2) + response1.SetFFTill(2) + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) + response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response2.SetFFSince(3) + response2.SetFFTill(3) splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 - })).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 3, - Till: 3}, - }, nil).Once() + })).Return(response2, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() @@ -296,24 +291,21 @@ func TestByPassingCDN(t *testing.T) { func TestByPassingCDNLimit(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response.SetFFSince(1) + response.SetFFTill(2) splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 1, - Till: 2}, - }, nil).Once() - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil).Times(10) + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response1.SetFFSince(2) + response1.SetFFTill(2) + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) + response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) + response2.SetFFSince(2) + response2.SetFFTill(2) splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 - })).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, - Since: 2, - Till: 2}, - }, nil).Times(10) + })).Return(response2, nil).Times(10) appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() @@ -368,12 +360,11 @@ func TestAddOrUpdateFeatureFlagNil(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(-1), nil).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(-1).Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil) + response.SetFFSince(2) + response.SetFFTill(2) splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, - Since: 2, - Splits: []dtos.SplitDTO{}}, - }, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryStorage, _ := inmemory.NewTelemetryStorage() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() @@ -443,12 +434,11 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(0), errors.New("error geting change number")).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(2)).Return().Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil) + response.SetFFSince(2) + response.SetFFTill(2) splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Till: 2, - Since: 2, - Splits: []dtos.SplitDTO{}}, - }, nil) + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil) telemetryStorage, _ := inmemory.NewTelemetryStorage() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return() @@ -468,38 +458,37 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { func TestGetActiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Active}} - featureFlagChanges := &dtos.SplitChangesDTO{FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) + actives, inactives := s.processFeatureFlagChanges(response) assert.Len(t, actives, 2) assert.Len(t, inactives, 0) } func TestGetInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Archived}, {Status: Archived}} - featureFlagChanges := &dtos.SplitChangesDTO{FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) + actives, inactives := s.processFeatureFlagChanges(response) assert.Len(t, actives, 0) assert.Len(t, inactives, 2) } func TestGetActiveAndInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Archived}} - featureFlagChanges := &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: featureFlags}} + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) + actives, inactives := s.processFeatureFlagChanges(response) assert.Len(t, actives, 1) assert.Len(t, inactives, 1) } @@ -509,12 +498,12 @@ func TestSplitSyncWithSets(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set1"}} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() @@ -546,13 +535,12 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set2"}} mockedSplit4 := dtos.SplitDTO{Name: "split4", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set2"}} + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, nil) + response.SetFFSince(3) + response.SetFFTill(3) splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, - Since: 3, - Till: 3}, - }, nil).Once() + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() @@ -628,18 +616,12 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 2: till is equal to currentSince but less than currentRBSince till = 100 - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: 100, - Till: 100, - Splits: []dtos.SplitDTO{}, - }, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ - Since: 150, - Till: 150, - RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, - }, - }, nil).Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}) + response.SetFFSince(100) + response.SetFFTill(100) + response.SetRBSince(150) + response.SetRBTill(150) + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) assert.NotNil(t, result) @@ -648,18 +630,13 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 3: till is equal to currentRBSince but greater than currentSince till = 150 - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: 100, - Till: 100, - Splits: []dtos.SplitDTO{}, - }, - RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ - Since: 150, - Till: 150, - RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, - }, - }, nil).Once() + + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}) + response1.SetFFSince(100) + response1.SetFFTill(100) + response1.SetRBSince(150) + response1.SetRBTill(150) + splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) assert.NotNil(t, result) @@ -777,40 +754,39 @@ func TestProcessMatchers(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - splitChange := &dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Till: 1, Since: 1, Splits: []dtos.SplitDTO{ - { - Name: "split1", - Status: Active, - Conditions: []dtos.ConditionDTO{ - { - ConditionType: "NEW_MATCHER", - Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, - MatcherGroup: dtos.MatcherGroupDTO{ - Matchers: []dtos.MatcherDTO{ - {MatcherType: "NEW_MATCHER", KeySelector: nil}, - }, + featureFlags := []dtos.SplitDTO{ + { + Name: "split1", + Status: Active, + Conditions: []dtos.ConditionDTO{ + { + ConditionType: "NEW_MATCHER", + Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + {MatcherType: "NEW_MATCHER", KeySelector: nil}, }, }, }, }, - { - Name: "split2", - Status: Active, - Conditions: []dtos.ConditionDTO{ - { - ConditionType: grammar.ConditionTypeRollout, - Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, - MatcherGroup: dtos.MatcherGroupDTO{ - Matchers: []dtos.MatcherDTO{ - {MatcherType: grammar.MatcherTypeAllKeys, KeySelector: nil}, - }, + }, + { + Name: "split2", + Status: Active, + Conditions: []dtos.ConditionDTO{ + { + ConditionType: grammar.ConditionTypeRollout, + Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + {MatcherType: grammar.MatcherTypeAllKeys, KeySelector: nil}, }, }, }, }, - }}} - toAdd, _ := splitUpdater.processFeatureFlagChanges(splitChange) + }} + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + toAdd, _ := splitUpdater.processFeatureFlagChanges(response) assert.Equal(t, grammar.ConditionTypeWhitelist, toAdd[0].Conditions[0].ConditionType) assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) assert.Equal(t, grammar.ConditionTypeRollout, toAdd[1].Conditions[0].ConditionType) diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8481d04f..ea2064f7 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -37,11 +37,10 @@ func TestSplitSyncTask(t *testing.T) { splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, - Since: 3, - Till: 3}, - }, nil).Once() + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) + response.SetFFSince(3) + response.SetFFTill(3) + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSuccessfulSyncCall: func(resource int, tm time.Time) { diff --git a/testdata/old_splits_mock.json b/testdata/old_splits_mock.json new file mode 100644 index 00000000..add7437a --- /dev/null +++ b/testdata/old_splits_mock.json @@ -0,0 +1,5 @@ +{ + "splits": [%s], + "since": 1491244291288, + "till": 1491244291288 +} \ No newline at end of file From 20568cca871eadcbda361ebe85dcfa9e2849fb5d Mon Sep 17 00:00:00 2001 From: nmayorsplit <104373752+nmayorsplit@users.noreply.github.com> Date: Tue, 7 Oct 2025 14:49:56 -0300 Subject: [PATCH 09/39] Delete .vscode/launch.json --- .vscode/launch.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 5c7247b4..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [] -} \ No newline at end of file From 96054a514218100a22024247ab7bc841bdda6753 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 7 Oct 2025 16:23:56 -0300 Subject: [PATCH 10/39] Add local response --- dtos/splitchangewrapper.go | 89 ++++++++++++++++++++++--- service/local/sanitizer.go | 2 +- service/local/splitFetcher.go | 8 +-- synchronizer/local_test.go | 8 +-- synchronizer/synchronizer_test.go | 12 +--- synchronizer/worker/split/split.go | 4 +- synchronizer/worker/split/split_test.go | 76 ++++++--------------- tasks/splitsync_test.go | 4 +- 8 files changed, 111 insertions(+), 92 deletions(-) diff --git a/dtos/splitchangewrapper.go b/dtos/splitchangewrapper.go index 915fb8b8..a5758940 100644 --- a/dtos/splitchangewrapper.go +++ b/dtos/splitchangewrapper.go @@ -12,12 +12,6 @@ type FFResponse interface { RBTill() int64 FFSince() int64 RBSince() int64 - SetFFTill(till int64) - SetFFSince(since int64) - SetRBTill(till int64) - SetRBSince(since int64) - ReplaceFF(featureFlags []SplitDTO) - ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) } type FFResponseV12 struct { @@ -56,7 +50,7 @@ func (f12 *FFResponseV12) RBTill() int64 { } func (f12 *FFResponseV12) FFSince() int64 { - return f12.FFSince() + return f12.SplitChanges.Since } func (f12 *FFResponseV12) RBSince() int64 { @@ -102,9 +96,9 @@ func NewFFResponseV13(data []byte) (FFResponse, error) { return nil, err } -func NewFFResponseWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO) FFResponse { - featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs}, - RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs}} +func NewFFResponseWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO, since int64, till int64, rbSince int64, rbTill int64) FFResponse { + featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs, Since: since, Till: till}, + RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs, Since: rbSince, Till: rbTill}} return &FFResponseV13{ SplitChanges: featureFlagChange, } @@ -161,3 +155,78 @@ func (f13 *FFResponseV13) ReplaceFF(featureFlags []SplitDTO) { func (f13 *FFResponseV13) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { f13.SplitChanges.RuleBasedSegments.RuleBasedSegments = ruleBasedSegments } + +type FFResponseLocalV13 struct { + SplitChanges SplitChangesDTO +} + +func NewFFResponseLocalV13(data []byte) (*FFResponseLocalV13, error) { + var splitChangesDto SplitChangesDTO + err := json.Unmarshal(data, &splitChangesDto) + if err == nil { + return &FFResponseLocalV13{ + SplitChanges: splitChangesDto, + }, nil + } + return nil, err +} + +func NewFFResponseLocalWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO, since int64, till int64, rbSince int64, rbTill int64) *FFResponseLocalV13 { + featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs, Since: since, Till: till}, + RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs, Since: rbSince, Till: rbTill}} + return &FFResponseLocalV13{ + SplitChanges: featureFlagChange, + } +} + +func (f *FFResponseLocalV13) FeatureFlags() []SplitDTO { + return f.SplitChanges.FeatureFlags.Splits +} + +func (f *FFResponseLocalV13) RuleBasedSegments() []RuleBasedSegmentDTO { + return f.SplitChanges.RuleBasedSegments.RuleBasedSegments +} + +func (f FFResponseLocalV13) NeedsAnotherFetch() bool { + return f.SplitChanges.FeatureFlags.Since == f.SplitChanges.FeatureFlags.Till && f.SplitChanges.RuleBasedSegments.Since == f.SplitChanges.RuleBasedSegments.Till +} + +func (f *FFResponseLocalV13) FFTill() int64 { + return f.SplitChanges.FeatureFlags.Till +} + +func (f *FFResponseLocalV13) RBTill() int64 { + return f.SplitChanges.RuleBasedSegments.Till +} + +func (f *FFResponseLocalV13) RBSince() int64 { + return f.SplitChanges.RuleBasedSegments.Since +} + +func (f *FFResponseLocalV13) SetFFTill(till int64) { + f.SplitChanges.FeatureFlags.Till = till +} + +func (f *FFResponseLocalV13) SetFFSince(since int64) { + f.SplitChanges.FeatureFlags.Since = since +} + +func (f *FFResponseLocalV13) SetRBTill(till int64) { + f.SplitChanges.RuleBasedSegments.Till = till +} + +func (f *FFResponseLocalV13) FFSince() int64 { + return f.SplitChanges.FeatureFlags.Since +} + +func (f *FFResponseLocalV13) SetRBSince(since int64) { + f.SplitChanges.RuleBasedSegments.Since = since +} + +func (f *FFResponseLocalV13) ReplaceFF(featureFlags []SplitDTO) { + f.SplitChanges.FeatureFlags.Splits = featureFlags +} + +func (f *FFResponseLocalV13) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { + f.SplitChanges.RuleBasedSegments.RuleBasedSegments = ruleBasedSegments +} diff --git a/service/local/sanitizer.go b/service/local/sanitizer.go index 9737c704..dfb46f5b 100644 --- a/service/local/sanitizer.go +++ b/service/local/sanitizer.go @@ -7,7 +7,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" ) -func splitSanitization(splitChange dtos.FFResponse) dtos.FFResponse { +func splitSanitization(splitChange *dtos.FFResponseLocalV13) *dtos.FFResponseLocalV13 { if splitChange.FFTill() < -1 { splitChange.SetFFTill(-1) } diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index e4927b63..717a3e22 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -217,8 +217,8 @@ func (f *FileSplitFetcher) parseSplitsYAML(data string) (d []dtos.SplitDTO) { return splits } -func (f *FileSplitFetcher) parseSplitsJson(data string) (dtos.FFResponse, error) { - splitChangesDto, err := dtos.NewFFResponseV13([]byte(data)) +func (f *FileSplitFetcher) parseSplitsJson(data string) (*dtos.FFResponseLocalV13, error) { + splitChangesDto, err := dtos.NewFFResponseLocalV13([]byte(data)) if err != nil { f.logger.Error(fmt.Sprintf("error: %v", err)) @@ -314,9 +314,7 @@ func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. } s.lastHash = currSum - responseToReturn := dtos.NewFFResponseWithFFRBV13(splits, nil) - responseToReturn.SetFFSince(fetchOptions.ChangeNumber()) - responseToReturn.SetFFTill(till) + responseToReturn := dtos.NewFFResponseWithFFRBV13(splits, nil, fetchOptions.ChangeNumber(), till, -1, -1) return responseToReturn, nil } diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 52571722..820fba3b 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -82,9 +82,7 @@ func TestLocalSyncAllOk(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) splitFetcher.On("Fetch", mock.MatchedBy(func(req *service.FlagRequestParams) bool { return req.ChangeNumber() == -1 @@ -119,9 +117,7 @@ func TestLocalPeriodicFetching(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index ccfab80d..39721f9e 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -96,9 +96,7 @@ func TestSyncAllErrorInSegments(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ @@ -165,9 +163,7 @@ func TestSyncAllOk(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) splitFetcher := &httpMocks.MockSplitFetcher{} splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ @@ -252,9 +248,7 @@ func TestPeriodicFetching(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) splitFetcher := &httpMocks.MockSplitFetcher{} splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{ diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 451ce03a..5768de72 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -316,7 +316,7 @@ func (s *UpdaterImpl) processFFChange(ffChange dtos.SplitChangeUpdate) *UpdateRe s.logger.Debug(fmt.Sprintf("updating feature flag %s", ffChange.FeatureFlag().Name)) featureFlags := make([]dtos.SplitDTO, 0, 1) featureFlags = append(featureFlags, *ffChange.FeatureFlag()) - splitChanges := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + splitChanges := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, ffChange.BaseUpdate.ChangeNumber(), ffChange.BaseUpdate.ChangeNumber(), -1, -1) activeFFs, inactiveFFs := s.processFeatureFlagChanges(splitChanges) s.splitStorage.Update(activeFFs, inactiveFFs, ffChange.BaseUpdate.ChangeNumber()) s.runtimeTelemetry.RecordUpdatesFromSSE(telemetry.SplitUpdate) @@ -383,7 +383,7 @@ func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitCha } ruleBasedSegments := make([]dtos.RuleBasedSegmentDTO, 0, 1) ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) - ffResponse := dtos.NewFFResponseWithFFRBV13(nil, ruleBasedSegments) + ffResponse := dtos.NewFFResponseWithFFRBV13(nil, ruleBasedSegments, -1, -1, ruleBasedChange.ChangeNumber(), ruleBasedChange.ChangeNumber()) toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(ffResponse) s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index d790d788..ceb7bd93 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -106,9 +106,7 @@ func TestSplitSynchronizer(t *testing.T) { splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -156,16 +154,12 @@ func TestSplitSyncProcess(t *testing.T) { }}}}, } - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit4, mockedSplit5}, nil) - response1.SetFFSince(3) - response1.SetFFTill(3) + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit4, mockedSplit5}, nil, 3, 3, -1, -1) splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} @@ -211,9 +205,7 @@ func TestSplitTill(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, []dtos.RuleBasedSegmentDTO{mockedRuleBased1}) - response.SetFFSince(2) - response.SetFFTill(2) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, 2, 2, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Twice() @@ -246,19 +238,13 @@ func TestSplitTill(t *testing.T) { func TestByPassingCDN(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response.SetFFSince(1) - response.SetFFTill(2) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 1, 2, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response1.SetFFSince(2) - response1.SetFFTill(2) + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) - response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response2.SetFFSince(3) - response2.SetFFTill(3) + response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 3, 3, -1, -1) splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 })).Return(response2, nil).Once() @@ -291,18 +277,12 @@ func TestByPassingCDN(t *testing.T) { func TestByPassingCDNLimit(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response.SetFFSince(1) - response.SetFFTill(2) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 1, 2, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response1.SetFFSince(2) - response1.SetFFTill(2) + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) - response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil) - response2.SetFFSince(2) - response2.SetFFTill(2) + response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 })).Return(response2, nil).Times(10) @@ -360,9 +340,7 @@ func TestAddOrUpdateFeatureFlagNil(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(-1), nil).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(-1).Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil) - response.SetFFSince(2) - response.SetFFTill(2) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil, 2, 2, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryStorage, _ := inmemory.NewTelemetryStorage() @@ -434,9 +412,7 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(0), errors.New("error geting change number")).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(2)).Return().Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil) - response.SetFFSince(2) - response.SetFFTill(2) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil, 2, 2, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil) telemetryStorage, _ := inmemory.NewTelemetryStorage() @@ -458,7 +434,7 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { func TestGetActiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Active}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -470,7 +446,7 @@ func TestGetActiveFF(t *testing.T) { func TestGetInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Archived}, {Status: Archived}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) @@ -482,7 +458,7 @@ func TestGetInactiveFF(t *testing.T) { func TestGetActiveAndInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Archived}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -498,9 +474,7 @@ func TestSplitSyncWithSets(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set1"}} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -535,9 +509,7 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set2"}} mockedSplit4 := dtos.SplitDTO{Name: "split4", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set2"}} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, nil, 3, 3, -1, -1) splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -616,11 +588,7 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 2: till is equal to currentSince but less than currentRBSince till = 100 - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}) - response.SetFFSince(100) - response.SetFFTill(100) - response.SetRBSince(150) - response.SetRBTill(150) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}, 100, 100, 150, 150) splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) @@ -631,11 +599,7 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 3: till is equal to currentRBSince but greater than currentSince till = 150 - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}) - response1.SetFFSince(100) - response1.SetFFTill(100) - response1.SetRBSince(150) - response1.SetRBTill(150) + response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}, 100, 100, 150, 150) splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) @@ -785,7 +749,7 @@ func TestProcessMatchers(t *testing.T) { }, }, }} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil) + response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) toAdd, _ := splitUpdater.processFeatureFlagChanges(response) assert.Equal(t, grammar.ConditionTypeWhitelist, toAdd[0].Conditions[0].ConditionType) assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index ea2064f7..8bac3053 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -37,9 +37,7 @@ func TestSplitSyncTask(t *testing.T) { splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() splitMockFetcher := &fetcherMock.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil) - response.SetFFSince(3) - response.SetFFTill(3) + response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ From 37db2a1cd3108f97b2bfc197b08e1cd169215c6c Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 8 Oct 2025 10:56:21 -0300 Subject: [PATCH 11/39] Remove extra functions from splitchangewrapper --- dtos/splitchangewrapper.go | 84 ++--------- service/api/http_fetchers.go | 2 +- service/local/splitFetcher.go | 11 +- synchronizer/local_test.go | 20 ++- synchronizer/synchronizer_test.go | 30 +++- synchronizer/worker/split/split.go | 38 +++-- synchronizer/worker/split/split_test.go | 188 +++++++++++++++++++++--- tasks/splitsync_test.go | 10 +- 8 files changed, 255 insertions(+), 128 deletions(-) diff --git a/dtos/splitchangewrapper.go b/dtos/splitchangewrapper.go index a5758940..f5508da7 100644 --- a/dtos/splitchangewrapper.go +++ b/dtos/splitchangewrapper.go @@ -14,73 +14,49 @@ type FFResponse interface { RBSince() int64 } -type FFResponseV12 struct { +type FFResponseLegacy struct { SplitChanges SplitsDTO } -func NewFFResponseV12(data []byte) (FFResponse, error) { +func NewFFResponseLegacy(data []byte) (FFResponse, error) { var splitChangesDto SplitsDTO err := json.Unmarshal(data, &splitChangesDto) if err == nil { - return &FFResponseV12{ + return &FFResponseLegacy{ SplitChanges: splitChangesDto, }, nil } return nil, err } -func (f12 *FFResponseV12) NeedsAnotherFetch() bool { +func (f12 *FFResponseLegacy) NeedsAnotherFetch() bool { return f12.SplitChanges.Since == f12.SplitChanges.Till } -func (f12 *FFResponseV12) FeatureFlags() []SplitDTO { +func (f12 *FFResponseLegacy) FeatureFlags() []SplitDTO { return f12.SplitChanges.Splits } -func (wf12 *FFResponseV12) RuleBasedSegments() []RuleBasedSegmentDTO { +func (wf12 *FFResponseLegacy) RuleBasedSegments() []RuleBasedSegmentDTO { return []RuleBasedSegmentDTO{} } -func (f12 *FFResponseV12) FFTill() int64 { +func (f12 *FFResponseLegacy) FFTill() int64 { return f12.SplitChanges.Till } -func (f12 *FFResponseV12) RBTill() int64 { +func (f12 *FFResponseLegacy) RBTill() int64 { return 0 } -func (f12 *FFResponseV12) FFSince() int64 { +func (f12 *FFResponseLegacy) FFSince() int64 { return f12.SplitChanges.Since } -func (f12 *FFResponseV12) RBSince() int64 { +func (f12 *FFResponseLegacy) RBSince() int64 { return 0 } -func (f12 *FFResponseV12) SetFFTill(till int64) { - f12.SplitChanges.Till = till -} - -func (f12 *FFResponseV12) SetFFSince(since int64) { - f12.SplitChanges.Since = since -} - -func (f12 *FFResponseV12) SetRBTill(till int64) { - //no op -} - -func (f12 *FFResponseV12) SetRBSince(since int64) { - //no op -} - -func (f12 *FFResponseV12) ReplaceFF(featureFlags []SplitDTO) { - f12.SplitChanges.Splits = featureFlags -} - -func (f12 *FFResponseV12) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { - //no op -} - type FFResponseV13 struct { SplitChanges SplitChangesDTO } @@ -96,14 +72,6 @@ func NewFFResponseV13(data []byte) (FFResponse, error) { return nil, err } -func NewFFResponseWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO, since int64, till int64, rbSince int64, rbTill int64) FFResponse { - featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs, Since: since, Till: till}, - RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs, Since: rbSince, Till: rbTill}} - return &FFResponseV13{ - SplitChanges: featureFlagChange, - } -} - func (f13 *FFResponseV13) FeatureFlags() []SplitDTO { return f13.SplitChanges.FeatureFlags.Splits } @@ -128,34 +96,10 @@ func (f13 *FFResponseV13) RBSince() int64 { return f13.SplitChanges.RuleBasedSegments.Since } -func (f13 *FFResponseV13) SetFFTill(till int64) { - f13.SplitChanges.FeatureFlags.Till = till -} - -func (f13 *FFResponseV13) SetFFSince(since int64) { - f13.SplitChanges.FeatureFlags.Since = since -} - -func (f13 *FFResponseV13) SetRBTill(till int64) { - f13.SplitChanges.RuleBasedSegments.Till = till -} - func (f13 *FFResponseV13) FFSince() int64 { return f13.SplitChanges.FeatureFlags.Since } -func (f13 *FFResponseV13) SetRBSince(since int64) { - f13.SplitChanges.RuleBasedSegments.Since = since -} - -func (f13 *FFResponseV13) ReplaceFF(featureFlags []SplitDTO) { - f13.SplitChanges.FeatureFlags.Splits = featureFlags -} - -func (f13 *FFResponseV13) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { - f13.SplitChanges.RuleBasedSegments.RuleBasedSegments = ruleBasedSegments -} - type FFResponseLocalV13 struct { SplitChanges SplitChangesDTO } @@ -171,14 +115,6 @@ func NewFFResponseLocalV13(data []byte) (*FFResponseLocalV13, error) { return nil, err } -func NewFFResponseLocalWithFFRBV13(ffDTOs []SplitDTO, rbDTOs []RuleBasedSegmentDTO, since int64, till int64, rbSince int64, rbTill int64) *FFResponseLocalV13 { - featureFlagChange := SplitChangesDTO{FeatureFlags: FeatureFlagsDTO{Splits: ffDTOs, Since: since, Till: till}, - RuleBasedSegments: RuleBasedSegmentsDTO{RuleBasedSegments: rbDTOs, Since: rbSince, Till: rbTill}} - return &FFResponseLocalV13{ - SplitChanges: featureFlagChange, - } -} - func (f *FFResponseLocalV13) FeatureFlags() []SplitDTO { return f.SplitChanges.FeatureFlags.Splits } diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index c6bdcf1b..7d94bb69 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -61,7 +61,7 @@ func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. if common.StringFromRef(f.specVersion) == specs.FLAG_V1_3 { splitChangesDto, err = dtos.NewFFResponseV13(data) } else { - splitChangesDto, err = dtos.NewFFResponseV12(data) + splitChangesDto, err = dtos.NewFFResponseLegacy(data) } if err != nil { f.logger.Error("Error parsing split changes JSON ", err) diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index 717a3e22..4903ff59 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -314,8 +314,15 @@ func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. } s.lastHash = currSum - responseToReturn := dtos.NewFFResponseWithFFRBV13(splits, nil, fetchOptions.ChangeNumber(), till, -1, -1) - return responseToReturn, nil + return &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: splits, + Since: fetchOptions.ChangeNumber(), + Till: till, + }, + }, + }, nil } var _ service.SplitFetcher = &FileSplitFetcher{} diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 820fba3b..7c99f7d1 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -82,7 +82,15 @@ func TestLocalSyncAllOk(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3, + }, + }, + } splitFetcher.On("Fetch", mock.MatchedBy(func(req *service.FlagRequestParams) bool { return req.ChangeNumber() == -1 @@ -117,7 +125,15 @@ func TestLocalPeriodicFetching(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3, + }, + }, + } splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{SplitFetcher: splitFetcher} diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 39721f9e..ef3ef90d 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -96,7 +96,15 @@ func TestSyncAllErrorInSegments(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) splitFetcher := &httpMocks.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3, + }, + }, + } splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ @@ -163,7 +171,15 @@ func TestSyncAllOk(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3, + }, + }, + } splitFetcher := &httpMocks.MockSplitFetcher{} splitFetcher.On("Fetch", mock.Anything).Return(response, nil) splitAPI := api.SplitAPI{ @@ -248,7 +264,15 @@ func TestPeriodicFetching(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: true, Status: "ACTIVE", TrafficTypeName: "two"} logger := logging.NewLogger(&logging.LoggerOptions{}) - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2}, + Since: 3, + Till: 3, + }, + }, + } splitFetcher := &httpMocks.MockSplitFetcher{} splitFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() splitAPI := api.SplitAPI{ diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 5768de72..405e78af 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -102,13 +102,13 @@ func (s *UpdaterImpl) SetRuleBasedSegmentStorage(storage storage.RuleBasedSegmen } func (s *UpdaterImpl) processUpdate(splitChanges dtos.FFResponse) { - activeSplits, inactiveSplits := s.processFeatureFlagChanges(splitChanges) + activeSplits, inactiveSplits := s.processFeatureFlagChanges(splitChanges.FeatureFlags()) // Add/Update active splits s.splitStorage.Update(activeSplits, inactiveSplits, splitChanges.FFTill()) } func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges dtos.FFResponse) []string { - activeRB, inactiveRB, segments := s.processRuleBasedSegmentChanges(splitChanges) + activeRB, inactiveRB, segments := s.processRuleBasedSegmentChanges(splitChanges.RuleBasedSegments()) // Add/Update active splits s.ruleBasedSegmentStorage.Update(activeRB, inactiveRB, splitChanges.RBTill()) return segments @@ -144,9 +144,9 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) s.processUpdate(splitChanges) segmentReferences = s.processRuleBasedUpdate(splitChanges) - segmentReferences = appendSegmentNames(segmentReferences, splitChanges) + segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges) - largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges) + largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) if splitChanges.NeedsAnotherFetch() { s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC()) break @@ -219,8 +219,8 @@ func appendSplitNames(dst []string, splitChanges dtos.FFResponse) []string { return dst } -func appendSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { - for _, split := range splitChanges.FeatureFlags() { +func appendSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { + for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInSegment && matcher.UserDefinedSegment != nil { @@ -232,8 +232,8 @@ func appendSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { return dst } -func appendLargeSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { - for _, split := range splitChanges.FeatureFlags() { +func appendLargeSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { + for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInLargeSegment && matcher.UserDefinedLargeSegment != nil { @@ -253,14 +253,14 @@ func addIfNotExists(dst []string, seen map[string]struct{}, name string) []strin return dst } -func appendRuleBasedSegmentNames(dst []string, splitChanges dtos.FFResponse) []string { +func appendRuleBasedSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { seen := make(map[string]struct{}) // Inicializamos el mapa con lo que ya tiene dst para no duplicar tampoco ahí for _, name := range dst { seen[name] = struct{}{} } - for _, split := range splitChanges.FeatureFlags() { + for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == matcherTypeInRuleBasedSegment && matcher.UserDefinedSegment != nil { @@ -272,8 +272,7 @@ func appendRuleBasedSegmentNames(dst []string, splitChanges dtos.FFResponse) []s return dst } -func (s *UpdaterImpl) processFeatureFlagChanges(splitChanges dtos.FFResponse) ([]dtos.SplitDTO, []dtos.SplitDTO) { - featureFlags := splitChanges.FeatureFlags() +func (s *UpdaterImpl) processFeatureFlagChanges(featureFlags []dtos.SplitDTO) ([]dtos.SplitDTO, []dtos.SplitDTO) { toRemove := make([]dtos.SplitDTO, 0, len(featureFlags)) toAdd := make([]dtos.SplitDTO, 0, len(featureFlags)) @@ -316,14 +315,13 @@ func (s *UpdaterImpl) processFFChange(ffChange dtos.SplitChangeUpdate) *UpdateRe s.logger.Debug(fmt.Sprintf("updating feature flag %s", ffChange.FeatureFlag().Name)) featureFlags := make([]dtos.SplitDTO, 0, 1) featureFlags = append(featureFlags, *ffChange.FeatureFlag()) - splitChanges := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, ffChange.BaseUpdate.ChangeNumber(), ffChange.BaseUpdate.ChangeNumber(), -1, -1) - activeFFs, inactiveFFs := s.processFeatureFlagChanges(splitChanges) + activeFFs, inactiveFFs := s.processFeatureFlagChanges(featureFlags) s.splitStorage.Update(activeFFs, inactiveFFs, ffChange.BaseUpdate.ChangeNumber()) s.runtimeTelemetry.RecordUpdatesFromSSE(telemetry.SplitUpdate) updatedSplitNames = append(updatedSplitNames, ffChange.FeatureFlag().Name) - segmentReferences = appendSegmentNames(segmentReferences, splitChanges) - largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges) - ruleBasedSegmentReferences = appendRuleBasedSegmentNames(ruleBasedSegmentReferences, splitChanges) + segmentReferences = appendSegmentNames(segmentReferences, featureFlags) + largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, featureFlags) + ruleBasedSegmentReferences = appendRuleBasedSegmentNames(ruleBasedSegmentReferences, featureFlags) requiresFetch := false if len(ruleBasedSegmentReferences) > 0 && !s.ruleBasedSegmentStorage.Contains(ruleBasedSegmentReferences) { requiresFetch = true @@ -358,8 +356,7 @@ func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) [] return segments } -func (s *UpdaterImpl) processRuleBasedSegmentChanges(splitChanges dtos.FFResponse) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO, []string) { - ruleBasedSegments := splitChanges.RuleBasedSegments() +func (s *UpdaterImpl) processRuleBasedSegmentChanges(ruleBasedSegments []dtos.RuleBasedSegmentDTO) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO, []string) { toRemove := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) toAdd := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) segments := make([]string, 0) @@ -383,8 +380,7 @@ func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitCha } ruleBasedSegments := make([]dtos.RuleBasedSegmentDTO, 0, 1) ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) - ffResponse := dtos.NewFFResponseWithFFRBV13(nil, ruleBasedSegments, -1, -1, ruleBasedChange.ChangeNumber(), ruleBasedChange.ChangeNumber()) - toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(ffResponse) + toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(ruleBasedSegments) s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) return &UpdateResult{ diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index ceb7bd93..8c52cbdf 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -106,7 +106,15 @@ func TestSplitSynchronizer(t *testing.T) { splitMockStorage.On("ChangeNumber").Return(int64(-1), nil) splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -154,12 +162,28 @@ func TestSplitSyncProcess(t *testing.T) { }}}}, } - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit4, mockedSplit5}, nil, 3, 3, -1, -1) + response1 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit4, mockedSplit5}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() appMonitorMock := &hcMock.ApplicationMonitorMock{} @@ -205,7 +229,20 @@ func TestSplitTill(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, 2, 2, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, + Since: -1, + Till: -1, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Twice() @@ -238,13 +275,37 @@ func TestSplitTill(t *testing.T) { func TestByPassingCDN(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 1, 2, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 1, + Till: 2, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) + response1 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2, + }, + }, + } splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) - response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 3, 3, -1, -1) + response2 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 })).Return(response2, nil).Once() @@ -277,12 +338,37 @@ func TestByPassingCDN(t *testing.T) { func TestByPassingCDNLimit(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 1, 2, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 1, + Till: 2, + }, + }, + } + splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) + response1 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2, + }, + }, + } splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(response1, nil).Times(10) - response2 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1}, nil, 2, 2, -1, -1) + response2 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 2, + Till: 2, + }, + }, + } splitMockFetcher.On("Fetch", mock.MatchedBy(func(params *service.FlagRequestParams) bool { return *params.Till() == 2 })).Return(response2, nil).Times(10) @@ -340,7 +426,15 @@ func TestAddOrUpdateFeatureFlagNil(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(-1), nil).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(-1).Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil, 2, 2, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 2, + Till: 2, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryStorage, _ := inmemory.NewTelemetryStorage() @@ -412,7 +506,15 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { ffStorageMock := &mocks.SplitStorageMock{} ffStorageMock.On("ChangeNumber").Return(int64(0), errors.New("error geting change number")).Times(3) ffStorageMock.On("Update", mock.Anything, mock.Anything, int64(2)).Return().Once() - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, nil, 2, 2, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 2, + Till: 2, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil) telemetryStorage, _ := inmemory.NewTelemetryStorage() @@ -434,37 +536,34 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { func TestGetActiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Active}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(response) + actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 2) assert.Len(t, inactives, 0) } func TestGetInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Archived}, {Status: Archived}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(response) + actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 0) assert.Len(t, inactives, 2) } func TestGetActiveAndInactiveFF(t *testing.T) { featureFlags := []dtos.SplitDTO{{Status: Active}, {Status: Archived}} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) - actives, inactives := s.processFeatureFlagChanges(response) + actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 1) assert.Len(t, inactives, 1) } @@ -474,7 +573,15 @@ func TestSplitSyncWithSets(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set1"}} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -509,7 +616,15 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { mockedSplit2 := dtos.SplitDTO{Name: "split2", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set4"}} mockedSplit3 := dtos.SplitDTO{Name: "split3", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set5", "set2"}} mockedSplit4 := dtos.SplitDTO{Name: "split4", Killed: false, Status: "ACTIVE", TrafficTypeName: "one", Sets: []string{"set2"}} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3, mockedSplit4}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() @@ -588,7 +703,20 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 2: till is equal to currentSince but less than currentRBSince till = 100 - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}, 100, 100, 150, 150) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 100, + Till: 100, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + Since: 150, + Till: 150, + }, + }, + } splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) @@ -599,7 +727,20 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { // Test case 3: till is equal to currentRBSince but greater than currentSince till = 150 - response1 := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{}, []dtos.RuleBasedSegmentDTO{}, 100, 100, 150, 150) + response1 := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 100, + Till: 100, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + Since: 150, + Till: 150, + }, + }, + } splitMockFetcher.On("Fetch", mock.Anything).Return(response1, nil).Once() result, err = splitUpdater.SynchronizeSplits(&till) assert.Nil(t, err) @@ -749,8 +890,7 @@ func TestProcessMatchers(t *testing.T) { }, }, }} - response := dtos.NewFFResponseWithFFRBV13(featureFlags, nil, -1, -1, -1, -1) - toAdd, _ := splitUpdater.processFeatureFlagChanges(response) + toAdd, _ := splitUpdater.processFeatureFlagChanges(featureFlags) assert.Equal(t, grammar.ConditionTypeWhitelist, toAdd[0].Conditions[0].ConditionType) assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) assert.Equal(t, grammar.ConditionTypeRollout, toAdd[1].Conditions[0].ConditionType) diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8bac3053..a3b3ab53 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -37,7 +37,15 @@ func TestSplitSyncTask(t *testing.T) { splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1, mockedSplit2}, []dtos.SplitDTO{mockedSplit3}, int64(3)).Once() splitMockFetcher := &fetcherMock.MockSplitFetcher{} - response := dtos.NewFFResponseWithFFRBV13([]dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, nil, 3, 3, -1, -1) + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1, mockedSplit2, mockedSplit3}, + Since: 3, + Till: 3, + }, + }, + } splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ From a2e103c2c69e25120679020147bdce2c29681a73 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 8 Oct 2025 14:52:30 -0300 Subject: [PATCH 12/39] Updates test cases to asserts --- service/api/http_fetchers_test.go | 340 ++++++++--------------------- synchronizer/worker/split/split.go | 5 +- 2 files changed, 92 insertions(+), 253 deletions(-) diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index ce654114..b4518c97 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -18,6 +18,7 @@ import ( "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api/specs" "github.com/splitio/go-toolkit/v5/logging" + "github.com/stretchr/testify/assert" ) var splitsMock, _ = ioutil.ReadFile("../../testdata/splits_mock.json") @@ -29,24 +30,12 @@ func TestSpitChangesFetch11(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get(CacheControlHeader) != CacheControlNoCache { - t.Error("wrong cache control header") - } - if r.URL.Query().Get("since") != "123456" { - t.Error("wrong since") - } - if r.URL.Query().Get("till") != "" { - t.Error("wrong till") - } - if r.URL.Query().Get("sets") != "" { - t.Error("wrong sets") - } - if r.URL.Query().Get("s") != specs.FLAG_V1_1 { - t.Error("wrong spec") - } - if r.URL.RawQuery != "s=1.1&since=123456&rbSince=123456" { - t.Error("wrong query params") - } + assert.Equal(t, CacheControlNoCache, r.Header.Get(CacheControlHeader), "wrong cache control header") + assert.Equal(t, "123456", r.URL.Query().Get("since"), "wrong since") + assert.Equal(t, "", r.URL.Query().Get("till"), "wrong till") + assert.Equal(t, "", r.URL.Query().Get("sets"), "wrong sets") + assert.Equal(t, specs.FLAG_V1_1, r.URL.Query().Get("s"), "wrong spec") + assert.Equal(t, "s=1.1&since=123456&rbSince=123456", r.URL.RawQuery, "wrong query params") fmt.Fprintln(w, fmt.Sprintf(string(oldSplitMock), splitMock)) })) defer ts.Close() @@ -63,50 +52,24 @@ func TestSpitChangesFetch11(t *testing.T) { ) splitChangesDTO, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithChangeNumberRB(123456)) - if err != nil { - t.Error(err) - } - - if splitChangesDTO.FFTill() != 1491244291288 || - splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2" { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations == nil { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations["of"] != "" { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations["on"] != "{\"color\": \"blue\",\"size\": 13}" { - t.Error("DTO mal formed") - } + assert.Equal(t, nil, err, err) + assert.False(t, splitChangesDTO.FFTill() != 1491244291288 || + splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2", "DTO mal formed") + assert.NotEqual(t, nil, splitChangesDTO.FeatureFlags()[0].Configurations, "DTO mal formed") + assert.Equal(t, "", splitChangesDTO.FeatureFlags()[0].Configurations["of"], "DTO mal formed") + assert.Equal(t, "{\"color\": \"blue\",\"size\": 13}", splitChangesDTO.FeatureFlags()[0].Configurations["on"], "DTO mal formed") } func TestSpitChangesFetch(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get(CacheControlHeader) != CacheControlNoCache { - t.Error("wrong cache control header") - } - if r.URL.Query().Get("since") != "123456" { - t.Error("wrong since") - } - if r.URL.Query().Get("till") != "" { - t.Error("wrong till") - } - if r.URL.Query().Get("sets") != "" { - t.Error("wrong sets") - } - if r.URL.Query().Get("s") != specs.FLAG_V1_3 { - t.Error("wrong spec") - } - if r.URL.RawQuery != "s=1.3&since=123456&rbSince=123456" { - t.Error("wrong query params") - } + assert.Equal(t, CacheControlNoCache, r.Header.Get(CacheControlHeader), "wrong cache control header") + assert.Equal(t, "123456", r.URL.Query().Get("since"), "wrong since") + assert.Equal(t, "", r.URL.Query().Get("till"), "wrong till") + assert.Equal(t, "", r.URL.Query().Get("sets"), "wrong sets") + assert.Equal(t, specs.FLAG_V1_3, r.URL.Query().Get("s"), "wrong spec") + assert.Equal(t, "s=1.3&since=123456&rbSince=123456", r.URL.RawQuery, "wrong query params") fmt.Fprintln(w, fmt.Sprintf(string(splitsMock), splitMock)) })) defer ts.Close() @@ -123,26 +86,12 @@ func TestSpitChangesFetch(t *testing.T) { ) splitChangesDTO, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithChangeNumberRB(123456)) - if err != nil { - t.Error(err) - } - - if splitChangesDTO.FFTill() != 1491244291288 || - splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2" { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations == nil { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations["of"] != "" { - t.Error("DTO mal formed") - } - - if splitChangesDTO.FeatureFlags()[0].Configurations["on"] != "{\"color\": \"blue\",\"size\": 13}" { - t.Error("DTO mal formed") - } + assert.Equal(t, nil, err, err) + assert.False(t, splitChangesDTO.FFTill() != 1491244291288 || + splitChangesDTO.FeatureFlags()[0].Name != "DEMO_MURMUR2", "DTO mal formed") + assert.NotEqual(t, nil, splitChangesDTO.FeatureFlags()[0].Configurations, "DTO mal formed") + assert.Equal(t, "", splitChangesDTO.FeatureFlags()[0].Configurations["of"], "DTO mal formed") + assert.Equal(t, "{\"color\": \"blue\",\"size\": 13}", splitChangesDTO.FeatureFlags()[0].Configurations["on"], "DTO mal formed") } func TestSpitChangesFetchWithFlagOptions(t *testing.T) { @@ -169,32 +118,17 @@ func TestSpitChangesFetchWithFlagOptions(t *testing.T) { ) _, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if queryParams.Has("till") { - t.Error("Expected to not have till") - } + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.False(t, queryParams.Has("till"), "Expected to not have till") + expectedTill := int64(10000) _, err = splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithTill(expectedTill)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if queryParams.Get("till") != "10000" { - t.Error("Expected to have till") - } + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.Equal(t, "10000", queryParams.Get("till"), "Expected to have till") } func TestSpitChangesFetchWithFlagSetsFilter(t *testing.T) { @@ -222,33 +156,23 @@ func TestSpitChangesFetchWithFlagSetsFilter(t *testing.T) { ) _, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if queryParams.Has("till") { - t.Error("Expected to not have till") - } - if !queryParams.Has("sets") { - t.Error("Expected to have sets") - } + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.False(t, queryParams.Has("till"), "Expected to not have till") + assert.True(t, queryParams.Has("sets"), "Expected to have sets") + asString := queryParams.Get("sets") asArray := strings.Split(asString, ",") setsToTest := make(map[string]struct{}) for _, featureFlag := range asArray { setsToTest[featureFlag] = struct{}{} } - if _, ok := setsToTest["one"]; !ok { - t.Error("Expected one to be present") - } - if _, ok := setsToTest["two"]; !ok { - t.Error("Expected two to be present") - } + + _, ok := setsToTest["one"] + assert.True(t, ok, "one key not found in setsToTest") + _, ok1 := setsToTest["two"] + assert.True(t, ok1, "two key not found in setsToTest") } func TestSpitChangesFetchWithAll(t *testing.T) { @@ -281,36 +205,24 @@ func TestSpitChangesFetchWithAll(t *testing.T) { ) _, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithTill(10000).WithChangeNumberRB(123456)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if !queryParams.Has("till") { - t.Error("Expected to have till") - } - if !queryParams.Has("sets") { - t.Error("Expected to have sets") - } - if queryParams.Get("s") != specs.FLAG_V1_1 { - t.Error("Expected to have spec") - } + + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.True(t, queryParams.Has("till"), "Expected to have till") + assert.True(t, queryParams.Has("sets"), "Expected to have sets") + assert.Equal(t, specs.FLAG_V1_1, queryParams.Get("s"), "Expected to have spec") + asString := queryParams.Get("sets") asArray := strings.Split(asString, ",") setsToTest := make(map[string]struct{}) for _, featureFlag := range asArray { setsToTest[featureFlag] = struct{}{} } - if _, ok := setsToTest["one"]; !ok { - t.Error("Expected one to be present") - } - if _, ok := setsToTest["two"]; !ok { - t.Error("Expected two to be present") - } + _, ok := setsToTest["one"] + assert.True(t, ok, "one key not found in setsToTest") + _, ok1 := setsToTest["two"] + assert.True(t, ok1, "two key not found in setsToTest") } func TestSpitChangesFetchHTTPError(t *testing.T) { @@ -333,9 +245,7 @@ func TestSpitChangesFetchHTTPError(t *testing.T) { ) _, err := splitFetcher.Fetch(service.MakeFlagRequestParams()) - if err == nil { - t.Error("Error expected but not found") - } + assert.NotEqual(t, nil, err, "Error expected but not found", err) } func TestSegmentChangesFetch(t *testing.T) { @@ -357,13 +267,8 @@ func TestSegmentChangesFetch(t *testing.T) { ) segmentFetched, err := segmentFetcher.Fetch("employees", service.MakeSegmentRequestParams()) - if err != nil { - t.Error("Error fetching segment", err) - return - } - if segmentFetched.Name != "employees" { - t.Error("Fetched segment mal-formed") - } + assert.Equal(t, nil, err, "Error fetching segment", err) + assert.Equal(t, "employees", segmentFetched.Name, "Fetched segment mal-formed") } func TestSegmentChangesFetchHTTPError(t *testing.T) { @@ -386,9 +291,7 @@ func TestSegmentChangesFetchHTTPError(t *testing.T) { ) _, err := segmentFetcher.Fetch("employees", service.MakeSegmentRequestParams()) - if err == nil { - t.Error("Error expected but not found") - } + assert.NotEqual(t, nil, err, "Error expected but not found", err) } func TestSegmentChangesFetchWithFlagOptions(t *testing.T) { @@ -415,32 +318,17 @@ func TestSegmentChangesFetchWithFlagOptions(t *testing.T) { ) _, err := segmentFetcher.Fetch("employees", service.MakeSegmentRequestParams().WithChangeNumber(123456)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if queryParams.Has("till") { - t.Error("Expected to not have till") - } + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.False(t, queryParams.Has("till"), "Expected to. not have till") + expectedTill := int64(10000) _, err = segmentFetcher.Fetch("employees", service.MakeSegmentRequestParams().WithTill(expectedTill).WithChangeNumber(123456)) - if err != nil { - t.Error(err) - } - if cacheControl != CacheControlNoCache { - t.Error("Wrong header sent") - } - if queryParams.Get("since") != "123456" { - t.Error("Expected to have since") - } - if queryParams.Get("till") != "10000" { - t.Error("Expected to have till") - } + assert.Equal(t, nil, err, err) + assert.Equal(t, CacheControlNoCache, cacheControl, "Wrong header sent") + assert.Equal(t, "123456", queryParams.Get("since"), "Expected to have since") + assert.Equal(t, "10000", queryParams.Get("till"), "Expected to have till") } // Large Segments tests @@ -479,17 +367,9 @@ func TestFetchCsvFormatHappyPath(t *testing.T) { } result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err != nil { - t.Error("Error should be nil") - } - - if result.Name != "large_segment_test" { - t.Error("LS name should be large_segment_test. Actual: ", result.Name) - } - - if len(result.Keys) != 1500 { - t.Error("Keys lenght should be 1500. Actual: ", len(result.Keys)) - } + assert.Equal(t, nil, err, err) + assert.Equal(t, "large_segment_test", result.Name, "LS name should be large_segment_test. Actual: ", result.Name) + assert.Equal(t, 1500, len(result.Keys), "Keys lenght should be 1500. Actual: ", len(result.Keys)) } func TestFetchCsvMultipleColumns(t *testing.T) { @@ -522,17 +402,10 @@ func TestFetchCsvMultipleColumns(t *testing.T) { lsName := "large_segment_test" lsRfdResponseDTO, err := fetcher.Fetch(lsName, &service.SegmentRequestParams{}) - if err != nil { - t.Error("Error should be nil") - } + assert.Equal(t, nil, err, err) result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err.Error() != "unssuported file content. The file has multiple columns" { - t.Error("Error should not be nil") - } - - if result != (*dtos.LargeSegment)(nil) { - t.Error("Response.Data should be nil") - } + assert.Equal(t, "unssuported file content. The file has multiple columns", err.Error(), "Error should not be nil") + assert.Equal(t, (*dtos.LargeSegment)(nil), result, "Response.Data should be nil") } func TestFetchCsvFormatWithOtherVersion(t *testing.T) { @@ -567,17 +440,10 @@ func TestFetchCsvFormatWithOtherVersion(t *testing.T) { lsName := "large_segment_test" lsRfdResponseDTO, err := fetcher.Fetch(lsName, &service.SegmentRequestParams{}) - if err != nil { - t.Error("Error should be nil") - } + assert.Equal(t, nil, err, err) result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err.Error() != "unsupported csv version 1111.0" { - t.Error("Error should not be nil") - } - - if result != (*dtos.LargeSegment)(nil) { - t.Error("Response.Data should be nil") - } + assert.Equal(t, "unsupported csv version 1111.0", err.Error(), "Error should not be nil") + assert.Equal(t, (*dtos.LargeSegment)(nil), result, "Response.Data should be nil") } func TestFetchUnknownFormat(t *testing.T) { @@ -612,17 +478,10 @@ func TestFetchUnknownFormat(t *testing.T) { lsName := "large_segment_test" lsRfdResponseDTO, err := fetcher.Fetch(lsName, &service.SegmentRequestParams{}) - if err != nil { - t.Error("Error should be nil") - } + assert.Equal(t, nil, err, err) result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err.Error() != "unsupported file format" { - t.Error("Error should not be nil") - } - - if result != (*dtos.LargeSegment)(nil) { - t.Error("Response.Data should be nil") - } + assert.Equal(t, "unsupported file format", err.Error(), "Error should not be nil") + assert.Equal(t, (*dtos.LargeSegment)(nil), result, "Response.Data should be nil") } func TestFetchAPIError(t *testing.T) { @@ -647,9 +506,7 @@ func TestFetchAPIError(t *testing.T) { ) rfe, err := fetcher.Fetch("large_segment_test", &service.SegmentRequestParams{}) - if err.Error() != "500 Internal Server Error" { - t.Error("Error should be 500") - } + assert.Equal(t, "500 Internal Server Error", err.Error(), "Error should be 500") if rfe != nil { t.Error("RequestForExport should be nil") } @@ -684,17 +541,10 @@ func TestFetchDownloadServerError(t *testing.T) { lsName := "large_segment_test" lsRfdResponseDTO, err := fetcher.Fetch(lsName, &service.SegmentRequestParams{}) - if err != nil { - t.Error("Error should be nil") - } + assert.Equal(t, nil, err, "Error should be nil") result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err.Error() != "500 Internal Server Error" { - t.Error("Error should not be nil") - } - - if result != (*dtos.LargeSegment)(nil) { - t.Error("Response.Data should be nil") - } + assert.Equal(t, "500 Internal Server Error", err.Error(), "Error should not be nil") + assert.Equal(t, (*dtos.LargeSegment)(nil), result, "Response.Data should be nil") } func TestFetchWithPost(t *testing.T) { @@ -729,21 +579,11 @@ func TestFetchWithPost(t *testing.T) { lsName := "large_segment_test" lsRfdResponseDTO, err := fetcher.Fetch(lsName, &service.SegmentRequestParams{}) - if err != nil { - t.Error("Error should be nil") - } + assert.Equal(t, nil, err, "Error should be nil") result, err := fetcher.DownloadFile(lsName, lsRfdResponseDTO) - if err != nil { - t.Error("Error shuld be nil") - } - - if result.Name != "large_segment_test" { - t.Error("LS name should be large_segment_test. Actual: ", result.Name) - } - - if len(result.Keys) != 1500 { - t.Error("Keys lenght should be 1500. Actual: ", len(result.Keys)) - } + assert.Equal(t, nil, err, "Error should be nil") + assert.Equal(t, "large_segment_test", result.Name, "LS name should be large_segment_test. Actual: ", result.Name) + assert.Equal(t, 1500, len(result.Keys), "Keys lenght should be 1500. Actual: ", len(result.Keys)) } func buildLargeSegmentRFDResponseDTO(url string) dtos.LargeSegmentRFDResponseDTO { diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 405e78af..5dbf404f 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -145,7 +145,7 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda s.processUpdate(splitChanges) segmentReferences = s.processRuleBasedUpdate(splitChanges) segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) - updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges) + updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges.FeatureFlags()) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) if splitChanges.NeedsAnotherFetch() { s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC()) @@ -211,8 +211,7 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { return internalSyncResultCDNBypass.updateResult, nil } -func appendSplitNames(dst []string, splitChanges dtos.FFResponse) []string { - featureFlags := splitChanges.FeatureFlags() +func appendSplitNames(dst []string, featureFlags []dtos.SplitDTO) []string { for idx := range featureFlags { dst = append(dst, featureFlags[idx].Name) } From 2fa65c8c70f2722382f2aa256790c6a9486186c6 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Wed, 8 Oct 2025 16:17:34 -0300 Subject: [PATCH 13/39] draft of retry in case is proxy --- service/api/http_fetchers.go | 2 +- service/api/http_fetchers_test.go | 5 +- service/commons.go | 13 +++ service/commons_test.go | 89 ++++++++------------ synchronizer/local.go | 2 +- synchronizer/local_test.go | 1 + synchronizer/synchronizer_test.go | 14 ++-- synchronizer/worker/split/split.go | 105 +++++++++++++++++++++--- synchronizer/worker/split/split_test.go | 50 +++++------ tasks/splitsync_test.go | 2 +- 10 files changed, 181 insertions(+), 102 deletions(-) diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 630e0607..cb206528 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -48,7 +48,7 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. // Fetch makes an http call to the split backend and returns the list of updated splits func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { - fetchOptions.WithFlagSetsFilter(f.flagSetsFilter).WithSpecVersion(f.specVersion) + fetchOptions.WithFlagSetsFilter(f.flagSetsFilter) data, err := f.fetchRaw("/splitChanges", fetchOptions) if err != nil { f.logger.Error("Error fetching split changes ", err) diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index 0d380bdb..6e752f2c 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -17,6 +17,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) @@ -61,7 +62,7 @@ func TestSpitChangesFetch(t *testing.T) { dtos.Metadata{}, ) - splitChangesDTO, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithChangeNumberRB(123456)) + splitChangesDTO, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithChangeNumberRB(123456).WithSpecVersion(common.StringRef(specs.FLAG_V1_1))) if err != nil { t.Error(err) } @@ -219,7 +220,7 @@ func TestSpitChangesFetchWithAll(t *testing.T) { dtos.Metadata{}, ) - _, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithTill(10000).WithChangeNumberRB(123456)) + _, err := splitFetcher.Fetch(service.MakeFlagRequestParams().WithChangeNumber(123456).WithTill(10000).WithChangeNumberRB(123456).WithSpecVersion(common.StringRef(specs.FLAG_V1_1))) if err != nil { t.Error(err) } diff --git a/service/commons.go b/service/commons.go index bdd56681..08a33c5b 100644 --- a/service/commons.go +++ b/service/commons.go @@ -53,6 +53,19 @@ func MakeFlagRequestParams() *FlagRequestParams { } } +func (s *FlagRequestParams) Copy() *FlagRequestParams { + return &FlagRequestParams{ + baseRequestParams: baseRequestParams{ + cacheControlHeaders: s.cacheControlHeaders, + }, + changeNumber: s.changeNumber, + changeNumberRB: s.changeNumberRB, + flagSetsFilter: s.flagSetsFilter, + specVersion: s.specVersion, + till: s.till, + } +} + // WithCacheControl sets the cache control header func (s *FlagRequestParams) WithCacheControl(cacheControl bool) *FlagRequestParams { s.cacheControlHeaders = cacheControl diff --git a/service/commons_test.go b/service/commons_test.go index 9617059a..2f203c31 100644 --- a/service/commons_test.go +++ b/service/commons_test.go @@ -5,7 +5,10 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-toolkit/v5/common" + + "github.com/stretchr/testify/assert" ) func TestSplitFetchOptions(t *testing.T) { @@ -14,24 +17,29 @@ func TestSplitFetchOptions(t *testing.T) { req, _ := http.NewRequest("GET", "test", nil) fetchOptions.Apply(req) - if req.Header.Get(cacheControl) != cacheControlNoCache { - t.Error("Cache control header not set") - } - if req.URL.Query().Get(since) != "123456" { - t.Error("Change number not set") - } - if req.URL.Query().Get(spec) != specs.FLAG_V1_1 { - t.Error("Spec version not set") - } - if req.URL.Query().Get(sets) != "filter" { - t.Error("Flag sets filter not set") - } - if req.URL.Query().Get(till) != "123" { - t.Error("Till not set") - } - if req.URL.String() != "test?s=1.1&since=123456&rbSince=123456&sets=filter&till=123" { - t.Error("Query params not set correctly, expected: test?s=v1&since=123456&sets=filter&till=123, got:", req.URL.String()) - } + assert.Equal(t, cacheControlNoCache, req.Header.Get(cacheControl)) + assert.Equal(t, "123456", req.URL.Query().Get(since)) + assert.Equal(t, specs.FLAG_V1_1, req.URL.Query().Get(spec)) + assert.Equal(t, "filter", req.URL.Query().Get(sets)) + assert.Equal(t, "123", req.URL.Query().Get(till)) + assert.Equal(t, "123456", req.URL.Query().Get(rbSince)) + assert.Equal(t, "test?s=1.1&since=123456&rbSince=123456&sets=filter&till=123", req.URL.String()) +} + +func TestCopy(t *testing.T) { + fetchOptions := MakeFlagRequestParams().WithChangeNumber(123456).WithFlagSetsFilter("filter").WithTill(*common.Int64Ref(123)).WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumberRB(123456) + copyOptions := fetchOptions.Copy().WithSpecVersion(common.StringRef(specs.FLAG_V1_2)).WithChangeNumber(654321).WithChangeNumberRB(654321).WithFlagSetsFilter("newfilter").WithTill(*common.Int64Ref(321)) + + assert.Equal(t, fetchOptions.ChangeNumber(), int64(123456)) + assert.Equal(t, copyOptions.ChangeNumber(), int64(654321)) + assert.Equal(t, fetchOptions.ChangeNumberRB(), int64(123456)) + assert.Equal(t, copyOptions.ChangeNumberRB(), int64(654321)) + assert.Equal(t, *fetchOptions.Till(), int64(123)) + assert.Equal(t, *copyOptions.Till(), int64(321)) + assert.Equal(t, *fetchOptions.specVersion, specs.FLAG_V1_1) + assert.Equal(t, *copyOptions.specVersion, specs.FLAG_V1_2) + assert.Equal(t, fetchOptions.flagSetsFilter, "filter") + assert.Equal(t, copyOptions.flagSetsFilter, "newfilter") } func TestSegmentRequestParams(t *testing.T) { @@ -39,20 +47,10 @@ func TestSegmentRequestParams(t *testing.T) { req, _ := http.NewRequest("GET", "test", nil) fetchOptions.Apply(req) - if req.Header.Get(cacheControl) != cacheControlNoCache { - t.Error("Cache control header not set") - } - - if req.URL.Query().Get(since) != "123456" { - t.Error("Change number not set") - } - if req.URL.Query().Get(till) != "123" { - t.Error("Till not set") - } - - if req.URL.String() != "test?since=123456&till=123" { - t.Error("Query params not set correctly, expected: test?s=v1&since=123456&till=123, got:", req.URL.String()) - } + assert.Equal(t, cacheControlNoCache, req.Header.Get(cacheControl)) + assert.Equal(t, "123456", req.URL.Query().Get(since)) + assert.Equal(t, "123", req.URL.Query().Get(till)) + assert.Equal(t, "test?since=123456&till=123", req.URL.String()) } func TestAuthRequestParams(t *testing.T) { @@ -60,39 +58,24 @@ func TestAuthRequestParams(t *testing.T) { req, _ := http.NewRequest("GET", "test", nil) fetchOptions.Apply(req) - if req.Header.Get(cacheControl) != cacheControlNoCache { - t.Error("Cache control header not set") - } - if req.URL.Query().Get(spec) != specs.FLAG_V1_1 { - t.Error("Spec version not set") - } - if req.URL.String() != "test?s=1.1" { - t.Error("Query params not set correctly, expected: test?s=v1, got:", req.URL.String()) - } + assert.Equal(t, cacheControlNoCache, req.Header.Get(cacheControl)) + assert.Equal(t, "1.1", req.URL.Query().Get(spec)) + assert.Equal(t, "test?s=1.1", req.URL.String()) } func TestOverrideCacheControl(t *testing.T) { flagParams := MakeFlagRequestParams().WithCacheControl(false) req, _ := http.NewRequest("GET", "test", nil) flagParams.Apply(req) - - if req.Header.Get(cacheControl) != "" { - t.Error("Cache control header should not be set") - } + assert.Equal(t, "", req.Header.Get(cacheControl)) segmentParams := MakeSegmentRequestParams().WithCacheControl(false) req, _ = http.NewRequest("GET", "test", nil) segmentParams.Apply(req) - - if req.Header.Get(cacheControl) != "" { - t.Error("Cache control header should not be set") - } + assert.Equal(t, "", req.Header.Get(cacheControl)) authParams := MakeAuthRequestParams(nil).WithCacheControl(false) req, _ = http.NewRequest("GET", "test", nil) authParams.Apply(req) - - if req.Header.Get(cacheControl) != "" { - t.Error("Cache control header should not be set") - } + assert.Equal(t, "", req.Header.Get(cacheControl)) } diff --git a/synchronizer/local.go b/synchronizer/local.go index 0a7963e6..a20b058a 100644 --- a/synchronizer/local.go +++ b/synchronizer/local.go @@ -37,7 +37,7 @@ type LocalConfig struct { // NewLocal creates new Local func NewLocal(cfg *LocalConfig, splitAPI *api.SplitAPI, splitStorage storage.SplitStorage, segmentStorage storage.SegmentStorage, largeSegmentStorage storage.LargeSegmentsStorage, ruleBasedStorage storage.RuleBasedSegmentsStorage, logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer, hcMonitor application.MonitorProducerInterface) Synchronizer { ruleBuilder := grammar.NewRuleBuilder(segmentStorage, ruleBasedStorage, largeSegmentStorage, cfg.FfRulesAccepted, cfg.RbRulesAccepted, logger, nil) - splitUpdater := split.NewSplitUpdater(splitStorage, ruleBasedStorage, splitAPI.SplitFetcher, logger, runtimeTelemetry, hcMonitor, flagsets.NewFlagSetFilter(cfg.FlagSets), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitStorage, ruleBasedStorage, splitAPI.SplitFetcher, logger, runtimeTelemetry, hcMonitor, flagsets.NewFlagSetFilter(cfg.FlagSets), ruleBuilder, false) splitUpdater.SetRuleBasedSegmentStorage(ruleBasedStorage) workers := Workers{ diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 25d83f82..e77dd344 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -55,6 +55,7 @@ func TestLocalSyncAllError(t *testing.T) { appMonitorMock, flagSetFilter, ruleBuilder, + false, ) splitUpdater.SetRuleBasedSegmentStorage(ruleBasedSegmentMockStorage) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 539470fd..12bf2f57 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -64,7 +64,7 @@ func TestSyncAllErrorSplits(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) workers := Workers{ SplitUpdater: splitUpdater, @@ -133,7 +133,7 @@ func TestSyncAllErrorInSegments(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -221,7 +221,7 @@ func TestSyncAllOk(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -306,7 +306,7 @@ func TestPeriodicFetching(t *testing.T) { ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -446,7 +446,7 @@ func TestSplitUpdateWorkerCNGreaterThanFFChange(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), } splitTasks := SplitTasks{ @@ -905,7 +905,7 @@ func TestLocalKill(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, storageMock.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, storageMock.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), } splitTasks := SplitTasks{ SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), @@ -969,7 +969,7 @@ func TestSplitUpdateWithReferencedSegments(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), TelemetryRecorder: telemetry.NewTelemetrySynchronizer(telemetryMockStorage, nil, nil, nil, nil, dtos.Metadata{}, telemetryMockStorage), diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index dd106087..389bc522 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -1,7 +1,9 @@ package split import ( + "errors" "fmt" + "net/http" "time" "github.com/splitio/go-split-commons/v7/dtos" @@ -10,6 +12,7 @@ import ( "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/healthcheck/application" "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v7/service/api/specs" "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-split-commons/v7/telemetry" "github.com/splitio/go-toolkit/v5/backoff" @@ -24,7 +27,6 @@ const ( UpdateTypeSplitChange = "SPLIT_UPDATE" UpdateTypeRuleBasedChange = "RB_SEGMENT_UPDATE" TypeStandard = "standard" - scRequestURITooLong = 414 onDemandFetchBackoffBase = int64(10) // backoff base starting at 10 seconds onDemandFetchBackoffMaxWait = 60 * time.Second // don't sleep for more than 1 minute onDemandFetchBackoffMaxRetries = 10 @@ -35,6 +37,10 @@ const ( Archived = "ARCHIVED" ) +var ( + ErrProxy = fmt.Errorf("maybe proxy error") +) + // Updater interface type Updater interface { SynchronizeSplits(till *int64) (*UpdateResult, error) @@ -70,6 +76,8 @@ type UpdaterImpl struct { onDemandFetchBackoffMaxWait time.Duration flagSetsFilter flagsets.FlagSetFilter validator validator.Validator + timestampLastSync int64 + fetcher func(fetchOptions *service.FlagRequestParams) (fetchResult, error) } // NewSplitUpdater creates new split synchronizer for processing split updates @@ -82,8 +90,9 @@ func NewSplitUpdater( hcMonitor application.MonitorProducerInterface, flagSetsFilter flagsets.FlagSetFilter, ruleBuilder grammar.RuleBuilder, + isProxy bool, ) *UpdaterImpl { - return &UpdaterImpl{ + updater := &UpdaterImpl{ splitStorage: splitStorage, splitFetcher: splitFetcher, logger: logger, @@ -94,7 +103,14 @@ func NewSplitUpdater( flagSetsFilter: flagSetsFilter, ruleBasedSegmentStorage: ruleBasedSegmentStorage, validator: validator.NewValidator(ruleBuilder), + timestampLastSync: 0, + } + if !isProxy { + updater.fetcher = updater.performFetchWithoutProxy + } else { + updater.fetcher = updater.performFetch } + return updater } func (s *UpdaterImpl) SetRuleBasedSegmentStorage(storage storage.RuleBasedSegmentsStorage) { @@ -124,24 +140,32 @@ type fetchResult struct { rbSince int64 } -func (s *UpdaterImpl) performFetch(fetchOptions *service.FlagRequestParams) (fetchResult, error) { - currentSince, _ := s.splitStorage.ChangeNumber() - currentRBSince := s.ruleBasedSegmentStorage.ChangeNumber() +func (s *UpdaterImpl) shouldUseLatest() bool { + return time.Since(time.Unix(s.timestampLastSync, 0)) >= 24*time.Hour +} + +func (s *UpdaterImpl) fetch(fetchOptions *service.FlagRequestParams) (*dtos.SplitChangesDTO, error) { + var splitChanges *dtos.SplitChangesDTO + var err error before := time.Now() - splitChanges, err := s.splitFetcher.Fetch(fetchOptions.WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + splitChanges, err = s.splitFetcher.Fetch(fetchOptions) if err != nil { if httpError, ok := err.(*dtos.HTTPError); ok { - if httpError.Code == scRequestURITooLong { + if httpError.Code == http.StatusRequestURITooLong { s.logger.Error("SDK Initialization, the amount of flag sets provided are big causing uri length error.") } + if httpError.Code == http.StatusBadRequest { + return splitChanges, ErrProxy + } s.runtimeTelemetry.RecordSyncError(telemetry.SplitSync, httpError.Code) } - return fetchResult{ - ffCurrentSince: currentSince, - rbCurrentSince: currentRBSince, - }, err + return splitChanges, err } s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) + return splitChanges, nil +} + +func (s *UpdaterImpl) processSplitChanges(splitChanges *dtos.SplitChangesDTO) fetchResult { s.processUpdate(splitChanges) segmentReferences := s.processRuleBasedUpdate(splitChanges) segmentReferences = appendSegmentNames(segmentReferences, splitChanges) @@ -153,7 +177,62 @@ func (s *UpdaterImpl) performFetch(fetchOptions *service.FlagRequestParams) (fet rbCurrentSince: splitChanges.RuleBasedSegments.Till, ffSince: splitChanges.FeatureFlags.Since, rbSince: splitChanges.RuleBasedSegments.Since, - }, nil + } +} + +func (s *UpdaterImpl) v11(fetchOptions *service.FlagRequestParams, currentSince, currentRBSince int64) (fetchResult, error) { + splitChanges, err := s.fetch(fetchOptions.Copy().WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + if err != nil { + return fetchResult{ + ffSince: currentSince, + rbSince: currentRBSince, + }, err + } + return s.processSplitChanges(splitChanges), nil +} + +func (s *UpdaterImpl) performFetchWithoutProxy(fetchOptions *service.FlagRequestParams) (fetchResult, error) { + currentSince, _ := s.splitStorage.ChangeNumber() + currentRBSince := s.ruleBasedSegmentStorage.ChangeNumber() + splitChanges, err := s.fetch(fetchOptions.Copy().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + if err != nil { + return fetchResult{ + ffSince: currentSince, + rbSince: currentRBSince, + }, err + } + return s.processSplitChanges(splitChanges), nil +} + +func (s *UpdaterImpl) performFetch(fetchOptions *service.FlagRequestParams) (fetchResult, error) { + var splitChanges *dtos.SplitChangesDTO + var err error + currentSince, _ := s.splitStorage.ChangeNumber() + currentRBSince := s.ruleBasedSegmentStorage.ChangeNumber() + shouldRetry := s.shouldUseLatest() + if shouldRetry || s.timestampLastSync == 0 { + if shouldRetry { // check if timestamp passed and reset since to -1 + currentSince = -1 + currentRBSince = -1 + } + splitChanges, err = s.fetch(fetchOptions.Copy().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince)) + if err != nil { + if errors.Is(err, ErrProxy) { + s.timestampLastSync = time.Now().Unix() + return s.v11(fetchOptions, currentSince, currentRBSince) + } + return fetchResult{ + ffSince: currentSince, + rbSince: currentRBSince, + }, err + } + if shouldRetry { // fetch was ok and needs to replace entire cache because legacy data are stored + // replaceALL if s.Timestamp != 0 AND RETURN + // return s.replaceAllChanges(splitChanges), nil + } + return s.processSplitChanges(splitChanges), nil + } + return s.v11(fetchOptions, currentSince, currentRBSince) } // fetchUntil Hit endpoint, update storage and return when since==till. @@ -166,7 +245,7 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda var fetchResult fetchResult for { // Fetch until since==till - fetchResult, err = s.performFetch(fetchOptions) + fetchResult, err = s.fetcher(fetchOptions) if err != nil { break } diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 85330a58..469042b1 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -10,6 +10,7 @@ import ( "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v7/service/api/specs" fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/inmemory" "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" @@ -55,7 +56,7 @@ func TestSplitSynchronizerError(t *testing.T) { appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) _, err := splitUpdater.SynchronizeSplits(nil) assert.NotNil(t, err) @@ -86,7 +87,7 @@ func TestSplitSynchronizerErrorScRequestURITooLong(t *testing.T) { appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) _, err := splitUpdater.SynchronizeSplits(nil) assert.NotNil(t, err) @@ -133,7 +134,7 @@ func TestSplitSynchronizer(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) _, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -182,7 +183,7 @@ func TestSplitSyncProcess(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -234,7 +235,7 @@ func TestSplitTill(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) var till int64 = 1 _, err := splitUpdater.SynchronizeSplits(&till) @@ -250,12 +251,12 @@ func TestSplitTill(t *testing.T) { func TestByPassingCDN(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, Since: 1, Till: 2}, }, nil).Once() - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, Since: 2, Till: 2}, @@ -280,7 +281,7 @@ func TestByPassingCDN(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) splitUpdater.onDemandFetchBackoffBase = 1 splitUpdater.onDemandFetchBackoffMaxWait = 10 * time.Nanosecond @@ -297,12 +298,12 @@ func TestByPassingCDNLimit(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, Since: 1, Till: 2}, }, nil).Once() - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(2).WithChangeNumberRB(-1)).Return(&dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Splits: []dtos.SplitDTO{mockedSplit1}, Since: 2, Till: 2}, @@ -327,7 +328,7 @@ func TestByPassingCDNLimit(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) splitUpdater.onDemandFetchBackoffBase = 1 splitUpdater.onDemandFetchBackoffMaxWait = 10 * time.Nanosecond @@ -351,7 +352,7 @@ func TestProcessFFChange(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) result, _ := fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 12), nil, nil, @@ -382,7 +383,7 @@ func TestAddOrUpdateFeatureFlagNil(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, )) @@ -403,7 +404,7 @@ func TestAddOrUpdateFeatureFlagPcnEquals(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) featureFlag := dtos.SplitDTO{ChangeNumber: 4, Status: Active} fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 4), common.Int64Ref(2), &featureFlag, @@ -425,7 +426,7 @@ func TestAddOrUpdateFeatureFlagArchive(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) featureFlag := dtos.SplitDTO{ChangeNumber: 4, Status: Archived} fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( @@ -459,7 +460,7 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, @@ -472,7 +473,7 @@ func TestGetActiveFF(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) assert.Len(t, actives, 2) assert.Len(t, inactives, 0) @@ -484,7 +485,7 @@ func TestGetInactiveFF(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) assert.Len(t, actives, 0) assert.Len(t, inactives, 2) @@ -498,7 +499,7 @@ func TestGetActiveAndInactiveFF(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) actives, inactives := s.processFeatureFlagChanges(featureFlagChanges) assert.Len(t, actives, 1) assert.Len(t, inactives, 1) @@ -528,7 +529,7 @@ func TestSplitSyncWithSets(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter([]string{"set1", "set2", "set3"}), ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter([]string{"set1", "set2", "set3"}), ruleBuilder, false) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -567,7 +568,7 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagSetFilter, ruleBuilder) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagSetFilter, ruleBuilder, false) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -617,6 +618,7 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, + false, ) // Test case 1: till is less than both currentSince and currentRBSince @@ -691,7 +693,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) lowerChangeNumber := int64(100) ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ @@ -736,7 +738,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) changeNumber := int64(300) ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ @@ -776,7 +778,7 @@ func TestProcessMatchers(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) splitChange := &dtos.SplitChangesDTO{ FeatureFlags: dtos.FeatureFlagsDTO{Till: 1, Since: 1, Splits: []dtos.SplitDTO{ { diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8481d04f..3b0052e5 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -64,7 +64,7 @@ func TestSplitSyncTask(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) splitTask := NewFetchSplitsTask( splitUpdater, From a88deafdb02ff4334317007ae16b0008622e7506 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 9 Oct 2025 12:02:43 -0300 Subject: [PATCH 14/39] Added function to know if the sdk is using a proxy or not --- service/api/http_fetchers.go | 9 +++++ service/api/http_fetchers_test.go | 64 +++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 7d94bb69..5aa62e18 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -47,6 +47,15 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. } } +func (f *HTTPSplitFetcher) isProxy(fetchOptions *service.FlagRequestParams) bool { + _, err := f.fetchRaw("/version", fetchOptions) + if err == nil { + return false + } + httpErr, ok := err.(*dtos.HTTPError) + return ok && httpErr.Code == 404 +} + // Fetch makes an http call to the split backend and returns the list of updated splits func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos.FFResponse, error) { fetchOptions.WithFlagSetsFilter(f.flagSetsFilter).WithSpecVersion(f.specVersion) diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index b4518c97..570892f7 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -586,6 +586,70 @@ func TestFetchWithPost(t *testing.T) { assert.Equal(t, 1500, len(result.Keys), "Keys lenght should be 1500. Actual: ", len(result.Keys)) } +func TestIsProxy(t *testing.T) { + logger := logging.NewLogger(&logging.LoggerOptions{}) + + // Test case 1: Not a proxy (version endpoint returns 200) + ts1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/version", r.URL.Path) + w.WriteHeader(http.StatusOK) + })) + defer ts1.Close() + + splitFetcher1 := NewHTTPSplitFetcher( + "", + conf.AdvancedConfig{ + EventsURL: ts1.URL, + SdkURL: ts1.URL, + }, + logger, + dtos.Metadata{}, + ).(*HTTPSplitFetcher) // Type assertion to access unexported method + + isProxy := splitFetcher1.isProxy(service.MakeFlagRequestParams()) + assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns 200") + + // Test case 2: Is a proxy (version endpoint returns 404) + ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/version", r.URL.Path) + w.WriteHeader(http.StatusNotFound) + })) + defer ts2.Close() + + splitFetcher2 := NewHTTPSplitFetcher( + "", + conf.AdvancedConfig{ + EventsURL: ts2.URL, + SdkURL: ts2.URL, + }, + logger, + dtos.Metadata{}, + ).(*HTTPSplitFetcher) // Type assertion to access unexported method + + isProxy = splitFetcher2.isProxy(service.MakeFlagRequestParams()) + assert.True(t, isProxy, "Should be identified as proxy when version endpoint returns 404") + + // Test case 3: Not a proxy (version endpoint returns other error code) + ts3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/version", r.URL.Path) + w.WriteHeader(http.StatusInternalServerError) + })) + defer ts3.Close() + + splitFetcher3 := NewHTTPSplitFetcher( + "", + conf.AdvancedConfig{ + EventsURL: ts3.URL, + SdkURL: ts3.URL, + }, + logger, + dtos.Metadata{}, + ).(*HTTPSplitFetcher) // Type assertion to access unexported method + + isProxy = splitFetcher3.isProxy(service.MakeFlagRequestParams()) + assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns non-404 error") +} + func buildLargeSegmentRFDResponseDTO(url string) dtos.LargeSegmentRFDResponseDTO { return dtos.LargeSegmentRFDResponseDTO{ NotificationType: "LS_NEW_DEFINITION", From 5f4176f58960f2f95c4d6fd4f25b779ac8cb18f8 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Thu, 9 Oct 2025 16:45:29 -0300 Subject: [PATCH 15/39] clean code --- service/commons.go | 13 ------------- service/commons_test.go | 16 ---------------- 2 files changed, 29 deletions(-) diff --git a/service/commons.go b/service/commons.go index 08a33c5b..bdd56681 100644 --- a/service/commons.go +++ b/service/commons.go @@ -53,19 +53,6 @@ func MakeFlagRequestParams() *FlagRequestParams { } } -func (s *FlagRequestParams) Copy() *FlagRequestParams { - return &FlagRequestParams{ - baseRequestParams: baseRequestParams{ - cacheControlHeaders: s.cacheControlHeaders, - }, - changeNumber: s.changeNumber, - changeNumberRB: s.changeNumberRB, - flagSetsFilter: s.flagSetsFilter, - specVersion: s.specVersion, - till: s.till, - } -} - // WithCacheControl sets the cache control header func (s *FlagRequestParams) WithCacheControl(cacheControl bool) *FlagRequestParams { s.cacheControlHeaders = cacheControl diff --git a/service/commons_test.go b/service/commons_test.go index 2f203c31..7ea533f7 100644 --- a/service/commons_test.go +++ b/service/commons_test.go @@ -26,22 +26,6 @@ func TestSplitFetchOptions(t *testing.T) { assert.Equal(t, "test?s=1.1&since=123456&rbSince=123456&sets=filter&till=123", req.URL.String()) } -func TestCopy(t *testing.T) { - fetchOptions := MakeFlagRequestParams().WithChangeNumber(123456).WithFlagSetsFilter("filter").WithTill(*common.Int64Ref(123)).WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumberRB(123456) - copyOptions := fetchOptions.Copy().WithSpecVersion(common.StringRef(specs.FLAG_V1_2)).WithChangeNumber(654321).WithChangeNumberRB(654321).WithFlagSetsFilter("newfilter").WithTill(*common.Int64Ref(321)) - - assert.Equal(t, fetchOptions.ChangeNumber(), int64(123456)) - assert.Equal(t, copyOptions.ChangeNumber(), int64(654321)) - assert.Equal(t, fetchOptions.ChangeNumberRB(), int64(123456)) - assert.Equal(t, copyOptions.ChangeNumberRB(), int64(654321)) - assert.Equal(t, *fetchOptions.Till(), int64(123)) - assert.Equal(t, *copyOptions.Till(), int64(321)) - assert.Equal(t, *fetchOptions.specVersion, specs.FLAG_V1_1) - assert.Equal(t, *copyOptions.specVersion, specs.FLAG_V1_2) - assert.Equal(t, fetchOptions.flagSetsFilter, "filter") - assert.Equal(t, copyOptions.flagSetsFilter, "newfilter") -} - func TestSegmentRequestParams(t *testing.T) { fetchOptions := MakeSegmentRequestParams().WithChangeNumber(123456).WithTill(*common.Int64Ref(123)) req, _ := http.NewRequest("GET", "test", nil) From 499f747775f62a7f0ebc05d146a028c9f4b51f20 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Thu, 9 Oct 2025 17:15:54 -0300 Subject: [PATCH 16/39] added next call for until since==till --- synchronizer/worker/split/split.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index a1829d9d..31a95fa6 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -274,15 +274,24 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { if s.isProxy && s.passedTimeWindow() { syncResult, err := s.attemptLatestSync() - if err != nil { + if err == nil { s.lastSyncNewSpec = -1 s.specVersion = specs.FLAG_V1_3 - return syncResult, nil + untilTillSince, err := s.synchronizeSplits(nil) + if err != nil { + return &UpdateResult{ + UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), + ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), + NewChangeNumber: untilTillSince.NewChangeNumber, + NewRBChangeNumber: untilTillSince.NewRBChangeNumber, + ReferencedLargeSegments: common.DedupeStringSlice(append(syncResult.ReferencedLargeSegments, untilTillSince.ReferencedLargeSegments...)), + }, nil + } } s.specVersion = specs.FLAG_V1_1 } - return s.synchronizeSplits(till) + return s.synchronizeSplits(nil) } func appendSplitNames(dst []string, featureFlags []dtos.SplitDTO) []string { From 18e02f996e94114672360365ef13678e248bbbeb Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 13 Oct 2025 15:41:59 -0300 Subject: [PATCH 17/39] fixed logic --- synchronizer/worker/split/split.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 31a95fa6..1a297349 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -264,7 +264,7 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { } func (s *UpdaterImpl) passedTimeWindow() bool { - return s.lastSyncNewSpec == 0 || time.Since(time.Unix(s.lastSyncNewSpec, 0)) >= 24*time.Hour + return s.lastSyncNewSpec == 0 || (s.lastSyncNewSpec > 0 && time.Since(time.Unix(s.lastSyncNewSpec, 0)) >= 24*time.Hour) } func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { @@ -273,12 +273,14 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { } if s.isProxy && s.passedTimeWindow() { + s.logger.Info("Attempting to sync splits with the latest spec version (v1.3)") syncResult, err := s.attemptLatestSync() + s.lastSyncNewSpec = time.Now().Unix() if err == nil { s.lastSyncNewSpec = -1 s.specVersion = specs.FLAG_V1_3 untilTillSince, err := s.synchronizeSplits(nil) - if err != nil { + if err == nil { return &UpdateResult{ UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), From e58bddda57d83cf7252e294195b41b27b18b2968 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 13 Oct 2025 16:21:19 -0300 Subject: [PATCH 18/39] added test --- synchronizer/worker/split/split.go | 2 +- synchronizer/worker/split/split_test.go | 153 ++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 1a297349..715ebebb 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -250,7 +250,7 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) s.splitStorage.ReplaceAll(splitChanges.FeatureFlags(), currentSince) s.ruleBasedSegmentStorage.Clear() - segmentReferences := s.processRuleBasedUpdate(splitChanges) + segmentReferences := s.processRuleBasedUpdate(splitChanges) // TODO ReplaceAll segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges.FeatureFlags()) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 31fe7cab..a5cc3cbd 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -2,6 +2,7 @@ package split import ( "errors" + "net/http" "testing" "time" @@ -898,3 +899,155 @@ func TestProcessMatchers(t *testing.T) { assert.Equal(t, grammar.ConditionTypeRollout, toAdd[1].Conditions[0].ConditionType) assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[1].Conditions[0].MatcherGroup.Matchers[0].MatcherType) } + +func TestSplitProxyDowngrade(t *testing.T) { + t.Run("Error both 1.3 and 1.1", func(t *testing.T) { + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)).Times(2) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusBadRequest}).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusBadRequest}).Once() + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSyncErrorCall: func(resource, status int) { + assert.Equal(t, telemetry.SplitSync, resource) + assert.Equal(t, http.StatusBadRequest, status) + }, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + + _, err := splitUpdater.SynchronizeSplits(nil) + assert.NotNil(t, err) + + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) + + t.Run("From 1.3 to 1.1", func(t *testing.T) { + mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} + response := &dtos.FFResponseLegacy{ + SplitChanges: dtos.SplitsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: 3, + Till: 3, + }, + } + + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) + splitMockStorage.On("Update", []dtos.SplitDTO{mockedSplit1}, []dtos.SplitDTO{}, int64(3)).Once() + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)).Times(2) + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(0)).Once().Return(-1) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusBadRequest}).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSuccessfulSyncCall: func(resource int, tm time.Time) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + RecordSyncLatencyCall: func(resource int, tm time.Duration) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + + result, err := splitUpdater.SynchronizeSplits(nil) + assert.Nil(t, err) + assert.Equal(t, int64(3), result.NewChangeNumber) + assert.Equal(t, int64(0), result.NewRBChangeNumber) + assert.ElementsMatch(t, []string{"split1"}, result.UpdatedSplits) + assert.Len(t, result.ReferencedSegments, 0) + assert.Len(t, result.ReferencedLargeSegments, 0) + assert.Greater(t, splitUpdater.lastSyncNewSpec, int64(0)) + assert.Equal(t, specs.FLAG_V1_1, splitUpdater.specVersion) + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) + + t.Run("1.3 OK", func(t *testing.T) { + mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} + mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: -1, + Till: 3, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + Since: -1, + Till: 3, + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, + }, + }, + } + empty := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 3, + Till: 3, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + Since: 3, + Till: 3, + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + }, + }, + } + + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(3), nil).Times(2) + splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once() + splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(3)).Once() + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) + ruleBasedSegmentMockStorage.On("Clear").Return().Once() + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(3).WithChangeNumberRB(3)).Return(empty, nil).Once() + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSuccessfulSyncCall: func(resource int, tm time.Time) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + RecordSyncLatencyCall: func(resource int, tm time.Duration) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + + result, err := splitUpdater.SynchronizeSplits(nil) + assert.Nil(t, err) + assert.Equal(t, int64(3), result.NewChangeNumber) + assert.Equal(t, int64(3), result.NewRBChangeNumber) + assert.Len(t, result.ReferencedSegments, 0) + assert.Len(t, result.ReferencedLargeSegments, 0) + assert.ElementsMatch(t, []string{"split1"}, result.UpdatedSplits) + assert.Equal(t, int64(-1), splitUpdater.lastSyncNewSpec) + assert.Equal(t, specs.FLAG_V1_3, splitUpdater.specVersion) + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) +} From 96dea754facfdbfa91a3ee0bdd72651dbe601293 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Tue, 14 Oct 2025 12:16:20 -0300 Subject: [PATCH 19/39] renamed method --- synchronizer/worker/split/split.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 715ebebb..12ba9e67 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -263,7 +263,7 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { }, err } -func (s *UpdaterImpl) passedTimeWindow() bool { +func (s *UpdaterImpl) shouldRetryWithLatestSpec() bool { return s.lastSyncNewSpec == 0 || (s.lastSyncNewSpec > 0 && time.Since(time.Unix(s.lastSyncNewSpec, 0)) >= 24*time.Hour) } @@ -272,7 +272,7 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { return s.synchronizeSplits(till) } - if s.isProxy && s.passedTimeWindow() { + if s.isProxy && s.shouldRetryWithLatestSpec() { s.logger.Info("Attempting to sync splits with the latest spec version (v1.3)") syncResult, err := s.attemptLatestSync() s.lastSyncNewSpec = time.Now().Unix() From 17ff98a8d8ccc74f80ebe6d33068e7fabf8901fb Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 14 Oct 2025 14:07:09 -0300 Subject: [PATCH 20/39] Add method in the interface --- service/api/http_fetchers.go | 2 +- service/api/http_fetchers_test.go | 6 +++--- service/interfaces.go | 1 + service/local/splitFetcher.go | 4 ++++ service/mocks/split.go | 6 ++++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 5aa62e18..2af8a914 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -47,7 +47,7 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. } } -func (f *HTTPSplitFetcher) isProxy(fetchOptions *service.FlagRequestParams) bool { +func (f *HTTPSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { _, err := f.fetchRaw("/version", fetchOptions) if err == nil { return false diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index 570892f7..e3f2d1d8 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -606,7 +606,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy := splitFetcher1.isProxy(service.MakeFlagRequestParams()) + isProxy := splitFetcher1.IsProxy(service.MakeFlagRequestParams()) assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns 200") // Test case 2: Is a proxy (version endpoint returns 404) @@ -626,7 +626,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy = splitFetcher2.isProxy(service.MakeFlagRequestParams()) + isProxy = splitFetcher2.IsProxy(service.MakeFlagRequestParams()) assert.True(t, isProxy, "Should be identified as proxy when version endpoint returns 404") // Test case 3: Not a proxy (version endpoint returns other error code) @@ -646,7 +646,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy = splitFetcher3.isProxy(service.MakeFlagRequestParams()) + isProxy = splitFetcher3.IsProxy(service.MakeFlagRequestParams()) assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns non-404 error") } diff --git a/service/interfaces.go b/service/interfaces.go index 699958ac..8f157b24 100644 --- a/service/interfaces.go +++ b/service/interfaces.go @@ -10,6 +10,7 @@ type AuthClient interface { // SplitFetcher interface to be implemented by Split Fetchers type SplitFetcher interface { Fetch(fetchOptions *FlagRequestParams) (dtos.FFResponse, error) + IsProxy(fetchOptions *FlagRequestParams) bool } // SegmentFetcher interface to be implemented by Split Fetchers diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index 4903ff59..3677b5d7 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -325,4 +325,8 @@ func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. }, nil } +func (s *FileSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { + return false +} + var _ service.SplitFetcher = &FileSplitFetcher{} diff --git a/service/mocks/split.go b/service/mocks/split.go index 4ee2fdf0..05574149 100644 --- a/service/mocks/split.go +++ b/service/mocks/split.go @@ -21,4 +21,10 @@ func (m *MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. return args.Get(0).(dtos.FFResponse), args.Error(1) } +// Fetch mock +func (m *MockSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { + args := m.Called(fetchOptions) + return args.Get(0).(bool) +} + var _ service.SplitFetcher = (*MockSplitFetcher)(nil) From c7ae6a7be45ef29b7e7fe889c1c1063da30f8e2a Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 14 Oct 2025 14:34:26 -0300 Subject: [PATCH 21/39] Updated isProxy function --- service/api/http_fetchers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 2af8a914..116f2b03 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -53,7 +53,7 @@ func (f *HTTPSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool return false } httpErr, ok := err.(*dtos.HTTPError) - return ok && httpErr.Code == 404 + return ok && httpErr.Code == http.StatusNotFound } // Fetch makes an http call to the split backend and returns the list of updated splits From f40682477c5ef5c9b4f47c413706b636efd59a57 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 14 Oct 2025 18:00:33 -0300 Subject: [PATCH 22/39] Added rule-based segment replace function in the storage --- storage/inmemory/mutexmap/rulebasedsegment.go | 22 +++- .../mutexmap/rulebasedsegment_test.go | 120 ++++++++++++++++++ storage/interfaces.go | 1 + storage/mocks/rulebasedsegment.go | 4 + synchronizer/worker/split/split.go | 12 +- synchronizer/worker/split/split_test.go | 4 +- 6 files changed, 158 insertions(+), 5 deletions(-) diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index 6aa4e71d..93aaf086 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -26,10 +26,15 @@ func NewRuleBasedSegmentsStorage() *RuleBasedSegmentsStorageImpl { } } -// Update atomically registers new rule-based, removes archived ones and updates the change number +// Update atomically registers new rule-based segments, removes archived ones and updates the change number func (r *RuleBasedSegmentsStorageImpl) Update(toAdd []dtos.RuleBasedSegmentDTO, toRemove []dtos.RuleBasedSegmentDTO, till int64) { r.mutex.Lock() defer r.mutex.Unlock() + r.update(toAdd, toRemove, till) +} + +// Update atomically registers new rule-based, removes archived ones and updates the change number +func (r *RuleBasedSegmentsStorageImpl) update(toAdd []dtos.RuleBasedSegmentDTO, toRemove []dtos.RuleBasedSegmentDTO, till int64) { for _, ruleBased := range toAdd { r.data[ruleBased.Name] = ruleBased } @@ -139,3 +144,18 @@ func (r *RuleBasedSegmentsStorageImpl) GetRuleBasedSegmentByName(name string) (* } return nil, fmt.Errorf("rule-based segment %s not found in storage", name) } + +func (r *RuleBasedSegmentsStorageImpl) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) { + // Get all current splits under read lock + r.mutex.RLock() + toRemove := make([]dtos.RuleBasedSegmentDTO, 0) + for _, split := range r.data { + toRemove = append(toRemove, split) + } + r.mutex.RUnlock() + + // Now acquire write lock for the update + r.mutex.Lock() + defer r.mutex.Unlock() + r.update(toAdd, toRemove, changeNumber) +} diff --git a/storage/inmemory/mutexmap/rulebasedsegment_test.go b/storage/inmemory/mutexmap/rulebasedsegment_test.go index 618f0071..9e7a7a7d 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment_test.go +++ b/storage/inmemory/mutexmap/rulebasedsegment_test.go @@ -95,6 +95,126 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { assert.Empty(t, storage.RuleBasedSegmentNames()) } +func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { + // Initialize storage + storage := NewRuleBasedSegmentsStorage() + + // Create initial test data + initialRuleBased := dtos.RuleBasedSegmentDTO{ + Name: "initial", + Conditions: []dtos.RuleBasedConditionDTO{ + { + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + { + UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ + SegmentName: "segment1", + }, + }, + }, + }, + }, + }, + } + + // Add initial data + storage.Update([]dtos.RuleBasedSegmentDTO{initialRuleBased}, nil, 100) + + // Create new data for replacement + newRuleBased := dtos.RuleBasedSegmentDTO{ + Name: "new", + Conditions: []dtos.RuleBasedConditionDTO{ + { + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + { + UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ + SegmentName: "segment2", + }, + }, + }, + }, + }, + }, + } + + // Test ReplaceAll + storage.ReplaceAll([]dtos.RuleBasedSegmentDTO{newRuleBased}, 200) + + // Verify change number was updated + assert.Equal(t, int64(200), storage.ChangeNumber()) + + // Verify old data was removed + oldSegment, err := storage.GetRuleBasedSegmentByName("initial") + assert.Error(t, err) + assert.Nil(t, oldSegment) + + // Verify new data was added + newSegment, err := storage.GetRuleBasedSegmentByName("new") + assert.NoError(t, err) + assert.NotNil(t, newSegment) + assert.Equal(t, "new", newSegment.Name) + + // Verify segments set + segments := storage.GetSegments() + assert.True(t, segments.Has("segment2")) + assert.False(t, segments.Has("segment1")) + + // Test ReplaceAll with empty slice + storage.ReplaceAll([]dtos.RuleBasedSegmentDTO{}, 300) + + // Verify storage is empty + assert.Empty(t, storage.All()) + assert.Equal(t, int64(300), storage.ChangeNumber()) + + // Test ReplaceAll with multiple segments + ruleBased1 := dtos.RuleBasedSegmentDTO{ + Name: "rule1", + Conditions: []dtos.RuleBasedConditionDTO{ + { + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + { + UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ + SegmentName: "segment3", + }, + }, + }, + }, + }, + }, + } + + ruleBased2 := dtos.RuleBasedSegmentDTO{ + Name: "rule2", + Conditions: []dtos.RuleBasedConditionDTO{ + { + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + { + UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ + SegmentName: "segment4", + }, + }, + }, + }, + }, + }, + } + + storage.ReplaceAll([]dtos.RuleBasedSegmentDTO{ruleBased1, ruleBased2}, 400) + + // Verify multiple segments were added + assert.Len(t, storage.All(), 2) + assert.Equal(t, int64(400), storage.ChangeNumber()) + assert.True(t, storage.Contains([]string{"rule1", "rule2"})) + + // Verify segments set contains both segments + segments = storage.GetSegments() + assert.True(t, segments.Has("segment3")) + assert.True(t, segments.Has("segment4")) +} + func TestRuleBasedSegmentsStorageEdgeCases(t *testing.T) { storage := NewRuleBasedSegmentsStorage() diff --git a/storage/interfaces.go b/storage/interfaces.go index 8cb54e35..fd9d87f4 100644 --- a/storage/interfaces.go +++ b/storage/interfaces.go @@ -273,6 +273,7 @@ type RuleBasedSegmentStorageProducer interface { SetChangeNumber(till int64) error Update(toAdd []dtos.RuleBasedSegmentDTO, toRemove []dtos.RuleBasedSegmentDTO, till int64) Clear() + ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) } // RuleBasedStorageConsumer interface should be implemented by all structs that ofer reading rule-based segments diff --git a/storage/mocks/rulebasedsegment.go b/storage/mocks/rulebasedsegment.go index 0f36bd63..e0c055d7 100644 --- a/storage/mocks/rulebasedsegment.go +++ b/storage/mocks/rulebasedsegment.go @@ -70,4 +70,8 @@ func (m *MockRuleBasedSegmentStorage) Clear() { m.Called() } +func (m *MockRuleBasedSegmentStorage) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) { + m.Called(toAdd, changeNumber) +} + var _ storage.RuleBasedSegmentsStorage = (*MockRuleBasedSegmentStorage)(nil) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 12ba9e67..a77fc61f 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -249,8 +249,8 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { currentRBSince = splitChanges.RBTill() s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) s.splitStorage.ReplaceAll(splitChanges.FeatureFlags(), currentSince) - s.ruleBasedSegmentStorage.Clear() - segmentReferences := s.processRuleBasedUpdate(splitChanges) // TODO ReplaceAll + s.ruleBasedSegmentStorage.ReplaceAll(splitChanges.RuleBasedSegments(), currentSince) + segmentReferences := s.getSegmentsFromRuleBasedSegments(splitChanges.RuleBasedSegments()) segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges.FeatureFlags()) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) @@ -456,6 +456,14 @@ func (s *UpdaterImpl) processRuleBasedSegmentChanges(ruleBasedSegments []dtos.Ru return toAdd, toRemove, segments } +func (s *UpdaterImpl) getSegmentsFromRuleBasedSegments(ruleBasedSegments []dtos.RuleBasedSegmentDTO) []string { + segments := make([]string, 0) + for _, rbSegment := range ruleBasedSegments { + segments = append(segments, s.getSegments(&rbSegment)...) + } + return segments +} + func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitChangeUpdate) *UpdateResult { changeNumber := s.ruleBasedSegmentStorage.ChangeNumber() if changeNumber >= ruleBasedChange.BaseUpdate.ChangeNumber() { diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index a5cc3cbd..3d79760e 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -1016,8 +1016,8 @@ func TestSplitProxyDowngrade(t *testing.T) { splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(3)).Once() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) - ruleBasedSegmentMockStorage.On("Clear").Return().Once() - ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) + ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once() + //ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} From 473108f5bdaecb3a1d6a90b5d140ace2ae1f91ba Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 Oct 2025 14:24:16 -0300 Subject: [PATCH 23/39] Updated params to create updater --- storage/inmemory/mutexmap/rulebasedsegment.go | 4 +- synchronizer/local.go | 3 +- synchronizer/local_test.go | 2 + synchronizer/synchronizer_test.go | 15 +++--- synchronizer/worker/split/split.go | 3 +- synchronizer/worker/split/split_test.go | 48 +++++++++---------- tasks/splitsync_test.go | 3 +- 7 files changed, 42 insertions(+), 36 deletions(-) diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index 93aaf086..d247ab7a 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -149,8 +149,8 @@ func (r *RuleBasedSegmentsStorageImpl) ReplaceAll(toAdd []dtos.RuleBasedSegmentD // Get all current splits under read lock r.mutex.RLock() toRemove := make([]dtos.RuleBasedSegmentDTO, 0) - for _, split := range r.data { - toRemove = append(toRemove, split) + for _, ruleBased := range r.data { + toRemove = append(toRemove, ruleBased) } r.mutex.RUnlock() diff --git a/synchronizer/local.go b/synchronizer/local.go index a20b058a..edad4a08 100644 --- a/synchronizer/local.go +++ b/synchronizer/local.go @@ -8,6 +8,7 @@ import ( "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/healthcheck/application" "github.com/splitio/go-split-commons/v7/service/api" + "github.com/splitio/go-split-commons/v7/service/api/specs" "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" @@ -37,7 +38,7 @@ type LocalConfig struct { // NewLocal creates new Local func NewLocal(cfg *LocalConfig, splitAPI *api.SplitAPI, splitStorage storage.SplitStorage, segmentStorage storage.SegmentStorage, largeSegmentStorage storage.LargeSegmentsStorage, ruleBasedStorage storage.RuleBasedSegmentsStorage, logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer, hcMonitor application.MonitorProducerInterface) Synchronizer { ruleBuilder := grammar.NewRuleBuilder(segmentStorage, ruleBasedStorage, largeSegmentStorage, cfg.FfRulesAccepted, cfg.RbRulesAccepted, logger, nil) - splitUpdater := split.NewSplitUpdater(splitStorage, ruleBasedStorage, splitAPI.SplitFetcher, logger, runtimeTelemetry, hcMonitor, flagsets.NewFlagSetFilter(cfg.FlagSets), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitStorage, ruleBasedStorage, splitAPI.SplitFetcher, logger, runtimeTelemetry, hcMonitor, flagsets.NewFlagSetFilter(cfg.FlagSets), ruleBuilder, false, specs.FLAG_V1_3) splitUpdater.SetRuleBasedSegmentStorage(ruleBasedStorage) workers := Workers{ diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 5d06a54f..6fb044fb 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -11,6 +11,7 @@ import ( hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api" + "github.com/splitio/go-split-commons/v7/service/api/specs" httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" @@ -56,6 +57,7 @@ func TestLocalSyncAllError(t *testing.T) { flagSetFilter, ruleBuilder, false, + specs.FLAG_V1_3, ) splitUpdater.SetRuleBasedSegmentStorage(ruleBasedSegmentMockStorage) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 52684502..5e67f98b 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -15,6 +15,7 @@ import ( "github.com/splitio/go-split-commons/v7/push" "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api" + "github.com/splitio/go-split-commons/v7/service/api/specs" httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" storageMock "github.com/splitio/go-split-commons/v7/storage/mocks" @@ -64,7 +65,7 @@ func TestSyncAllErrorSplits(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) workers := Workers{ SplitUpdater: splitUpdater, @@ -139,7 +140,7 @@ func TestSyncAllErrorInSegments(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -232,7 +233,7 @@ func TestSyncAllOk(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -323,7 +324,7 @@ func TestPeriodicFetching(t *testing.T) { ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) advanced := conf.AdvancedConfig{EventsQueueSize: 100, EventsBulkSize: 100, HTTPTimeout: 100, ImpressionsBulkSize: 100, ImpressionsQueueSize: 100, SegmentQueueSize: 50, SegmentWorkers: 5} workers := Workers{ SplitUpdater: splitUpdater, @@ -463,7 +464,7 @@ func TestSplitUpdateWorkerCNGreaterThanFFChange(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3), SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), } splitTasks := SplitTasks{ @@ -922,7 +923,7 @@ func TestLocalKill(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, storageMock.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, storageMock.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3), } splitTasks := SplitTasks{ SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitUpdater, 1, logger), @@ -986,7 +987,7 @@ func TestSplitUpdateWithReferencedSegments(t *testing.T) { ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logger, nil) workers := Workers{ - SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false), + SplitUpdater: split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitAPI.SplitFetcher, logger, telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3), SegmentUpdater: segment.NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, splitAPI.SegmentFetcher, logger, telemetryMockStorage, appMonitorMock), EventRecorder: event.NewEventRecorderSingle(storageMock.MockEventStorage{}, splitAPI.EventRecorder, logger, dtos.Metadata{}, telemetryMockStorage), TelemetryRecorder: telemetry.NewTelemetrySynchronizer(telemetryMockStorage, nil, nil, nil, nil, dtos.Metadata{}, telemetryMockStorage), diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index a77fc61f..b7747da4 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -92,6 +92,7 @@ func NewSplitUpdater( flagSetsFilter flagsets.FlagSetFilter, ruleBuilder grammar.RuleBuilder, isProxy bool, + specVersion string, ) *UpdaterImpl { return &UpdaterImpl{ splitStorage: splitStorage, @@ -106,7 +107,7 @@ func NewSplitUpdater( validator: validator.NewValidator(ruleBuilder), isProxy: isProxy, lastSyncNewSpec: 0, - specVersion: specs.FLAG_V1_3, + specVersion: specVersion, } } diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 3d79760e..45f37eda 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -57,7 +57,7 @@ func TestSplitSynchronizerError(t *testing.T) { appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) _, err := splitUpdater.SynchronizeSplits(nil) assert.NotNil(t, err) @@ -88,7 +88,7 @@ func TestSplitSynchronizerErrorScRequestURITooLong(t *testing.T) { appMonitorMock.On("NotifyEvent", mock.Anything).Once() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) _, err := splitUpdater.SynchronizeSplits(nil) assert.NotNil(t, err) @@ -141,7 +141,7 @@ func TestSplitSynchronizer(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) _, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -202,7 +202,7 @@ func TestSplitSyncProcess(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -262,7 +262,7 @@ func TestSplitTill(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) var till int64 = 1 _, err := splitUpdater.SynchronizeSplits(&till) @@ -324,7 +324,7 @@ func TestByPassingCDN(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) splitUpdater.onDemandFetchBackoffBase = 1 splitUpdater.onDemandFetchBackoffMaxWait = 10 * time.Nanosecond @@ -387,7 +387,7 @@ func TestByPassingCDNLimit(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) splitUpdater.onDemandFetchBackoffBase = 1 splitUpdater.onDemandFetchBackoffMaxWait = 10 * time.Nanosecond @@ -411,7 +411,7 @@ func TestProcessFFChange(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) result, _ := fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 12), nil, nil, @@ -447,7 +447,7 @@ func TestAddOrUpdateFeatureFlagNil(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, )) @@ -468,7 +468,7 @@ func TestAddOrUpdateFeatureFlagPcnEquals(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) featureFlag := dtos.SplitDTO{ChangeNumber: 4, Status: Active} fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 4), common.Int64Ref(2), &featureFlag, @@ -490,7 +490,7 @@ func TestAddOrUpdateFeatureFlagArchive(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) featureFlag := dtos.SplitDTO{ChangeNumber: 4, Status: Archived} fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( @@ -529,7 +529,7 @@ func TestAddOrUpdateFFCNFromStorageError(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, nil) - fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + fetcher := NewSplitUpdater(ffStorageMock, ruleBasedSegmentMockStorage, splitMockFetcher, logger, telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) fetcher.SynchronizeFeatureFlags(dtos.NewSplitChangeUpdate( dtos.NewBaseUpdate(dtos.NewBaseMessage(0, "some"), 2), nil, nil, @@ -541,7 +541,7 @@ func TestGetActiveFF(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 2) assert.Len(t, inactives, 0) @@ -552,7 +552,7 @@ func TestGetInactiveFF(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 0) assert.Len(t, inactives, 2) @@ -564,7 +564,7 @@ func TestGetActiveAndInactiveFF(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + s := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, nil, mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) actives, inactives := s.processFeatureFlagChanges(featureFlags) assert.Len(t, actives, 1) assert.Len(t, inactives, 1) @@ -600,7 +600,7 @@ func TestSplitSyncWithSets(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter([]string{"set1", "set2", "set3"}), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagsets.NewFlagSetFilter([]string{"set1", "set2", "set3"}), ruleBuilder, false, specs.FLAG_V1_3) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -644,7 +644,7 @@ func TestSplitSyncWithSetsInConfig(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagSetFilter, ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryStorage, appMonitorMock, flagSetFilter, ruleBuilder, false, specs.FLAG_V1_3) res, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -695,6 +695,7 @@ func TestSynchronizeSplitsWithLowerTill(t *testing.T) { flagsets.NewFlagSetFilter(nil), ruleBuilder, false, + specs.FLAG_V1_3, ) // Test case 1: till is less than both currentSince and currentRBSince @@ -776,7 +777,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) lowerChangeNumber := int64(100) ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ @@ -821,7 +822,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) changeNumber := int64(300) ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ @@ -861,7 +862,7 @@ func TestProcessMatchers(t *testing.T) { largeSegmentStorage := &mocks.MockLargeSegmentStorage{} ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := NewSplitUpdater(mocks.MockSplitStorage{}, ruleBasedSegmentMockStorage, &fetcherMock.MockSplitFetcher{}, logging.NewLogger(nil), mocks.MockTelemetryStorage{}, hcMock.MockApplicationMonitor{}, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) featureFlags := []dtos.SplitDTO{ { Name: "split1", @@ -919,7 +920,7 @@ func TestSplitProxyDowngrade(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true, specs.FLAG_V1_3) _, err := splitUpdater.SynchronizeSplits(nil) assert.NotNil(t, err) @@ -961,7 +962,7 @@ func TestSplitProxyDowngrade(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true, specs.FLAG_V1_3) result, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) @@ -1017,7 +1018,6 @@ func TestSplitProxyDowngrade(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once() - //ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} @@ -1034,7 +1034,7 @@ func TestSplitProxyDowngrade(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return() ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true, specs.FLAG_V1_3) result, err := splitUpdater.SynchronizeSplits(nil) assert.Nil(t, err) diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index f33e7edf..8adc752c 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -8,6 +8,7 @@ import ( "github.com/splitio/go-split-commons/v7/engine/grammar" "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" + "github.com/splitio/go-split-commons/v7/service/api/specs" fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" "github.com/splitio/go-split-commons/v7/storage/mocks" "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" @@ -69,7 +70,7 @@ func TestSplitSyncTask(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Once().Return(-1) ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, nil, goClientFeatureFlagsRules, goClientRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) - splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false) + splitUpdater := split.NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) splitTask := NewFetchSplitsTask( splitUpdater, From 814c8989614901a356b3a659bcb2de798c20a670 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 Oct 2025 15:33:02 -0300 Subject: [PATCH 24/39] Updated to v8 --- engine/engine.go | 8 ++-- engine/engine_test.go | 8 ++-- engine/evaluator/evaluator.go | 10 ++--- engine/evaluator/evaluator_test.go | 14 +++---- engine/evaluator/mocks/mocks.go | 2 +- engine/grammar/allkeys_test.go | 2 +- engine/grammar/allofset_test.go | 2 +- engine/grammar/anyofset_test.go | 2 +- engine/grammar/between.go | 2 +- engine/grammar/between_test.go | 2 +- engine/grammar/boolean_test.go | 2 +- engine/grammar/condition.go | 4 +- engine/grammar/condition_test.go | 4 +- engine/grammar/contains_test.go | 2 +- .../dependency_test/dependency_test.go | 12 +++--- engine/grammar/endswith_test.go | 2 +- engine/grammar/equalto.go | 2 +- engine/grammar/equalto_test.go | 2 +- engine/grammar/equaltoset_test.go | 2 +- engine/grammar/gtoet.go | 2 +- engine/grammar/gtoet_test.go | 2 +- engine/grammar/inlargesegment.go | 2 +- engine/grammar/inlargesegment_test.go | 4 +- engine/grammar/inrulebasedsegment.go | 2 +- engine/grammar/inrulebasedsegment_test.go | 6 +-- engine/grammar/insegment.go | 2 +- engine/grammar/insegment_test.go | 4 +- engine/grammar/ltoet.go | 2 +- engine/grammar/ltoet_test.go | 2 +- engine/grammar/matcher_test.go | 2 +- engine/grammar/matchers_test.go | 2 +- engine/grammar/partofset_test.go | 2 +- engine/grammar/prerequisites.go | 2 +- engine/grammar/prerequisites_test.go | 2 +- engine/grammar/regex_test.go | 2 +- engine/grammar/rulebuilder.go | 6 +-- engine/grammar/semver.go | 2 +- engine/grammar/semver_test.go | 2 +- engine/grammar/split.go | 6 +-- engine/grammar/split_test.go | 4 +- engine/grammar/startswith_test.go | 2 +- engine/grammar/whitelist_test.go | 2 +- engine/validator/matchers.go | 10 ++--- engine/validator/matchers_test.go | 4 +- flagsets/featuresbyset.go | 2 +- flagsets/featuresbyset_test.go | 2 +- flagsets/flag_set_validator.go | 2 +- go.mod | 2 +- healthcheck/mocks/applicationmonitor.go | 2 +- provisional/impmanager.go | 4 +- provisional/impmanager_test.go | 10 ++--- provisional/strategy/debug.go | 2 +- provisional/strategy/debug_test.go | 2 +- provisional/strategy/impcounter.go | 2 +- provisional/strategy/imphasher.go | 2 +- provisional/strategy/imphasher_test.go | 2 +- provisional/strategy/impobserver.go | 2 +- provisional/strategy/impobserver_test.go | 2 +- provisional/strategy/interfaces.go | 2 +- provisional/strategy/none.go | 2 +- provisional/strategy/none_test.go | 6 +-- provisional/strategy/optimized.go | 8 ++-- provisional/strategy/optimized_test.go | 4 +- provisional/strategy/uniquekeystracker.go | 4 +- .../strategy/uniquekeystracker_test.go | 2 +- push/borrowed.go | 2 +- push/largesegment.go | 2 +- push/largesegment_test.go | 4 +- push/manager.go | 12 +++--- push/manager_test.go | 16 ++++---- push/mocks/parser.go | 2 +- push/mocks/sync.go | 2 +- push/parser.go | 4 +- push/parser_test.go | 2 +- push/processor.go | 4 +- push/processor_test.go | 6 +-- push/segment.go | 2 +- push/segment_test.go | 4 +- push/split.go | 2 +- push/split_test.go | 4 +- push/statustracker.go | 6 +-- push/statustracker_test.go | 6 +-- service/api/auth.go | 8 ++-- service/api/auth_test.go | 8 ++-- service/api/client.go | 6 +-- service/api/client_test.go | 6 +-- service/api/helpers.go | 4 +- service/api/helpers_test.go | 2 +- service/api/http_fetchers.go | 8 ++-- service/api/http_fetchers_test.go | 8 ++-- service/api/http_recorders.go | 4 +- service/api/http_recorders_test.go | 4 +- service/api/mocks/client.go | 2 +- service/api/specs/splitversionfilter.go | 2 +- service/api/specs/splitversionfilter_test.go | 2 +- service/api/split.go | 6 +-- service/api/sse/client.go | 6 +-- service/api/sse/client_test.go | 4 +- service/api/sse/mocks/mock.go | 2 +- service/commons_test.go | 2 +- service/interfaces.go | 2 +- service/local/sanitizer.go | 2 +- service/local/segmentFetcher.go | 4 +- service/local/segmentFetcher_test.go | 6 +-- service/local/splitFetcher.go | 4 +- service/local/splitFetcher_test.go | 4 +- service/mocks/auth.go | 2 +- service/mocks/event.go | 2 +- service/mocks/impression.go | 2 +- service/mocks/large_segment.go | 4 +- service/mocks/segment.go | 4 +- service/mocks/split.go | 4 +- service/mocks/telemetry.go | 2 +- storage/filter/bloom_filter.go | 2 +- storage/inmemory/mutexmap/largesegments.go | 2 +- storage/inmemory/mutexmap/mutexmap_test.go | 4 +- storage/inmemory/mutexmap/rulebasedsegment.go | 2 +- .../mutexmap/rulebasedsegment_test.go | 2 +- storage/inmemory/mutexmap/segments_test.go | 4 +- storage/inmemory/mutexmap/splits.go | 6 +-- storage/inmemory/mutexmap/splits_test.go | 4 +- storage/inmemory/mutexqueue/events.go | 6 +-- storage/inmemory/mutexqueue/events_test.go | 6 +-- storage/inmemory/mutexqueue/impressions.go | 6 +-- .../inmemory/mutexqueue/impressions_test.go | 6 +-- storage/inmemory/telemetry.go | 6 +-- storage/inmemory/telemetry_test.go | 4 +- storage/interfaces.go | 2 +- storage/mocks/event.go | 2 +- storage/mocks/impression.go | 2 +- storage/mocks/impressionscount.go | 2 +- storage/mocks/rulebasedsegment.go | 4 +- storage/mocks/split.go | 4 +- storage/mocks/telemetry.go | 2 +- storage/redis/events.go | 2 +- storage/redis/events_test.go | 2 +- storage/redis/helpers.go | 4 +- storage/redis/impressions.go | 4 +- storage/redis/impressions_test.go | 2 +- storage/redis/impressionscount.go | 4 +- storage/redis/impressionscount_test.go | 2 +- storage/redis/redis.go | 2 +- storage/redis/redis_test.go | 2 +- storage/redis/rulebasedsegment_test.go | 2 +- storage/redis/rulebasedsegments.go | 2 +- storage/redis/segments.go | 2 +- storage/redis/splits.go | 6 +-- storage/redis/splits_test.go | 6 +-- storage/redis/telemetry.go | 6 +-- storage/redis/telemetry_test.go | 4 +- storage/redis/uniquekeys.go | 2 +- storage/redis/uniquekeys_test.go | 2 +- synchronizer/local.go | 20 +++++----- synchronizer/local_test.go | 20 +++++----- synchronizer/manager.go | 14 +++---- synchronizer/manager_test.go | 20 +++++----- synchronizer/mocks/mocks.go | 2 +- synchronizer/mocks/workers.go | 12 +++--- synchronizer/redis_test.go | 2 +- synchronizer/synchronizer.go | 20 +++++----- synchronizer/synchronizer_test.go | 38 +++++++++---------- synchronizer/worker/event/single.go | 8 ++-- synchronizer/worker/event/single_test.go | 16 ++++---- synchronizer/worker/impression/redis.go | 2 +- synchronizer/worker/impression/redis_test.go | 4 +- synchronizer/worker/impression/single.go | 8 ++-- synchronizer/worker/impression/single_test.go | 16 ++++---- synchronizer/worker/impressionscount/redis.go | 4 +- .../worker/impressionscount/redis_test.go | 6 +-- .../worker/impressionscount/single.go | 10 ++--- .../worker/impressionscount/single_test.go | 12 +++--- .../worker/largesegment/largesegment.go | 10 ++--- .../worker/largesegment/largesegment_test.go | 14 +++---- synchronizer/worker/segment/segment.go | 12 +++--- synchronizer/worker/segment/segment_test.go | 20 +++++----- synchronizer/worker/split/split.go | 18 ++++----- synchronizer/worker/split/split_test.go | 22 +++++------ tasks/cleanfiltersync.go | 2 +- tasks/cleanfiltersync_test.go | 2 +- tasks/eventsync.go | 2 +- tasks/eventsync_test.go | 10 ++--- tasks/impressionscountsync.go | 2 +- tasks/impressionscountsync_test.go | 12 +++--- tasks/impressionsync.go | 2 +- tasks/impressionsync_test.go | 12 +++--- tasks/largesegmentsync.go | 6 +-- tasks/largesegmentsync_test.go | 6 +-- tasks/segmentsync.go | 4 +- tasks/segmentsync_test.go | 14 +++---- tasks/splitsync.go | 2 +- tasks/splitsync_test.go | 18 ++++----- tasks/telemetrysync.go | 2 +- tasks/telemetrysync_test.go | 8 ++-- tasks/uniquekeyssync.go | 4 +- tasks/uniquekeyssync_test.go | 10 ++--- telemetry/constants.go | 2 +- telemetry/helpers.go | 4 +- telemetry/helpers_test.go | 2 +- telemetry/interface.go | 2 +- telemetry/localhost.go | 2 +- telemetry/memory.go | 6 +-- telemetry/memory_test.go | 10 ++--- telemetry/redis.go | 4 +- telemetry/redis_test.go | 4 +- 204 files changed, 526 insertions(+), 526 deletions(-) diff --git a/engine/engine.go b/engine/engine.go index 1dcfcec0..d399386d 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -4,10 +4,10 @@ import ( "fmt" "math" - "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/engine/grammar/constants" - "github.com/splitio/go-split-commons/v7/engine/hash" + "github.com/splitio/go-split-commons/v8/engine/evaluator/impressionlabels" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/grammar/constants" + "github.com/splitio/go-split-commons/v8/engine/hash" "github.com/splitio/go-toolkit/v5/hasher" "github.com/splitio/go-toolkit/v5/logging" diff --git a/engine/engine_test.go b/engine/engine_test.go index 981ebf2c..66e8d306 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -7,10 +7,10 @@ import ( "os" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/engine/grammar/constants" - "github.com/splitio/go-split-commons/v7/engine/hash" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/grammar/constants" + "github.com/splitio/go-split-commons/v8/engine/hash" "github.com/splitio/go-toolkit/v5/hasher" "github.com/splitio/go-toolkit/v5/logging" diff --git a/engine/evaluator/evaluator.go b/engine/evaluator/evaluator.go index 507995ef..045d782e 100644 --- a/engine/evaluator/evaluator.go +++ b/engine/evaluator/evaluator.go @@ -4,11 +4,11 @@ import ( "fmt" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine" - "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine" + "github.com/splitio/go-split-commons/v8/engine/evaluator/impressionlabels" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/evaluator/evaluator_test.go b/engine/evaluator/evaluator_test.go index 679a2207..64bb4978 100644 --- a/engine/evaluator/evaluator_test.go +++ b/engine/evaluator/evaluator_test.go @@ -3,13 +3,13 @@ package evaluator import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine" - "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" - "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine" + "github.com/splitio/go-split-commons/v8/engine/evaluator/impressionlabels" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" diff --git a/engine/evaluator/mocks/mocks.go b/engine/evaluator/mocks/mocks.go index 81b58656..24a6cd28 100644 --- a/engine/evaluator/mocks/mocks.go +++ b/engine/evaluator/mocks/mocks.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/engine/evaluator" +import "github.com/splitio/go-split-commons/v8/engine/evaluator" // MockEvaluator mock evaluator type MockEvaluator struct { diff --git a/engine/grammar/allkeys_test.go b/engine/grammar/allkeys_test.go index 7a7ab34c..3cc53bcf 100644 --- a/engine/grammar/allkeys_test.go +++ b/engine/grammar/allkeys_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/allofset_test.go b/engine/grammar/allofset_test.go index 33b408ee..ba4be306 100644 --- a/engine/grammar/allofset_test.go +++ b/engine/grammar/allofset_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/anyofset_test.go b/engine/grammar/anyofset_test.go index f6624a5b..14264f37 100644 --- a/engine/grammar/anyofset_test.go +++ b/engine/grammar/anyofset_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/between.go b/engine/grammar/between.go index 8c72cdd8..4ce7a04e 100644 --- a/engine/grammar/between.go +++ b/engine/grammar/between.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" ) // BetweenMatcher will match if two numbers or two datetimes are equal diff --git a/engine/grammar/between_test.go b/engine/grammar/between_test.go index 1c02dcef..abd8f289 100644 --- a/engine/grammar/between_test.go +++ b/engine/grammar/between_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/boolean_test.go b/engine/grammar/boolean_test.go index 1f34003a..ca836a6a 100644 --- a/engine/grammar/boolean_test.go +++ b/engine/grammar/boolean_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/condition.go b/engine/grammar/condition.go index 2f0c132e..2376d923 100644 --- a/engine/grammar/condition.go +++ b/engine/grammar/condition.go @@ -1,8 +1,8 @@ package grammar import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/condition_test.go b/engine/grammar/condition_test.go index 05bf627b..66dd2bef 100644 --- a/engine/grammar/condition_test.go +++ b/engine/grammar/condition_test.go @@ -3,8 +3,8 @@ package grammar import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" ) diff --git a/engine/grammar/contains_test.go b/engine/grammar/contains_test.go index bc13a1b6..23bf8c58 100644 --- a/engine/grammar/contains_test.go +++ b/engine/grammar/contains_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/dependency_test/dependency_test.go b/engine/grammar/dependency_test/dependency_test.go index 7a64c665..17f65c11 100644 --- a/engine/grammar/dependency_test/dependency_test.go +++ b/engine/grammar/dependency_test/dependency_test.go @@ -7,12 +7,12 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine" - "github.com/splitio/go-split-commons/v7/engine/evaluator" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine" + "github.com/splitio/go-split-commons/v8/engine/evaluator" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/endswith_test.go b/engine/grammar/endswith_test.go index 94cec502..5716f5b1 100644 --- a/engine/grammar/endswith_test.go +++ b/engine/grammar/endswith_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/equalto.go b/engine/grammar/equalto.go index 6fec7468..cbbcd322 100644 --- a/engine/grammar/equalto.go +++ b/engine/grammar/equalto.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" ) // EqualToMatcher will match if two numbers or two datetimes are equal diff --git a/engine/grammar/equalto_test.go b/engine/grammar/equalto_test.go index 3361d093..627af6d2 100644 --- a/engine/grammar/equalto_test.go +++ b/engine/grammar/equalto_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/equaltoset_test.go b/engine/grammar/equaltoset_test.go index 503323ea..f5c4417c 100644 --- a/engine/grammar/equaltoset_test.go +++ b/engine/grammar/equaltoset_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/gtoet.go b/engine/grammar/gtoet.go index fab053a4..5e422477 100644 --- a/engine/grammar/gtoet.go +++ b/engine/grammar/gtoet.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" ) // GreaterThanOrEqualToMatcher will match if two numbers or two datetimes are equal diff --git a/engine/grammar/gtoet_test.go b/engine/grammar/gtoet_test.go index 318ab165..1def1e40 100644 --- a/engine/grammar/gtoet_test.go +++ b/engine/grammar/gtoet_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/inlargesegment.go b/engine/grammar/inlargesegment.go index 77d1fbb1..3ba8d1a6 100644 --- a/engine/grammar/inlargesegment.go +++ b/engine/grammar/inlargesegment.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" ) // InLargeSegmentMatcher matches if the key passed is in the large segment which the matcher was constructed with diff --git a/engine/grammar/inlargesegment_test.go b/engine/grammar/inlargesegment_test.go index 7a064b52..4a2eb72c 100644 --- a/engine/grammar/inlargesegment_test.go +++ b/engine/grammar/inlargesegment_test.go @@ -4,8 +4,8 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/inrulebasedsegment.go b/engine/grammar/inrulebasedsegment.go index 6d79ce97..376cd083 100644 --- a/engine/grammar/inrulebasedsegment.go +++ b/engine/grammar/inrulebasedsegment.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "golang.org/x/exp/slices" ) diff --git a/engine/grammar/inrulebasedsegment_test.go b/engine/grammar/inrulebasedsegment_test.go index 5a36375b..15b2a9ad 100644 --- a/engine/grammar/inrulebasedsegment_test.go +++ b/engine/grammar/inrulebasedsegment_test.go @@ -3,9 +3,9 @@ package grammar import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" diff --git a/engine/grammar/insegment.go b/engine/grammar/insegment.go index b33f7072..60c42bf0 100644 --- a/engine/grammar/insegment.go +++ b/engine/grammar/insegment.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" ) // InSegmentMatcher matches if the key passed is in the segment which the matcher was constructed with diff --git a/engine/grammar/insegment_test.go b/engine/grammar/insegment_test.go index 49cd56b7..e7c795dc 100644 --- a/engine/grammar/insegment_test.go +++ b/engine/grammar/insegment_test.go @@ -4,8 +4,8 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" diff --git a/engine/grammar/ltoet.go b/engine/grammar/ltoet.go index 95d2f3fa..73d34840 100644 --- a/engine/grammar/ltoet.go +++ b/engine/grammar/ltoet.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" ) // LessThanOrEqualToMatcher will match if two numbers or two datetimes are equal diff --git a/engine/grammar/ltoet_test.go b/engine/grammar/ltoet_test.go index 738e7fd1..a099acbc 100644 --- a/engine/grammar/ltoet_test.go +++ b/engine/grammar/ltoet_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/matcher_test.go b/engine/grammar/matcher_test.go index cc20e247..0002c978 100644 --- a/engine/grammar/matcher_test.go +++ b/engine/grammar/matcher_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/matchers_test.go b/engine/grammar/matchers_test.go index 9fb9d25f..41782135 100644 --- a/engine/grammar/matchers_test.go +++ b/engine/grammar/matchers_test.go @@ -3,7 +3,7 @@ package grammar import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" ) diff --git a/engine/grammar/partofset_test.go b/engine/grammar/partofset_test.go index 47193fc7..e00534de 100644 --- a/engine/grammar/partofset_test.go +++ b/engine/grammar/partofset_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/prerequisites.go b/engine/grammar/prerequisites.go index 9b263b9f..7886d87b 100644 --- a/engine/grammar/prerequisites.go +++ b/engine/grammar/prerequisites.go @@ -1,7 +1,7 @@ package grammar import ( - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "golang.org/x/exp/slices" ) diff --git a/engine/grammar/prerequisites_test.go b/engine/grammar/prerequisites_test.go index 21729e46..bc2b2c77 100644 --- a/engine/grammar/prerequisites_test.go +++ b/engine/grammar/prerequisites_test.go @@ -3,7 +3,7 @@ package grammar import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) diff --git a/engine/grammar/regex_test.go b/engine/grammar/regex_test.go index b71d05f3..9995860f 100644 --- a/engine/grammar/regex_test.go +++ b/engine/grammar/regex_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/rulebuilder.go b/engine/grammar/rulebuilder.go index 40cb8450..6cc9a337 100644 --- a/engine/grammar/rulebuilder.go +++ b/engine/grammar/rulebuilder.go @@ -6,9 +6,9 @@ import ( "golang.org/x/exp/slices" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/semver.go b/engine/grammar/semver.go index 604ea7cd..c92bd156 100644 --- a/engine/grammar/semver.go +++ b/engine/grammar/semver.go @@ -3,7 +3,7 @@ package grammar import ( "fmt" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/semver_test.go b/engine/grammar/semver_test.go index ee1a908c..a5348198 100644 --- a/engine/grammar/semver_test.go +++ b/engine/grammar/semver_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/split.go b/engine/grammar/split.go index a39c2ef5..586eca45 100644 --- a/engine/grammar/split.go +++ b/engine/grammar/split.go @@ -1,9 +1,9 @@ package grammar import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" - "github.com/splitio/go-split-commons/v7/engine/grammar/constants" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/evaluator/impressionlabels" + "github.com/splitio/go-split-commons/v8/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/split_test.go b/engine/grammar/split_test.go index 63ee1b58..81594f4b 100644 --- a/engine/grammar/split_test.go +++ b/engine/grammar/split_test.go @@ -3,8 +3,8 @@ package grammar import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar/constants" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/startswith_test.go b/engine/grammar/startswith_test.go index 6e553d13..c6b02fb9 100644 --- a/engine/grammar/startswith_test.go +++ b/engine/grammar/startswith_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/grammar/whitelist_test.go b/engine/grammar/whitelist_test.go index 48bb365a..aeaf684a 100644 --- a/engine/grammar/whitelist_test.go +++ b/engine/grammar/whitelist_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/validator/matchers.go b/engine/validator/matchers.go index 1767ea01..3d05d7f8 100644 --- a/engine/validator/matchers.go +++ b/engine/validator/matchers.go @@ -1,11 +1,11 @@ package validator import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/evaluator" - "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/evaluator" + "github.com/splitio/go-split-commons/v8/engine/evaluator/impressionlabels" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/engine/validator/matchers_test.go b/engine/validator/matchers_test.go index c272d6ac..829fd12f 100644 --- a/engine/validator/matchers_test.go +++ b/engine/validator/matchers_test.go @@ -3,8 +3,8 @@ package validator import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/flagsets/featuresbyset.go b/flagsets/featuresbyset.go index 9d483d8b..4fde4c5f 100644 --- a/flagsets/featuresbyset.go +++ b/flagsets/featuresbyset.go @@ -1,6 +1,6 @@ package flagsets -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" type FeaturesBySet struct { data map[string]map[string]struct{} diff --git a/flagsets/featuresbyset_test.go b/flagsets/featuresbyset_test.go index dea6d828..294ad0c2 100644 --- a/flagsets/featuresbyset_test.go +++ b/flagsets/featuresbyset_test.go @@ -3,7 +3,7 @@ package flagsets import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) func TestFeaturesBySet(t *testing.T) { diff --git a/flagsets/flag_set_validator.go b/flagsets/flag_set_validator.go index 541b79a9..b3ef7834 100644 --- a/flagsets/flag_set_validator.go +++ b/flagsets/flag_set_validator.go @@ -6,7 +6,7 @@ import ( "sort" "strings" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "golang.org/x/exp/slices" ) diff --git a/go.mod b/go.mod index 7ffe3ef2..50c18fd9 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/splitio/go-split-commons/v7 +module github.com/splitio/go-split-commons/v8 go 1.18 diff --git a/healthcheck/mocks/applicationmonitor.go b/healthcheck/mocks/applicationmonitor.go index a0ec38a4..a95f50f5 100644 --- a/healthcheck/mocks/applicationmonitor.go +++ b/healthcheck/mocks/applicationmonitor.go @@ -1,7 +1,7 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/healthcheck/application" + "github.com/splitio/go-split-commons/v8/healthcheck/application" "github.com/stretchr/testify/mock" ) diff --git a/provisional/impmanager.go b/provisional/impmanager.go index c08a23b0..da98b65a 100644 --- a/provisional/impmanager.go +++ b/provisional/impmanager.go @@ -1,8 +1,8 @@ package provisional import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" ) // ImpressionManager interface diff --git a/provisional/impmanager_test.go b/provisional/impmanager_test.go index dd7dbc54..1f8553ef 100644 --- a/provisional/impmanager_test.go +++ b/provisional/impmanager_test.go @@ -4,11 +4,11 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/storage/filter" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/storage/filter" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/telemetry" ) func TestImpManagerInMemoryDebugListenerDisabled(t *testing.T) { diff --git a/provisional/strategy/debug.go b/provisional/strategy/debug.go index e3ad1155..3bb9a282 100644 --- a/provisional/strategy/debug.go +++ b/provisional/strategy/debug.go @@ -1,6 +1,6 @@ package strategy -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // DebugImpl struct for debug impression mode strategy. type DebugImpl struct { diff --git a/provisional/strategy/debug_test.go b/provisional/strategy/debug_test.go index 4af12d5e..f056718b 100644 --- a/provisional/strategy/debug_test.go +++ b/provisional/strategy/debug_test.go @@ -3,7 +3,7 @@ package strategy import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) func TestDebugMode(t *testing.T) { diff --git a/provisional/strategy/impcounter.go b/provisional/strategy/impcounter.go index 755fbd36..8bf4d98e 100644 --- a/provisional/strategy/impcounter.go +++ b/provisional/strategy/impcounter.go @@ -3,7 +3,7 @@ package strategy import ( "sync" - "github.com/splitio/go-split-commons/v7/util" + "github.com/splitio/go-split-commons/v8/util" ) // Key struct for mapping each key to an amount diff --git a/provisional/strategy/imphasher.go b/provisional/strategy/imphasher.go index c17e4d5d..93d694c1 100644 --- a/provisional/strategy/imphasher.go +++ b/provisional/strategy/imphasher.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/provisional/hashing" ) diff --git a/provisional/strategy/imphasher_test.go b/provisional/strategy/imphasher_test.go index a0c807b2..54e2c7d4 100644 --- a/provisional/strategy/imphasher_test.go +++ b/provisional/strategy/imphasher_test.go @@ -3,7 +3,7 @@ package strategy import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) func TestHasher(t *testing.T) { diff --git a/provisional/strategy/impobserver.go b/provisional/strategy/impobserver.go index 7e6277c1..f1aeeb71 100644 --- a/provisional/strategy/impobserver.go +++ b/provisional/strategy/impobserver.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/provisional/int64cache" ) diff --git a/provisional/strategy/impobserver_test.go b/provisional/strategy/impobserver_test.go index 8c10ec69..a08064bd 100644 --- a/provisional/strategy/impobserver_test.go +++ b/provisional/strategy/impobserver_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/provisional/int64cache" ) diff --git a/provisional/strategy/interfaces.go b/provisional/strategy/interfaces.go index f37007e4..428b3415 100644 --- a/provisional/strategy/interfaces.go +++ b/provisional/strategy/interfaces.go @@ -1,6 +1,6 @@ package strategy -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // ProcessStrategyInterface interface type ProcessStrategyInterface interface { diff --git a/provisional/strategy/none.go b/provisional/strategy/none.go index 0eb2c2d2..acce316b 100644 --- a/provisional/strategy/none.go +++ b/provisional/strategy/none.go @@ -3,7 +3,7 @@ package strategy import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) // NoneImpl struct for none impression mode strategy. diff --git a/provisional/strategy/none_test.go b/provisional/strategy/none_test.go index cee17ffb..b3987f8f 100644 --- a/provisional/strategy/none_test.go +++ b/provisional/strategy/none_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/filter" - "github.com/splitio/go-split-commons/v7/util" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/filter" + "github.com/splitio/go-split-commons/v8/util" ) func TestNoneMode(t *testing.T) { diff --git a/provisional/strategy/optimized.go b/provisional/strategy/optimized.go index c1e0ddc1..44f49488 100644 --- a/provisional/strategy/optimized.go +++ b/provisional/strategy/optimized.go @@ -3,10 +3,10 @@ package strategy import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" - "github.com/splitio/go-split-commons/v7/util" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" + "github.com/splitio/go-split-commons/v8/util" ) // OptimizedImpl struct for optimized impression mode strategy. diff --git a/provisional/strategy/optimized_test.go b/provisional/strategy/optimized_test.go index 6f44e1aa..0989fe41 100644 --- a/provisional/strategy/optimized_test.go +++ b/provisional/strategy/optimized_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/inmemory" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/inmemory" ) func TestOptimizedMode(t *testing.T) { diff --git a/provisional/strategy/uniquekeystracker.go b/provisional/strategy/uniquekeystracker.go index 5e1003b2..aa4bd664 100644 --- a/provisional/strategy/uniquekeystracker.go +++ b/provisional/strategy/uniquekeystracker.go @@ -3,8 +3,8 @@ package strategy import ( "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" ) diff --git a/provisional/strategy/uniquekeystracker_test.go b/provisional/strategy/uniquekeystracker_test.go index 5ef87949..a2e71011 100644 --- a/provisional/strategy/uniquekeystracker_test.go +++ b/provisional/strategy/uniquekeystracker_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/storage/filter" + "github.com/splitio/go-split-commons/v8/storage/filter" ) func Test(t *testing.T) { diff --git a/push/borrowed.go b/push/borrowed.go index 1284b7f7..cc2af249 100644 --- a/push/borrowed.go +++ b/push/borrowed.go @@ -1,6 +1,6 @@ package push -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // Borrowed synchronizer interface to break circular dependencies type synchronizerInterface interface { diff --git a/push/largesegment.go b/push/largesegment.go index f2d691ce..0ada1a54 100644 --- a/push/largesegment.go +++ b/push/largesegment.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" ) diff --git a/push/largesegment_test.go b/push/largesegment_test.go index 3b4de09d..33e0cfc4 100644 --- a/push/largesegment_test.go +++ b/push/largesegment_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/push/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/push/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/manager.go b/push/manager.go index f1f79c76..6b1ece86 100644 --- a/push/manager.go +++ b/push/manager.go @@ -7,12 +7,12 @@ import ( "sync" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/sse" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/sse" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" diff --git a/push/manager_test.go b/push/manager_test.go index 504dfc52..c1b9f611 100644 --- a/push/manager_test.go +++ b/push/manager_test.go @@ -6,14 +6,14 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - pushMocks "github.com/splitio/go-split-commons/v7/push/mocks" - "github.com/splitio/go-split-commons/v7/service/api/sse" - sseMocks "github.com/splitio/go-split-commons/v7/service/api/sse/mocks" - serviceMocks "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + pushMocks "github.com/splitio/go-split-commons/v8/push/mocks" + "github.com/splitio/go-split-commons/v8/service/api/sse" + sseMocks "github.com/splitio/go-split-commons/v8/service/api/sse/mocks" + serviceMocks "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" diff --git a/push/mocks/parser.go b/push/mocks/parser.go index eac12267..da9fb260 100644 --- a/push/mocks/parser.go +++ b/push/mocks/parser.go @@ -1,7 +1,7 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/service/api/sse" + "github.com/splitio/go-split-commons/v8/service/api/sse" ) type NotificationParserMock struct { diff --git a/push/mocks/sync.go b/push/mocks/sync.go index 39aa8c0b..a198cffc 100644 --- a/push/mocks/sync.go +++ b/push/mocks/sync.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" type LocalSyncMock struct { SyncAllCall func() error diff --git a/push/parser.go b/push/parser.go index 4420dddb..0b16dbef 100644 --- a/push/parser.go +++ b/push/parser.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api/sse" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api/sse" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/datautils" diff --git a/push/parser_test.go b/push/parser_test.go index 992b9696..2b3ceeed 100644 --- a/push/parser_test.go +++ b/push/parser_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/datautils" "github.com/splitio/go-toolkit/v5/logging" diff --git a/push/processor.go b/push/processor.go index d54c30b5..c7d515cf 100644 --- a/push/processor.go +++ b/push/processor.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/processor_test.go b/push/processor_test.go index e6cb256e..6a9bb5e6 100644 --- a/push/processor_test.go +++ b/push/processor_test.go @@ -3,9 +3,9 @@ package push import ( "testing" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/push/mocks" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/push/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/segment.go b/push/segment.go index 50017372..7bc4b447 100644 --- a/push/segment.go +++ b/push/segment.go @@ -5,7 +5,7 @@ import ( "fmt" "sync/atomic" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" diff --git a/push/segment_test.go b/push/segment_test.go index f9dcece8..b119558a 100644 --- a/push/segment_test.go +++ b/push/segment_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/push/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/push/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/split.go b/push/split.go index 3ec7cae0..0ad9c6e5 100644 --- a/push/split.go +++ b/push/split.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" ) diff --git a/push/split_test.go b/push/split_test.go index 5aac938b..1ae8b242 100644 --- a/push/split_test.go +++ b/push/split_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/push/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/push/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/statustracker.go b/push/statustracker.go index 0e6d4b09..bfdae188 100644 --- a/push/statustracker.go +++ b/push/statustracker.go @@ -4,9 +4,9 @@ import ( "fmt" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/push/statustracker_test.go b/push/statustracker_test.go index 0c810eb9..3e75b4b5 100644 --- a/push/statustracker_test.go +++ b/push/statustracker_test.go @@ -3,9 +3,9 @@ package push import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/auth.go b/service/api/auth.go index 89d8f571..e8d7497a 100644 --- a/service/api/auth.go +++ b/service/api/auth.go @@ -3,10 +3,10 @@ package api import ( "encoding/json" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/auth_test.go b/service/api/auth_test.go index 5c5464d6..f176b861 100644 --- a/service/api/auth_test.go +++ b/service/api/auth_test.go @@ -6,10 +6,10 @@ import ( "net/http/httptest" "testing" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/mocks" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/client.go b/service/api/client.go index 53e67cfd..a6044d0a 100644 --- a/service/api/client.go +++ b/service/api/client.go @@ -9,9 +9,9 @@ import ( "net/http" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/client_test.go b/service/api/client_test.go index eee4c242..a36a8432 100644 --- a/service/api/client_test.go +++ b/service/api/client_test.go @@ -8,9 +8,9 @@ import ( "net/http/httptest" "testing" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/helpers.go b/service/api/helpers.go index 2f352ce4..c3d38ebc 100644 --- a/service/api/helpers.go +++ b/service/api/helpers.go @@ -6,8 +6,8 @@ import ( "io" "net/http" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api/specs" ) const ( diff --git a/service/api/helpers_test.go b/service/api/helpers_test.go index c3cbbe3f..bd4885c7 100644 --- a/service/api/helpers_test.go +++ b/service/api/helpers_test.go @@ -3,7 +3,7 @@ package api import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) func TestAddMetadataToHeaders(t *testing.T) { diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 9bb6bd14..08787505 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -7,10 +7,10 @@ import ( "net/http" "strings" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index c6df7625..143dcce7 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -13,10 +13,10 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" diff --git a/service/api/http_recorders.go b/service/api/http_recorders.go index 6211f3c4..16e51762 100644 --- a/service/api/http_recorders.go +++ b/service/api/http_recorders.go @@ -3,8 +3,8 @@ package api import ( "encoding/json" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/http_recorders_test.go b/service/api/http_recorders_test.go index f1b6709a..5adbcbb9 100644 --- a/service/api/http_recorders_test.go +++ b/service/api/http_recorders_test.go @@ -9,8 +9,8 @@ import ( "net/http/httptest" "testing" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/mocks/client.go b/service/api/mocks/client.go index 7c82cacd..e249928f 100644 --- a/service/api/mocks/client.go +++ b/service/api/mocks/client.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/service" +import "github.com/splitio/go-split-commons/v8/service" // ClientMock mocks client type ClientMock struct { diff --git a/service/api/specs/splitversionfilter.go b/service/api/specs/splitversionfilter.go index be2e401e..0cd3fb92 100644 --- a/service/api/specs/splitversionfilter.go +++ b/service/api/specs/splitversionfilter.go @@ -1,7 +1,7 @@ package specs import ( - "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/grammar" ) type SplitVersionFilter struct { diff --git a/service/api/specs/splitversionfilter_test.go b/service/api/specs/splitversionfilter_test.go index 43680447..c02d1128 100644 --- a/service/api/specs/splitversionfilter_test.go +++ b/service/api/specs/splitversionfilter_test.go @@ -3,7 +3,7 @@ package specs import ( "testing" - "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/grammar" ) func TestParseAndValidate(t *testing.T) { diff --git a/service/api/split.go b/service/api/split.go index 7d0153e8..0c7b3e33 100644 --- a/service/api/split.go +++ b/service/api/split.go @@ -1,9 +1,9 @@ package api import ( - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/api/sse/client.go b/service/api/sse/client.go index 9f31254a..61efac4e 100644 --- a/service/api/sse/client.go +++ b/service/api/sse/client.go @@ -4,9 +4,9 @@ import ( "errors" "strings" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/sse" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" diff --git a/service/api/sse/client_test.go b/service/api/sse/client_test.go index 5d6f66c6..c1837a1d 100644 --- a/service/api/sse/client_test.go +++ b/service/api/sse/client_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/sse" ) diff --git a/service/api/sse/mocks/mock.go b/service/api/sse/mocks/mock.go index cb3b43e7..8a28712a 100644 --- a/service/api/sse/mocks/mock.go +++ b/service/api/sse/mocks/mock.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/service/api/sse" +import "github.com/splitio/go-split-commons/v8/service/api/sse" type StreamingClientMock struct { ConnectStreamingCall func(token string, streamingStatus chan int, channelList []string, handleIncomingMessage func(sse.IncomingMessage)) diff --git a/service/commons_test.go b/service/commons_test.go index 7ea533f7..7594adc8 100644 --- a/service/commons_test.go +++ b/service/commons_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/splitio/go-split-commons/v7/service/api/specs" + "github.com/splitio/go-split-commons/v8/service/api/specs" "github.com/splitio/go-toolkit/v5/common" diff --git a/service/interfaces.go b/service/interfaces.go index 8f157b24..c9270c10 100644 --- a/service/interfaces.go +++ b/service/interfaces.go @@ -1,6 +1,6 @@ package service -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // AuthClient inteface to be implemneted by AuthClient type AuthClient interface { diff --git a/service/local/sanitizer.go b/service/local/sanitizer.go index dfb46f5b..a67ee798 100644 --- a/service/local/sanitizer.go +++ b/service/local/sanitizer.go @@ -4,7 +4,7 @@ import ( "fmt" "math/rand" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) func splitSanitization(splitChange *dtos.FFResponseLocalV13) *dtos.FFResponseLocalV13 { diff --git a/service/local/segmentFetcher.go b/service/local/segmentFetcher.go index eba83c42..a7d28e0e 100644 --- a/service/local/segmentFetcher.go +++ b/service/local/segmentFetcher.go @@ -7,8 +7,8 @@ import ( "fmt" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/local/segmentFetcher_test.go b/service/local/segmentFetcher_test.go index 9962bea4..1bdb030b 100644 --- a/service/local/segmentFetcher_test.go +++ b/service/local/segmentFetcher_test.go @@ -5,9 +5,9 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/local/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/local/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index 3677b5d7..1eb72a4a 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -9,8 +9,8 @@ import ( "strings" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/splitio/go-toolkit/v5/logging" yaml "gopkg.in/yaml.v3" diff --git a/service/local/splitFetcher_test.go b/service/local/splitFetcher_test.go index 8e68e9b8..ccbb4c5b 100644 --- a/service/local/splitFetcher_test.go +++ b/service/local/splitFetcher_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/local/mocks" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/local/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/service/mocks/auth.go b/service/mocks/auth.go index 354a4a43..ff83c285 100644 --- a/service/mocks/auth.go +++ b/service/mocks/auth.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockAuthClient mocked implementation of auth type MockAuthClient struct { diff --git a/service/mocks/event.go b/service/mocks/event.go index 7e4b1562..dd827186 100644 --- a/service/mocks/event.go +++ b/service/mocks/event.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockEventRecorder mocked implementation of event recorder type MockEventRecorder struct { diff --git a/service/mocks/impression.go b/service/mocks/impression.go index 66e40184..056db139 100644 --- a/service/mocks/impression.go +++ b/service/mocks/impression.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockImpressionRecorder mocked implementation of impression recorder type MockImpressionRecorder struct { diff --git a/service/mocks/large_segment.go b/service/mocks/large_segment.go index 9e9c68c9..e46d7ee2 100644 --- a/service/mocks/large_segment.go +++ b/service/mocks/large_segment.go @@ -1,8 +1,8 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" ) type MockLargeSegmentFetcher struct { diff --git a/service/mocks/segment.go b/service/mocks/segment.go index c0d1b252..5825c2bf 100644 --- a/service/mocks/segment.go +++ b/service/mocks/segment.go @@ -1,8 +1,8 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" ) // MockSegmentFetcher mocked implementation of segment fetcher diff --git a/service/mocks/split.go b/service/mocks/split.go index 05574149..2acc97aa 100644 --- a/service/mocks/split.go +++ b/service/mocks/split.go @@ -1,8 +1,8 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" "github.com/stretchr/testify/mock" ) diff --git a/service/mocks/telemetry.go b/service/mocks/telemetry.go index 65ed93c3..df62d9ba 100644 --- a/service/mocks/telemetry.go +++ b/service/mocks/telemetry.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockTelemetryRecorder mocked implementation of telemetry recorder type MockTelemetryRecorder struct { diff --git a/storage/filter/bloom_filter.go b/storage/filter/bloom_filter.go index 1f09a4a4..4439b6c0 100644 --- a/storage/filter/bloom_filter.go +++ b/storage/filter/bloom_filter.go @@ -4,7 +4,7 @@ import ( "sync" "github.com/bits-and-blooms/bloom/v3" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" ) // BloomFilter description diff --git a/storage/inmemory/mutexmap/largesegments.go b/storage/inmemory/mutexmap/largesegments.go index 49a93844..9c93c69b 100644 --- a/storage/inmemory/mutexmap/largesegments.go +++ b/storage/inmemory/mutexmap/largesegments.go @@ -5,7 +5,7 @@ import ( "sort" "sync" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" ) // LargeSegmentsStorageImpl implements the LargeSegmentsStorage interface diff --git a/storage/inmemory/mutexmap/mutexmap_test.go b/storage/inmemory/mutexmap/mutexmap_test.go index 365b78c3..b5fba0a4 100644 --- a/storage/inmemory/mutexmap/mutexmap_test.go +++ b/storage/inmemory/mutexmap/mutexmap_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" ) func TestSplitMutexMapConcurrency(t *testing.T) { diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index d247ab7a..557af46e 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/datastructures/set" ) diff --git a/storage/inmemory/mutexmap/rulebasedsegment_test.go b/storage/inmemory/mutexmap/rulebasedsegment_test.go index 9e7a7a7d..2d5ec235 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment_test.go +++ b/storage/inmemory/mutexmap/rulebasedsegment_test.go @@ -4,7 +4,7 @@ import ( "sync" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/stretchr/testify/assert" ) diff --git a/storage/inmemory/mutexmap/segments_test.go b/storage/inmemory/mutexmap/segments_test.go index e281a622..9a3679b1 100644 --- a/storage/inmemory/mutexmap/segments_test.go +++ b/storage/inmemory/mutexmap/segments_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" "github.com/splitio/go-toolkit/v5/datastructures/set" ) diff --git a/storage/inmemory/mutexmap/splits.go b/storage/inmemory/mutexmap/splits.go index 5de3f907..9760b339 100644 --- a/storage/inmemory/mutexmap/splits.go +++ b/storage/inmemory/mutexmap/splits.go @@ -3,9 +3,9 @@ package mutexmap import ( "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" ) diff --git a/storage/inmemory/mutexmap/splits_test.go b/storage/inmemory/mutexmap/splits_test.go index 3430d700..71ab82db 100644 --- a/storage/inmemory/mutexmap/splits_test.go +++ b/storage/inmemory/mutexmap/splits_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/stretchr/testify/assert" ) diff --git a/storage/inmemory/mutexqueue/events.go b/storage/inmemory/mutexqueue/events.go index b7f01925..3eb42bdd 100644 --- a/storage/inmemory/mutexqueue/events.go +++ b/storage/inmemory/mutexqueue/events.go @@ -5,9 +5,9 @@ import ( "fmt" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/storage/inmemory/mutexqueue/events_test.go b/storage/inmemory/mutexqueue/events_test.go index 513f84af..0b635827 100644 --- a/storage/inmemory/mutexqueue/events_test.go +++ b/storage/inmemory/mutexqueue/events_test.go @@ -4,9 +4,9 @@ import ( "strconv" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/storage/inmemory/mutexqueue/impressions.go b/storage/inmemory/mutexqueue/impressions.go index e204d4b1..974ded8e 100644 --- a/storage/inmemory/mutexqueue/impressions.go +++ b/storage/inmemory/mutexqueue/impressions.go @@ -4,9 +4,9 @@ import ( "container/list" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/storage/inmemory/mutexqueue/impressions_test.go b/storage/inmemory/mutexqueue/impressions_test.go index c6d89247..c44641ca 100644 --- a/storage/inmemory/mutexqueue/impressions_test.go +++ b/storage/inmemory/mutexqueue/impressions_test.go @@ -4,9 +4,9 @@ import ( "strconv" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/storage/inmemory/telemetry.go b/storage/inmemory/telemetry.go index af4eb2e6..460b4eaa 100644 --- a/storage/inmemory/telemetry.go +++ b/storage/inmemory/telemetry.go @@ -6,9 +6,9 @@ import ( "sync/atomic" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - constants "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + constants "github.com/splitio/go-split-commons/v8/telemetry" ) type latencies struct { diff --git a/storage/inmemory/telemetry_test.go b/storage/inmemory/telemetry_test.go index 6c6d3e84..98a83901 100644 --- a/storage/inmemory/telemetry_test.go +++ b/storage/inmemory/telemetry_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/telemetry" ) func TestTelemetryStorage(t *testing.T) { diff --git a/storage/interfaces.go b/storage/interfaces.go index fd9d87f4..e126e7f8 100644 --- a/storage/interfaces.go +++ b/storage/interfaces.go @@ -3,7 +3,7 @@ package storage import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/datastructures/set" ) diff --git a/storage/mocks/event.go b/storage/mocks/event.go index c9d6c7e8..f9db93c9 100644 --- a/storage/mocks/event.go +++ b/storage/mocks/event.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockEventStorage is a mocked implementation of Event Storage type MockEventStorage struct { diff --git a/storage/mocks/impression.go b/storage/mocks/impression.go index 691341c3..cf8f2809 100644 --- a/storage/mocks/impression.go +++ b/storage/mocks/impression.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // MockImpressionStorage is a mocked implementation of Impression Storage type MockImpressionStorage struct { diff --git a/storage/mocks/impressionscount.go b/storage/mocks/impressionscount.go index 824824ce..659620eb 100644 --- a/storage/mocks/impressionscount.go +++ b/storage/mocks/impressionscount.go @@ -1,6 +1,6 @@ package mocks -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" type MockImpressionsCountStorage struct { RecordImpressionsCountCall func(impressions dtos.ImpressionsCountDTO) error diff --git a/storage/mocks/rulebasedsegment.go b/storage/mocks/rulebasedsegment.go index e0c055d7..3cccaf51 100644 --- a/storage/mocks/rulebasedsegment.go +++ b/storage/mocks/rulebasedsegment.go @@ -1,8 +1,8 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/stretchr/testify/mock" ) diff --git a/storage/mocks/split.go b/storage/mocks/split.go index b618f122..e1c1c26b 100644 --- a/storage/mocks/split.go +++ b/storage/mocks/split.go @@ -1,8 +1,8 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/stretchr/testify/mock" ) diff --git a/storage/mocks/telemetry.go b/storage/mocks/telemetry.go index 72a59482..b2f0209f 100644 --- a/storage/mocks/telemetry.go +++ b/storage/mocks/telemetry.go @@ -3,7 +3,7 @@ package mocks import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) // MockTelemetryStorage is a mocked implementation of Telemetry Storage diff --git a/storage/redis/events.go b/storage/redis/events.go index 1d233a04..e345596e 100644 --- a/storage/redis/events.go +++ b/storage/redis/events.go @@ -6,7 +6,7 @@ import ( "math" "sync" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/queuecache" "github.com/splitio/go-toolkit/v5/redis" diff --git a/storage/redis/events_test.go b/storage/redis/events_test.go index ed9a08ae..0dee4711 100644 --- a/storage/redis/events_test.go +++ b/storage/redis/events_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/storage/redis/helpers.go b/storage/redis/helpers.go index 80d2a12e..e84124f3 100644 --- a/storage/redis/helpers.go +++ b/storage/redis/helpers.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/impressions.go b/storage/redis/impressions.go index 9822cb9f..cd906e6a 100644 --- a/storage/redis/impressions.go +++ b/storage/redis/impressions.go @@ -5,8 +5,8 @@ import ( "sync" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/impressions_test.go b/storage/redis/impressions_test.go index ac6b08a7..ce9b5086 100644 --- a/storage/redis/impressions_test.go +++ b/storage/redis/impressions_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/storage/redis/impressionscount.go b/storage/redis/impressionscount.go index fe6993b3..d2894f86 100644 --- a/storage/redis/impressionscount.go +++ b/storage/redis/impressionscount.go @@ -7,8 +7,8 @@ import ( "sync" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/impressionscount_test.go b/storage/redis/impressionscount_test.go index 7dd46e29..451745f5 100644 --- a/storage/redis/impressionscount_test.go +++ b/storage/redis/impressionscount_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/storage/redis/redis.go b/storage/redis/redis.go index afe839e4..b7bc927d 100644 --- a/storage/redis/redis.go +++ b/storage/redis/redis.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/splitio/go-split-commons/v7/conf" + "github.com/splitio/go-split-commons/v8/conf" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/redis_test.go b/storage/redis/redis_test.go index 17210d9f..7c418b53 100644 --- a/storage/redis/redis_test.go +++ b/storage/redis/redis_test.go @@ -5,7 +5,7 @@ import ( "net" "testing" - "github.com/splitio/go-split-commons/v7/conf" + "github.com/splitio/go-split-commons/v8/conf" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/storage/redis/rulebasedsegment_test.go b/storage/redis/rulebasedsegment_test.go index 8ed1c2ab..38d06eb1 100644 --- a/storage/redis/rulebasedsegment_test.go +++ b/storage/redis/rulebasedsegment_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/storage/redis/rulebasedsegments.go b/storage/redis/rulebasedsegments.go index 9e3769dc..6857f577 100644 --- a/storage/redis/rulebasedsegments.go +++ b/storage/redis/rulebasedsegments.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/segments.go b/storage/redis/segments.go index 171fa972..e2693c4c 100644 --- a/storage/redis/segments.go +++ b/storage/redis/segments.go @@ -6,7 +6,7 @@ import ( "strings" "sync" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" diff --git a/storage/redis/splits.go b/storage/redis/splits.go index 8688ee0d..0805a43c 100644 --- a/storage/redis/splits.go +++ b/storage/redis/splits.go @@ -8,9 +8,9 @@ import ( "strings" "sync" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" diff --git a/storage/redis/splits_test.go b/storage/redis/splits_test.go index 40902221..fe5b72fb 100644 --- a/storage/redis/splits_test.go +++ b/storage/redis/splits_test.go @@ -10,9 +10,9 @@ import ( "golang.org/x/exp/slices" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" diff --git a/storage/redis/telemetry.go b/storage/redis/telemetry.go index afd10930..bfaeca3c 100644 --- a/storage/redis/telemetry.go +++ b/storage/redis/telemetry.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/telemetry_test.go b/storage/redis/telemetry_test.go index 9e37304a..9d650412 100644 --- a/storage/redis/telemetry_test.go +++ b/storage/redis/telemetry_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/storage/redis/uniquekeys.go b/storage/redis/uniquekeys.go index dd09cab0..3746d10a 100644 --- a/storage/redis/uniquekeys.go +++ b/storage/redis/uniquekeys.go @@ -3,7 +3,7 @@ package redis import ( "sync" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" ) diff --git a/storage/redis/uniquekeys_test.go b/storage/redis/uniquekeys_test.go index 89f82d17..34067a91 100644 --- a/storage/redis/uniquekeys_test.go +++ b/storage/redis/uniquekeys_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/redis" "github.com/splitio/go-toolkit/v5/redis/mocks" diff --git a/synchronizer/local.go b/synchronizer/local.go index edad4a08..4bec7c0c 100644 --- a/synchronizer/local.go +++ b/synchronizer/local.go @@ -3,16 +3,16 @@ package synchronizer import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/service/api" - "github.com/splitio/go-split-commons/v7/service/api/specs" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" - "github.com/splitio/go-split-commons/v7/tasks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/service/api" + "github.com/splitio/go-split-commons/v8/service/api/specs" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/tasks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 6fb044fb..14783e1a 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -5,16 +5,16 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api" - "github.com/splitio/go-split-commons/v7/service/api/specs" - httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api" + "github.com/splitio/go-split-commons/v8/service/api/specs" + httpMocks "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" "github.com/splitio/go-toolkit/v5/logging" diff --git a/synchronizer/manager.go b/synchronizer/manager.go index b8b83e0b..b2e2d575 100644 --- a/synchronizer/manager.go +++ b/synchronizer/manager.go @@ -6,13 +6,13 @@ import ( "sync/atomic" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - hc "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/push" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + hc "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/push" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/backoff" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/struct/traits/lifecycle" diff --git a/synchronizer/manager_test.go b/synchronizer/manager_test.go index 24e9f7e4..dfda0b21 100644 --- a/synchronizer/manager_test.go +++ b/synchronizer/manager_test.go @@ -6,16 +6,16 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/healthcheck/application" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/push" - pushMocks "github.com/splitio/go-split-commons/v7/push/mocks" - apiMocks "github.com/splitio/go-split-commons/v7/service/mocks" - storageMocks "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/healthcheck/application" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/push" + pushMocks "github.com/splitio/go-split-commons/v8/push/mocks" + apiMocks "github.com/splitio/go-split-commons/v8/service/mocks" + storageMocks "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/mocks/mocks.go b/synchronizer/mocks/mocks.go index 2bef575a..62d88626 100644 --- a/synchronizer/mocks/mocks.go +++ b/synchronizer/mocks/mocks.go @@ -3,7 +3,7 @@ package mocks import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/dtos" ) // MockSynchronizer mock implementation diff --git a/synchronizer/mocks/workers.go b/synchronizer/mocks/workers.go index 75e0783b..101e1b10 100644 --- a/synchronizer/mocks/workers.go +++ b/synchronizer/mocks/workers.go @@ -1,12 +1,12 @@ package mocks import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/largesegment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/event" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impression" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/largesegment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" "github.com/stretchr/testify/mock" ) diff --git a/synchronizer/redis_test.go b/synchronizer/redis_test.go index 43ceae99..2f6889aa 100644 --- a/synchronizer/redis_test.go +++ b/synchronizer/redis_test.go @@ -3,7 +3,7 @@ package synchronizer import ( "testing" - "github.com/splitio/go-split-commons/v7/synchronizer/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index 0ba12f88..a4535724 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -3,16 +3,16 @@ package synchronizer import ( "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impressionscount" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/largesegment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" - "github.com/splitio/go-split-commons/v7/tasks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/event" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impression" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impressionscount" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/largesegment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/tasks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/sync" diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 5e67f98b..f343b0c1 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -7,28 +7,28 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/push" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api" - "github.com/splitio/go-split-commons/v7/service/api/specs" - httpMocks "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - storageMock "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/push" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api" + "github.com/splitio/go-split-commons/v8/service/api/specs" + httpMocks "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + storageMock "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - syncMocks "github.com/splitio/go-split-commons/v7/synchronizer/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" - "github.com/splitio/go-split-commons/v7/tasks" - "github.com/splitio/go-split-commons/v7/telemetry" + syncMocks "github.com/splitio/go-split-commons/v8/synchronizer/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/event" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impression" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/tasks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/datastructures/set" diff --git a/synchronizer/worker/event/single.go b/synchronizer/worker/event/single.go index 526f40cc..3151454f 100644 --- a/synchronizer/worker/event/single.go +++ b/synchronizer/worker/event/single.go @@ -4,10 +4,10 @@ import ( "errors" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/event/single_test.go b/synchronizer/worker/event/single_test.go index 8d793b4e..4adbbba9 100644 --- a/synchronizer/worker/event/single_test.go +++ b/synchronizer/worker/event/single_test.go @@ -10,14 +10,14 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api" - recorderMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexqueue" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api" + recorderMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexqueue" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impression/redis.go b/synchronizer/worker/impression/redis.go index 78ea1525..38149d14 100644 --- a/synchronizer/worker/impression/redis.go +++ b/synchronizer/worker/impression/redis.go @@ -3,7 +3,7 @@ package impression import ( "errors" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impression/redis_test.go b/synchronizer/worker/impression/redis_test.go index 5bbc71ed..d57cb59a 100644 --- a/synchronizer/worker/impression/redis_test.go +++ b/synchronizer/worker/impression/redis_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impression/single.go b/synchronizer/worker/impression/single.go index a18da5dc..3ecd57b6 100644 --- a/synchronizer/worker/impression/single.go +++ b/synchronizer/worker/impression/single.go @@ -4,10 +4,10 @@ import ( "errors" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impression/single_test.go b/synchronizer/worker/impression/single_test.go index 2ae6cf60..ebd93c91 100644 --- a/synchronizer/worker/impression/single_test.go +++ b/synchronizer/worker/impression/single_test.go @@ -10,14 +10,14 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api" - recorderMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexqueue" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api" + recorderMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexqueue" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impressionscount/redis.go b/synchronizer/worker/impressionscount/redis.go index 44805231..12b8efbc 100644 --- a/synchronizer/worker/impressionscount/redis.go +++ b/synchronizer/worker/impressionscount/redis.go @@ -1,8 +1,8 @@ package impressionscount import ( - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impressionscount/redis_test.go b/synchronizer/worker/impressionscount/redis_test.go index 68b155f2..70770579 100644 --- a/synchronizer/worker/impressionscount/redis_test.go +++ b/synchronizer/worker/impressionscount/redis_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impressionscount/single.go b/synchronizer/worker/impressionscount/single.go index 83203596..868dda07 100644 --- a/synchronizer/worker/impressionscount/single.go +++ b/synchronizer/worker/impressionscount/single.go @@ -3,11 +3,11 @@ package impressionscount import ( "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/impressionscount/single_test.go b/synchronizer/worker/impressionscount/single_test.go index 113aa2b8..6864af5f 100644 --- a/synchronizer/worker/impressionscount/single_test.go +++ b/synchronizer/worker/impressionscount/single_test.go @@ -4,12 +4,12 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/service/mocks" - st "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" - "github.com/splitio/go-split-commons/v7/util" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/service/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" + "github.com/splitio/go-split-commons/v8/util" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/largesegment/largesegment.go b/synchronizer/worker/largesegment/largesegment.go index 30fa395b..c71087c6 100644 --- a/synchronizer/worker/largesegment/largesegment.go +++ b/synchronizer/worker/largesegment/largesegment.go @@ -7,11 +7,11 @@ import ( "sync" "time" - "github.com/splitio/go-split-commons/v7/dtos" - hc "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/utils" + "github.com/splitio/go-split-commons/v8/dtos" + hc "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/utils" "github.com/splitio/go-toolkit/v5/backoff" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" diff --git a/synchronizer/worker/largesegment/largesegment_test.go b/synchronizer/worker/largesegment/largesegment_test.go index a2b2fc2c..68826ae4 100644 --- a/synchronizer/worker/largesegment/largesegment_test.go +++ b/synchronizer/worker/largesegment/largesegment_test.go @@ -9,13 +9,13 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" - fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" - "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" + fetcherMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/synchronizer/worker/segment/segment.go b/synchronizer/worker/segment/segment.go index d313c083..c427d261 100644 --- a/synchronizer/worker/segment/segment.go +++ b/synchronizer/worker/segment/segment.go @@ -6,12 +6,12 @@ import ( "sync" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/utils" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/utils" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/backoff" "github.com/splitio/go-toolkit/v5/common" diff --git a/synchronizer/worker/segment/segment_test.go b/synchronizer/worker/segment/segment_test.go index d361e238..6b2abeb2 100644 --- a/synchronizer/worker/segment/segment_test.go +++ b/synchronizer/worker/segment/segment_test.go @@ -8,16 +8,16 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/healthcheck/application" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" - fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/healthcheck/application" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service" + fetcherMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index b7747da4..e9ba4e11 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -5,15 +5,15 @@ import ( "net/http" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/engine/validator" - "github.com/splitio/go-split-commons/v7/flagsets" - "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/engine/validator" + "github.com/splitio/go-split-commons/v8/flagsets" + "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/backoff" "github.com/splitio/go-toolkit/v5/common" diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 45f37eda..3432f4a1 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -6,17 +6,17 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/service/api/specs" - fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/inmemory" - "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/service/api/specs" + fetcherMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/inmemory" + "github.com/splitio/go-split-commons/v8/storage/inmemory/mutexmap" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" diff --git a/tasks/cleanfiltersync.go b/tasks/cleanfiltersync.go index 6341b581..9fae3cb0 100644 --- a/tasks/cleanfiltersync.go +++ b/tasks/cleanfiltersync.go @@ -1,7 +1,7 @@ package tasks import ( - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/cleanfiltersync_test.go b/tasks/cleanfiltersync_test.go index 58272024..acc5ae82 100644 --- a/tasks/cleanfiltersync_test.go +++ b/tasks/cleanfiltersync_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - st "github.com/splitio/go-split-commons/v7/storage/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/eventsync.go b/tasks/eventsync.go index b93310dc..78e2ad2c 100644 --- a/tasks/eventsync.go +++ b/tasks/eventsync.go @@ -3,7 +3,7 @@ package tasks import ( "fmt" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/event" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/eventsync_test.go b/tasks/eventsync_test.go index babc05c5..0a5c5715 100644 --- a/tasks/eventsync_test.go +++ b/tasks/eventsync_test.go @@ -5,11 +5,11 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - recorderMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/event" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + recorderMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/event" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/impressionscountsync.go b/tasks/impressionscountsync.go index 260d0eb6..ec44715a 100644 --- a/tasks/impressionscountsync.go +++ b/tasks/impressionscountsync.go @@ -1,7 +1,7 @@ package tasks import ( - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impressionscount" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impressionscount" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/impressionscountsync_test.go b/tasks/impressionscountsync_test.go index b46201a4..f674acdc 100644 --- a/tasks/impressionscountsync_test.go +++ b/tasks/impressionscountsync_test.go @@ -4,12 +4,12 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/service/mocks" - st "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impressionscount" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/service/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impressionscount" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/impressionsync.go b/tasks/impressionsync.go index b4c96268..fd292876 100644 --- a/tasks/impressionsync.go +++ b/tasks/impressionsync.go @@ -3,7 +3,7 @@ package tasks import ( "fmt" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impression" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/impressionsync_test.go b/tasks/impressionsync_test.go index 8f9124d7..d4df7a27 100644 --- a/tasks/impressionsync_test.go +++ b/tasks/impressionsync_test.go @@ -5,12 +5,12 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - recorderMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/impression" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + recorderMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/impression" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/largesegmentsync.go b/tasks/largesegmentsync.go index b401308d..aa00dfc1 100644 --- a/tasks/largesegmentsync.go +++ b/tasks/largesegmentsync.go @@ -5,9 +5,9 @@ import ( "fmt" "sync/atomic" - hc "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/storage" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/largesegment" + hc "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/storage" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/largesegment" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/workerpool" diff --git a/tasks/largesegmentsync_test.go b/tasks/largesegmentsync_test.go index 58e2ef76..277ed71c 100644 --- a/tasks/largesegmentsync_test.go +++ b/tasks/largesegmentsync_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - syncMocks "github.com/splitio/go-split-commons/v7/synchronizer/mocks" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + syncMocks "github.com/splitio/go-split-commons/v8/synchronizer/mocks" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" diff --git a/tasks/segmentsync.go b/tasks/segmentsync.go index 8bd70d4b..b659d847 100644 --- a/tasks/segmentsync.go +++ b/tasks/segmentsync.go @@ -5,8 +5,8 @@ import ( "fmt" "sync/atomic" - healthcheck "github.com/splitio/go-split-commons/v7/healthcheck/application" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" + healthcheck "github.com/splitio/go-split-commons/v8/healthcheck/application" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" "github.com/splitio/go-toolkit/v5/workerpool" diff --git a/tasks/segmentsync_test.go b/tasks/segmentsync_test.go index 8c4cf1dc..7c94b243 100644 --- a/tasks/segmentsync_test.go +++ b/tasks/segmentsync_test.go @@ -5,13 +5,13 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service" - fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/segment" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service" + fetcherMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/segment" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/splitsync.go b/tasks/splitsync.go index 9b7bb9c6..e652b9ff 100644 --- a/tasks/splitsync.go +++ b/tasks/splitsync.go @@ -1,7 +1,7 @@ package tasks import ( - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8adc752c..3eb67d0b 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -4,15 +4,15 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/engine/grammar" - "github.com/splitio/go-split-commons/v7/flagsets" - hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" - "github.com/splitio/go-split-commons/v7/service/api/specs" - fetcherMock "github.com/splitio/go-split-commons/v7/service/mocks" - "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/synchronizer/worker/split" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/engine/grammar" + "github.com/splitio/go-split-commons/v8/flagsets" + hcMock "github.com/splitio/go-split-commons/v8/healthcheck/mocks" + "github.com/splitio/go-split-commons/v8/service/api/specs" + fetcherMock "github.com/splitio/go-split-commons/v8/service/mocks" + "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/synchronizer/worker/split" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" diff --git a/tasks/telemetrysync.go b/tasks/telemetrysync.go index b56f7ffa..a4ebcde7 100644 --- a/tasks/telemetrysync.go +++ b/tasks/telemetrysync.go @@ -1,7 +1,7 @@ package tasks import ( - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/telemetrysync_test.go b/tasks/telemetrysync_test.go index 285294d8..9b416109 100644 --- a/tasks/telemetrysync_test.go +++ b/tasks/telemetrysync_test.go @@ -4,10 +4,10 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/mocks" - st "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/uniquekeyssync.go b/tasks/uniquekeyssync.go index 4caad3c4..1de405f7 100644 --- a/tasks/uniquekeyssync.go +++ b/tasks/uniquekeyssync.go @@ -1,8 +1,8 @@ package tasks import ( - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/asynctask" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/tasks/uniquekeyssync_test.go b/tasks/uniquekeyssync_test.go index 6976828a..f9edaa8d 100644 --- a/tasks/uniquekeyssync_test.go +++ b/tasks/uniquekeyssync_test.go @@ -4,11 +4,11 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/provisional/strategy" - "github.com/splitio/go-split-commons/v7/service/mocks" - st "github.com/splitio/go-split-commons/v7/storage/mocks" - "github.com/splitio/go-split-commons/v7/telemetry" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/provisional/strategy" + "github.com/splitio/go-split-commons/v8/service/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" + "github.com/splitio/go-split-commons/v8/telemetry" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/telemetry/constants.go b/telemetry/constants.go index e61da035..90ec045a 100644 --- a/telemetry/constants.go +++ b/telemetry/constants.go @@ -1,6 +1,6 @@ package telemetry -import "github.com/splitio/go-split-commons/v7/conf" +import "github.com/splitio/go-split-commons/v8/conf" const ( // Treatment getTreatment diff --git a/telemetry/helpers.go b/telemetry/helpers.go index 0b88b0bb..c3b7178f 100644 --- a/telemetry/helpers.go +++ b/telemetry/helpers.go @@ -3,8 +3,8 @@ package telemetry import ( "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" ) // GetStreamingEvent get streaming event diff --git a/telemetry/helpers_test.go b/telemetry/helpers_test.go index bc22d771..1c24946d 100644 --- a/telemetry/helpers_test.go +++ b/telemetry/helpers_test.go @@ -3,7 +3,7 @@ package telemetry import ( "testing" - "github.com/splitio/go-split-commons/v7/conf" + "github.com/splitio/go-split-commons/v8/conf" ) func TestGetURLOVerrides(t *testing.T) { diff --git a/telemetry/interface.go b/telemetry/interface.go index d58a2818..ba4c2d44 100644 --- a/telemetry/interface.go +++ b/telemetry/interface.go @@ -1,6 +1,6 @@ package telemetry -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" // TelemetrySynchronizer interface type TelemetrySynchronizer interface { diff --git a/telemetry/localhost.go b/telemetry/localhost.go index 0cfd5c28..7fbb5bcf 100644 --- a/telemetry/localhost.go +++ b/telemetry/localhost.go @@ -1,6 +1,6 @@ package telemetry -import "github.com/splitio/go-split-commons/v7/dtos" +import "github.com/splitio/go-split-commons/v8/dtos" type NoOp struct{} diff --git a/telemetry/memory.go b/telemetry/memory.go index 8e144c71..7052d246 100644 --- a/telemetry/memory.go +++ b/telemetry/memory.go @@ -5,9 +5,9 @@ import ( "strings" "time" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/telemetry/memory_test.go b/telemetry/memory_test.go index 980d02d9..f84c6fb2 100644 --- a/telemetry/memory_test.go +++ b/telemetry/memory_test.go @@ -9,11 +9,11 @@ import ( "testing" "time" - "github.com/splitio/go-split-commons/v7/conf" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/service/api" - "github.com/splitio/go-split-commons/v7/service/mocks" - st "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/conf" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/service/api" + "github.com/splitio/go-split-commons/v8/service/mocks" + st "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/datastructures/set" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/telemetry/redis.go b/telemetry/redis.go index 94abf0f4..1330e092 100644 --- a/telemetry/redis.go +++ b/telemetry/redis.go @@ -1,8 +1,8 @@ package telemetry import ( - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage" "github.com/splitio/go-toolkit/v5/logging" ) diff --git a/telemetry/redis_test.go b/telemetry/redis_test.go index b5490035..a597ef66 100644 --- a/telemetry/redis_test.go +++ b/telemetry/redis_test.go @@ -3,8 +3,8 @@ package telemetry import ( "testing" - "github.com/splitio/go-split-commons/v7/dtos" - "github.com/splitio/go-split-commons/v7/storage/mocks" + "github.com/splitio/go-split-commons/v8/dtos" + "github.com/splitio/go-split-commons/v8/storage/mocks" "github.com/splitio/go-toolkit/v5/logging" ) From 039f2f93168f8c173e9bdcb21ba9a88eb0007db2 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Wed, 15 Oct 2025 16:11:46 -0300 Subject: [PATCH 25/39] updated toolkit --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7ffe3ef2..64c9d0b5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/bits-and-blooms/bloom/v3 v3.3.1 - github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99 + github.com/splitio/go-toolkit/v5 v5.4.1 github.com/stretchr/testify v1.11.1 golang.org/x/sync v0.3.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index b5c1d4eb..74c2db50 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvkt github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99 h1:rQo355F9JbdyTMz2X5MU+FeRvkT6rvD1n+GnXdJr33A= github.com/splitio/go-toolkit/v5 v5.4.1-0.20250930172659-38274b802d99/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= +github.com/splitio/go-toolkit/v5 v5.4.1 h1:srTyvDBJZMUcJ/KiiQDMyjCuELVgTBh2TGRVn0sOXEE= +github.com/splitio/go-toolkit/v5 v5.4.1/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= From acbfdbc7594c5a0d1a372d6a4d37ebf200c56d50 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Wed, 15 Oct 2025 17:22:49 -0300 Subject: [PATCH 26/39] forwarded err in logic --- synchronizer/worker/split/split.go | 25 ++++++---- synchronizer/worker/split/split_test.go | 63 ++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index b7747da4..ad66e630 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -1,6 +1,7 @@ package split import ( + "errors" "fmt" "net/http" "time" @@ -245,6 +246,7 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { } s.runtimeTelemetry.RecordSyncError(telemetry.SplitSync, httpError.Code) } + return nil, err } currentSince = splitChanges.FFTill() currentRBSince = splitChanges.RBTill() @@ -281,17 +283,22 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { s.lastSyncNewSpec = -1 s.specVersion = specs.FLAG_V1_3 untilTillSince, err := s.synchronizeSplits(nil) - if err == nil { - return &UpdateResult{ - UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), - ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), - NewChangeNumber: untilTillSince.NewChangeNumber, - NewRBChangeNumber: untilTillSince.NewRBChangeNumber, - ReferencedLargeSegments: common.DedupeStringSlice(append(syncResult.ReferencedLargeSegments, untilTillSince.ReferencedLargeSegments...)), - }, nil + if err != nil { + return untilTillSince, err } + return &UpdateResult{ + UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), + ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), + NewChangeNumber: untilTillSince.NewChangeNumber, + NewRBChangeNumber: untilTillSince.NewRBChangeNumber, + ReferencedLargeSegments: common.DedupeStringSlice(append(syncResult.ReferencedLargeSegments, untilTillSince.ReferencedLargeSegments...)), + }, nil + } else { + if !errors.Is(err, ErrProxy) { + return syncResult, err + } + s.specVersion = specs.FLAG_V1_1 } - s.specVersion = specs.FLAG_V1_1 } return s.synchronizeSplits(nil) diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 45f37eda..b1bca597 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -902,19 +902,16 @@ func TestProcessMatchers(t *testing.T) { } func TestSplitProxyDowngrade(t *testing.T) { - t.Run("Error both 1.3 and 1.1", func(t *testing.T) { + t.Run("Error 1.3", func(t *testing.T) { splitMockStorage := &mocks.SplitStorageMock{} - splitMockStorage.On("ChangeNumber").Return(int64(-1), nil).Times(2) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(-1)).Times(2) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusBadRequest}).Once() - splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_1)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusBadRequest}).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(nil, &dtos.HTTPError{Code: http.StatusNotFound}).Once() telemetryMockStorage := mocks.MockTelemetryStorage{ RecordSyncErrorCall: func(resource, status int) { assert.Equal(t, telemetry.SplitSync, resource) - assert.Equal(t, http.StatusBadRequest, status) + assert.Equal(t, http.StatusNotFound, status) }, } appMonitorMock := &hcMock.ApplicationMonitorMock{} @@ -979,6 +976,60 @@ func TestSplitProxyDowngrade(t *testing.T) { appMonitorMock.AssertExpectations(t) }) + t.Run("1.3 OK, then Err", func(t *testing.T) { + mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} + mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{mockedSplit1}, + Since: -1, + Till: 3, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + Since: -1, + Till: 3, + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, + }, + }, + } + + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(3), nil).Times(2) + splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once() + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) + ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once() + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() + splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(3).WithChangeNumberRB(3)).Return(nil, errors.New("some error")).Once() + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSuccessfulSyncCall: func(resource int, tm time.Time) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + RecordSyncLatencyCall: func(resource int, tm time.Duration) { + assert.Equal(t, telemetry.SplitSync, resource) + }, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return() + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, true, specs.FLAG_V1_3) + + result, err := splitUpdater.SynchronizeSplits(nil) + assert.NotNil(t, err) + assert.Len(t, result.ReferencedSegments, 0) + assert.Len(t, result.ReferencedLargeSegments, 0) + assert.ElementsMatch(t, []string{}, result.UpdatedSplits) + assert.Equal(t, int64(-1), splitUpdater.lastSyncNewSpec) + assert.Equal(t, specs.FLAG_V1_3, splitUpdater.specVersion) + splitMockStorage.AssertExpectations(t) + splitMockFetcher.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) + t.Run("1.3 OK", func(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} mockedRuleBased1 := dtos.RuleBasedSegmentDTO{Name: "rb1", Status: "ACTIVE"} From 01d556553cb9910528f7a1018aec739bf291dcb9 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 16 Oct 2025 09:29:06 -0300 Subject: [PATCH 27/39] Remove logs when 404 and removed extra param for isProxy --- service/api/client.go | 2 +- service/api/http_fetchers.go | 4 ++-- service/api/http_fetchers_test.go | 6 +++--- service/interfaces.go | 2 +- service/local/splitFetcher.go | 2 +- service/mocks/split.go | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/service/api/client.go b/service/api/client.go index 53e67cfd..6293ea68 100644 --- a/service/api/client.go +++ b/service/api/client.go @@ -87,7 +87,7 @@ func (c *HTTPClient) Get(endpoint string, fetchOptions service.RequestParams) ([ message := fmt.Sprintf("GET method: [%s] Status Code: %d - %s", req.URL.String(), resp.StatusCode, resp.Status) if resp.StatusCode == http.StatusNotModified { c.logger.Debug(message) - } else { + } else if resp.StatusCode != http.StatusNotFound { c.logger.Error(message) } diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 9bb6bd14..8f31276e 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -47,8 +47,8 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. } } -func (f *HTTPSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { - _, err := f.fetchRaw("/version", fetchOptions) +func (f *HTTPSplitFetcher) IsProxy() bool { + _, err := f.fetchRaw("/version", nil) if err == nil { return false } diff --git a/service/api/http_fetchers_test.go b/service/api/http_fetchers_test.go index c6df7625..a4c850d5 100644 --- a/service/api/http_fetchers_test.go +++ b/service/api/http_fetchers_test.go @@ -606,7 +606,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy := splitFetcher1.IsProxy(service.MakeFlagRequestParams()) + isProxy := splitFetcher1.IsProxy() assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns 200") // Test case 2: Is a proxy (version endpoint returns 404) @@ -626,7 +626,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy = splitFetcher2.IsProxy(service.MakeFlagRequestParams()) + isProxy = splitFetcher2.IsProxy() assert.True(t, isProxy, "Should be identified as proxy when version endpoint returns 404") // Test case 3: Not a proxy (version endpoint returns other error code) @@ -646,7 +646,7 @@ func TestIsProxy(t *testing.T) { dtos.Metadata{}, ).(*HTTPSplitFetcher) // Type assertion to access unexported method - isProxy = splitFetcher3.IsProxy(service.MakeFlagRequestParams()) + isProxy = splitFetcher3.IsProxy() assert.False(t, isProxy, "Should not be identified as proxy when version endpoint returns non-404 error") } diff --git a/service/interfaces.go b/service/interfaces.go index 8f157b24..0153cd3e 100644 --- a/service/interfaces.go +++ b/service/interfaces.go @@ -10,7 +10,7 @@ type AuthClient interface { // SplitFetcher interface to be implemented by Split Fetchers type SplitFetcher interface { Fetch(fetchOptions *FlagRequestParams) (dtos.FFResponse, error) - IsProxy(fetchOptions *FlagRequestParams) bool + IsProxy() bool } // SegmentFetcher interface to be implemented by Split Fetchers diff --git a/service/local/splitFetcher.go b/service/local/splitFetcher.go index 3677b5d7..a75fb7c1 100644 --- a/service/local/splitFetcher.go +++ b/service/local/splitFetcher.go @@ -325,7 +325,7 @@ func (s *FileSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. }, nil } -func (s *FileSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { +func (s *FileSplitFetcher) IsProxy() bool { return false } diff --git a/service/mocks/split.go b/service/mocks/split.go index 05574149..77d43c5c 100644 --- a/service/mocks/split.go +++ b/service/mocks/split.go @@ -22,8 +22,8 @@ func (m *MockSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. } // Fetch mock -func (m *MockSplitFetcher) IsProxy(fetchOptions *service.FlagRequestParams) bool { - args := m.Called(fetchOptions) +func (m *MockSplitFetcher) IsProxy() bool { + args := m.Called() return args.Get(0).(bool) } From 7976fa1a0e9dc667fc8d36c39a381c64b0dd4851 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Thu, 16 Oct 2025 14:23:36 -0300 Subject: [PATCH 28/39] resolving spec version from fetchOptions --- service/api/http_fetchers.go | 5 +---- service/commons.go | 5 +++++ service/commons_test.go | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/service/api/http_fetchers.go b/service/api/http_fetchers.go index 8f31276e..b6ad344a 100644 --- a/service/api/http_fetchers.go +++ b/service/api/http_fetchers.go @@ -11,7 +11,6 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/service" "github.com/splitio/go-split-commons/v7/service/api/specs" - "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) @@ -32,7 +31,6 @@ func (h *httpFetcherBase) fetchRaw(endpoint string, fetchOptions service.Request type HTTPSplitFetcher struct { httpFetcherBase flagSetsFilter string - specVersion *string } // NewHTTPSplitFetcher instantiates and return an HTTPSplitFetcher @@ -43,7 +41,6 @@ func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging. logger: logger, }, flagSetsFilter: strings.Join(cfg.FlagSetsFilter, ","), - specVersion: specs.Match(cfg.FlagsSpecVersion), } } @@ -67,7 +64,7 @@ func (f *HTTPSplitFetcher) Fetch(fetchOptions *service.FlagRequestParams) (dtos. var splitChangesDto dtos.FFResponse - if common.StringFromRef(f.specVersion) == specs.FLAG_V1_3 { + if fetchOptions.SpecVersion() == specs.FLAG_V1_3 { splitChangesDto, err = dtos.NewFFResponseV13(data) } else { splitChangesDto, err = dtos.NewFFResponseLegacy(data) diff --git a/service/commons.go b/service/commons.go index bdd56681..238dac8f 100644 --- a/service/commons.go +++ b/service/commons.go @@ -104,6 +104,11 @@ func (s *FlagRequestParams) Till() *int64 { return s.till } +// SpecVersion returns the spec version +func (s *FlagRequestParams) SpecVersion() string { + return common.StringFromRef(s.specVersion) +} + // Apply applies the request parameters func (s *FlagRequestParams) Apply(request *http.Request) error { if s.cacheControlHeaders { diff --git a/service/commons_test.go b/service/commons_test.go index 7ea533f7..4bfe7c20 100644 --- a/service/commons_test.go +++ b/service/commons_test.go @@ -24,6 +24,10 @@ func TestSplitFetchOptions(t *testing.T) { assert.Equal(t, "123", req.URL.Query().Get(till)) assert.Equal(t, "123456", req.URL.Query().Get(rbSince)) assert.Equal(t, "test?s=1.1&since=123456&rbSince=123456&sets=filter&till=123", req.URL.String()) + assert.Equal(t, "1.1", fetchOptions.SpecVersion()) + + fetchOptions = MakeFlagRequestParams() + assert.Equal(t, "", fetchOptions.SpecVersion()) } func TestSegmentRequestParams(t *testing.T) { From de7c602b30a74ade1909f6b08312610d8986e1dd Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 16 Oct 2025 15:34:27 -0300 Subject: [PATCH 29/39] Updated client --- service/api/client.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/service/api/client.go b/service/api/client.go index 6293ea68..f2b36e32 100644 --- a/service/api/client.go +++ b/service/api/client.go @@ -85,10 +85,12 @@ func (c *HTTPClient) Get(endpoint string, fetchOptions service.RequestParams) ([ } if resp.StatusCode < 200 || resp.StatusCode >= 300 { message := fmt.Sprintf("GET method: [%s] Status Code: %d - %s", req.URL.String(), resp.StatusCode, resp.Status) - if resp.StatusCode == http.StatusNotModified { - c.logger.Debug(message) - } else if resp.StatusCode != http.StatusNotFound { - c.logger.Error(message) + if endpoint != "/version" { + if resp.StatusCode == http.StatusNotModified { + c.logger.Debug(message) + } else { + c.logger.Error(message) + } } return nil, &dtos.HTTPError{ From e5554be1aea2249c860c887cdae948b2e250638b Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Thu, 16 Oct 2025 15:40:52 -0300 Subject: [PATCH 30/39] added coverage --- dtos/splitchangewrapper.go | 60 ++++++++++--- dtos/splitchangewrapper_test.go | 150 ++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+), 11 deletions(-) create mode 100644 dtos/splitchangewrapper_test.go diff --git a/dtos/splitchangewrapper.go b/dtos/splitchangewrapper.go index f5508da7..32a53085 100644 --- a/dtos/splitchangewrapper.go +++ b/dtos/splitchangewrapper.go @@ -4,6 +4,7 @@ import ( "encoding/json" ) +// FFResponse is an interface that abstracts the differences between different versions of feature flag responses. type FFResponse interface { NeedsAnotherFetch() bool RuleBasedSegments() []RuleBasedSegmentDTO @@ -14,10 +15,12 @@ type FFResponse interface { RBSince() int64 } +// FFResponseLegacy handles the legacy format of feature flag responses. type FFResponseLegacy struct { SplitChanges SplitsDTO } +// NewFFResponseLegacy creates a new FFResponseLegacy instance from the provided JSON data. func NewFFResponseLegacy(data []byte) (FFResponse, error) { var splitChangesDto SplitsDTO err := json.Unmarshal(data, &splitChangesDto) @@ -29,38 +32,47 @@ func NewFFResponseLegacy(data []byte) (FFResponse, error) { return nil, err } -func (f12 *FFResponseLegacy) NeedsAnotherFetch() bool { - return f12.SplitChanges.Since == f12.SplitChanges.Till +// NeedsAnotherFetch checks if another fetch is needed based on the since and till values. +func (ffLegacy *FFResponseLegacy) NeedsAnotherFetch() bool { + return ffLegacy.SplitChanges.Since == ffLegacy.SplitChanges.Till } -func (f12 *FFResponseLegacy) FeatureFlags() []SplitDTO { - return f12.SplitChanges.Splits +// FeatureFlags returns the list of feature flags (splits) from the response. +func (ffLegacy *FFResponseLegacy) FeatureFlags() []SplitDTO { + return ffLegacy.SplitChanges.Splits } -func (wf12 *FFResponseLegacy) RuleBasedSegments() []RuleBasedSegmentDTO { +// RuleBasedSegments returns an empty list as legacy responses do not contain rule-based segments. +func (ffLegacy *FFResponseLegacy) RuleBasedSegments() []RuleBasedSegmentDTO { return []RuleBasedSegmentDTO{} } -func (f12 *FFResponseLegacy) FFTill() int64 { - return f12.SplitChanges.Till +// FFTill returns the till value for feature flags. +func (ffLegacy *FFResponseLegacy) FFTill() int64 { + return ffLegacy.SplitChanges.Till } -func (f12 *FFResponseLegacy) RBTill() int64 { +// RBTill returns 0 as legacy responses do not contain rule-based segments. +func (ffLegacy *FFResponseLegacy) RBTill() int64 { return 0 } -func (f12 *FFResponseLegacy) FFSince() int64 { - return f12.SplitChanges.Since +// FFSince returns the since value for feature flags. +func (ffLegacy *FFResponseLegacy) FFSince() int64 { + return ffLegacy.SplitChanges.Since } -func (f12 *FFResponseLegacy) RBSince() int64 { +// RBSince returns 0 as legacy responses do not contain rule-based segments. +func (ffLegacy *FFResponseLegacy) RBSince() int64 { return 0 } +// FFResponseV13 handles the version 1.3 format of feature flag responses. type FFResponseV13 struct { SplitChanges SplitChangesDTO } +// NewFFResponseV13 creates a new FFResponseV13 instance from the provided JSON data. func NewFFResponseV13(data []byte) (FFResponse, error) { var splitChangesDto SplitChangesDTO err := json.Unmarshal(data, &splitChangesDto) @@ -72,38 +84,47 @@ func NewFFResponseV13(data []byte) (FFResponse, error) { return nil, err } +// FeatureFlags returns the list of feature flags (splits) from the response. func (f13 *FFResponseV13) FeatureFlags() []SplitDTO { return f13.SplitChanges.FeatureFlags.Splits } +// RuleBasedSegments returns the list of rule-based segments from the response. func (f13 *FFResponseV13) RuleBasedSegments() []RuleBasedSegmentDTO { return f13.SplitChanges.RuleBasedSegments.RuleBasedSegments } +// NeedsAnotherFetch checks if another fetch is needed based on the since and till values for both feature flags and rule-based segments. func (f13 FFResponseV13) NeedsAnotherFetch() bool { return f13.SplitChanges.FeatureFlags.Since == f13.SplitChanges.FeatureFlags.Till && f13.SplitChanges.RuleBasedSegments.Since == f13.SplitChanges.RuleBasedSegments.Till } +// FFTill returns the till value for feature flags. func (f13 *FFResponseV13) FFTill() int64 { return f13.SplitChanges.FeatureFlags.Till } +// RBTill returns the till value for rule-based segments. func (f13 *FFResponseV13) RBTill() int64 { return f13.SplitChanges.RuleBasedSegments.Till } +// RBSince returns the since value for rule-based segments. func (f13 *FFResponseV13) RBSince() int64 { return f13.SplitChanges.RuleBasedSegments.Since } +// FFSince returns the since value for feature flags. func (f13 *FFResponseV13) FFSince() int64 { return f13.SplitChanges.FeatureFlags.Since } +// FFResponseLocalV13 is a local version of FFResponseV13 for internal use. type FFResponseLocalV13 struct { SplitChanges SplitChangesDTO } +// NewFFResponseLocalV13 creates a new FFResponseLocalV13 instance from the provided JSON data. func NewFFResponseLocalV13(data []byte) (*FFResponseLocalV13, error) { var splitChangesDto SplitChangesDTO err := json.Unmarshal(data, &splitChangesDto) @@ -115,54 +136,71 @@ func NewFFResponseLocalV13(data []byte) (*FFResponseLocalV13, error) { return nil, err } +// FeatureFlags returns the list of feature flags (splits) from the response. func (f *FFResponseLocalV13) FeatureFlags() []SplitDTO { return f.SplitChanges.FeatureFlags.Splits } +// RuleBasedSegments returns the list of rule-based segments from the response. func (f *FFResponseLocalV13) RuleBasedSegments() []RuleBasedSegmentDTO { return f.SplitChanges.RuleBasedSegments.RuleBasedSegments } +// NeedsAnotherFetch checks if another fetch is needed based on the since and till values for both feature flags and rule-based segments. func (f FFResponseLocalV13) NeedsAnotherFetch() bool { return f.SplitChanges.FeatureFlags.Since == f.SplitChanges.FeatureFlags.Till && f.SplitChanges.RuleBasedSegments.Since == f.SplitChanges.RuleBasedSegments.Till } +// FFTill returns the till value for feature flags. func (f *FFResponseLocalV13) FFTill() int64 { return f.SplitChanges.FeatureFlags.Till } +// RBTill returns the till value for rule-based segments. func (f *FFResponseLocalV13) RBTill() int64 { return f.SplitChanges.RuleBasedSegments.Till } +// RBSince returns the since value for rule-based segments. func (f *FFResponseLocalV13) RBSince() int64 { return f.SplitChanges.RuleBasedSegments.Since } +// FFSince returns the since value for feature flags. func (f *FFResponseLocalV13) SetFFTill(till int64) { f.SplitChanges.FeatureFlags.Till = till } +// SetFFSince sets the since value for feature flags. func (f *FFResponseLocalV13) SetFFSince(since int64) { f.SplitChanges.FeatureFlags.Since = since } +// SetRBTill sets the till value for rule-based segments. func (f *FFResponseLocalV13) SetRBTill(till int64) { f.SplitChanges.RuleBasedSegments.Till = till } +// FFSince returns the since value for feature flags. func (f *FFResponseLocalV13) FFSince() int64 { return f.SplitChanges.FeatureFlags.Since } +// SetRBSince sets the since value for rule-based segments. func (f *FFResponseLocalV13) SetRBSince(since int64) { f.SplitChanges.RuleBasedSegments.Since = since } +// ReplaceFF replaces the feature flags (splits) in the response with the provided list. func (f *FFResponseLocalV13) ReplaceFF(featureFlags []SplitDTO) { f.SplitChanges.FeatureFlags.Splits = featureFlags } +// ReplaceRB replaces the rule-based segments in the response with the provided list. func (f *FFResponseLocalV13) ReplaceRB(ruleBasedSegments []RuleBasedSegmentDTO) { f.SplitChanges.RuleBasedSegments.RuleBasedSegments = ruleBasedSegments } + +var _ FFResponse = (*FFResponseLegacy)(nil) +var _ FFResponse = (*FFResponseV13)(nil) +var _ FFResponse = (*FFResponseLocalV13)(nil) diff --git a/dtos/splitchangewrapper_test.go b/dtos/splitchangewrapper_test.go new file mode 100644 index 00000000..d2fe3382 --- /dev/null +++ b/dtos/splitchangewrapper_test.go @@ -0,0 +1,150 @@ +package dtos + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFFResponseLegacy(t *testing.T) { + some, err := NewFFResponseLegacy([]byte(`{wrong json}`)) + assert.Nil(t, some) + assert.NotNil(t, err) + + ok, err := NewFFResponseLegacy([]byte(`{"since":1,"till":2,"splits":[{"name":"split1"},{"name":"split2"}]}`)) + assert.NotNil(t, ok) + assert.Nil(t, err) + assert.Equal(t, int64(2), ok.FFTill()) + assert.Equal(t, int64(0), ok.RBTill()) + assert.Equal(t, int64(1), ok.FFSince()) + assert.Equal(t, int64(0), ok.RBSince()) + assert.False(t, ok.NeedsAnotherFetch()) + assert.Len(t, ok.FeatureFlags(), 2) + assert.Empty(t, ok.RuleBasedSegments()) + + noFetch, err := NewFFResponseLegacy([]byte(`{"since":2,"till":2,"splits":[]}`)) + assert.NotNil(t, noFetch) + assert.Nil(t, err) + assert.Equal(t, int64(2), noFetch.FFTill()) + assert.Equal(t, int64(0), noFetch.RBTill()) + assert.Equal(t, int64(2), noFetch.FFSince()) + assert.Equal(t, int64(0), noFetch.RBSince()) + assert.True(t, noFetch.NeedsAnotherFetch()) + assert.Len(t, noFetch.FeatureFlags(), 0) + assert.Empty(t, noFetch.RuleBasedSegments()) +} + +func TestFFResponseLatest(t *testing.T) { + some, err := NewFFResponseV13([]byte(`{wrong json}`)) + assert.Nil(t, some) + assert.NotNil(t, err) + + ok, err := NewFFResponseV13([]byte(`{ + "ff":{ + "s":1, + "t":2, + "d":[{"name":"split1"},{"name":"split2"}] + }, + "rbs":{ + "s":3, + "t":4, + "d":[{"name":"rb1"},{"name":"rb2"},{"name":"rb3"}] + } + }`)) + assert.NotNil(t, ok) + assert.Nil(t, err) + assert.Equal(t, int64(2), ok.FFTill()) + assert.Equal(t, int64(4), ok.RBTill()) + assert.Equal(t, int64(1), ok.FFSince()) + assert.Equal(t, int64(3), ok.RBSince()) + assert.Len(t, ok.FeatureFlags(), 2) + assert.Len(t, ok.RuleBasedSegments(), 3) + assert.False(t, ok.NeedsAnotherFetch()) + + noFetch, err := NewFFResponseV13([]byte(`{ + "ff":{ + "s":2, + "t":2, + "d":[] + }, + "rbs":{ + "s":4, + "t":4, + "d":[] + } + }`)) + assert.NotNil(t, noFetch) + assert.Nil(t, err) + assert.Equal(t, int64(2), noFetch.FFTill()) + assert.Equal(t, int64(4), noFetch.RBTill()) + assert.Equal(t, int64(2), noFetch.FFSince()) + assert.Equal(t, int64(4), noFetch.RBSince()) + assert.Len(t, noFetch.FeatureFlags(), 0) + assert.Len(t, noFetch.RuleBasedSegments(), 0) + assert.True(t, noFetch.NeedsAnotherFetch()) +} + +func TestFFResponseLocalV13(t *testing.T) { + some, err := NewFFResponseLocalV13([]byte(`{wrong json}`)) + assert.Nil(t, some) + assert.NotNil(t, err) + + ok, err := NewFFResponseLocalV13([]byte(`{ + "ff":{ + "s":1, + "t":2, + "d":[{"name":"split1"},{"name":"split2"}] + }, + "rbs":{ + "s":3, + "t":4, + "d":[{"name":"rb1"},{"name":"rb2"},{"name":"rb3"}] + } + }`)) + assert.NotNil(t, ok) + assert.Nil(t, err) + assert.Equal(t, int64(2), ok.FFTill()) + assert.Equal(t, int64(4), ok.RBTill()) + assert.Equal(t, int64(1), ok.FFSince()) + assert.Equal(t, int64(3), ok.RBSince()) + assert.Len(t, ok.FeatureFlags(), 2) + assert.Len(t, ok.RuleBasedSegments(), 3) + assert.False(t, ok.NeedsAnotherFetch()) + + ok.SetFFTill(5) + ok.SetFFSince(5) + ok.SetRBSince(5) + ok.SetRBTill(5) + assert.Equal(t, int64(5), ok.FFTill()) + assert.Equal(t, int64(5), ok.RBTill()) + assert.Equal(t, int64(5), ok.FFSince()) + assert.Equal(t, int64(5), ok.RBSince()) + ok.ReplaceFF([]SplitDTO{{Name: "other"}}) + ok.ReplaceRB([]RuleBasedSegmentDTO{{Name: "other_rb"}}) + assert.Len(t, ok.FeatureFlags(), 1) + assert.Len(t, ok.RuleBasedSegments(), 1) + assert.Equal(t, "other", ok.FeatureFlags()[0].Name) + assert.Equal(t, "other_rb", ok.RuleBasedSegments()[0].Name) + + noFetch, err := NewFFResponseLocalV13([]byte(`{ + "ff":{ + "s":2, + "t":2, + "d":[] + }, + "rbs":{ + "s":4, + "t":4, + "d":[] + } + }`)) + assert.NotNil(t, noFetch) + assert.Nil(t, err) + assert.Equal(t, int64(2), noFetch.FFTill()) + assert.Equal(t, int64(4), noFetch.RBTill()) + assert.Equal(t, int64(2), noFetch.FFSince()) + assert.Equal(t, int64(4), noFetch.RBSince()) + assert.Len(t, noFetch.FeatureFlags(), 0) + assert.Len(t, noFetch.RuleBasedSegments(), 0) + assert.True(t, noFetch.NeedsAnotherFetch()) +} From 330171cbc45bfac92d50fabd1da11354c823f286 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 20 Oct 2025 11:52:03 -0300 Subject: [PATCH 31/39] Updated sotrages and logic when processFFChange --- engine/evaluator/evaluator_test.go | 13 +- storage/inmemory/mutexmap/rulebasedsegment.go | 28 ++- .../mutexmap/rulebasedsegment_test.go | 31 +-- storage/inmemory/mutexmap/splits.go | 20 +- storage/interfaces.go | 21 +- storage/mocks/rulebasedsegment.go | 19 +- storage/mocks/split.go | 56 +++-- storage/redis/splits.go | 22 +- synchronizer/synchronizer_test.go | 4 +- synchronizer/worker/segment/segment.go | 2 +- synchronizer/worker/segment/segment_test.go | 10 +- synchronizer/worker/split/split.go | 195 ++++++++++++------ synchronizer/worker/split/split_test.go | 21 +- 13 files changed, 306 insertions(+), 136 deletions(-) diff --git a/engine/evaluator/evaluator_test.go b/engine/evaluator/evaluator_test.go index 679a2207..c542a1ae 100644 --- a/engine/evaluator/evaluator_test.go +++ b/engine/evaluator/evaluator_test.go @@ -285,12 +285,13 @@ func (s *mockStorage) FetchMany( splits["mysplittest5"] = nil return splits } -func (s *mockStorage) All() []dtos.SplitDTO { return make([]dtos.SplitDTO, 0) } -func (s *mockStorage) SegmentNames() *set.ThreadUnsafeSet { return nil } -func (s *mockStorage) LargeSegmentNames() *set.ThreadUnsafeSet { return nil } -func (s *mockStorage) SplitNames() []string { return make([]string, 0) } -func (s *mockStorage) TrafficTypeExists(trafficType string) bool { return true } -func (s *mockStorage) ChangeNumber() (int64, error) { return 0, nil } +func (s *mockStorage) All() []dtos.SplitDTO { return make([]dtos.SplitDTO, 0) } +func (s *mockStorage) SegmentNames() *set.ThreadUnsafeSet { return nil } +func (s *mockStorage) LargeSegmentNames() *set.ThreadUnsafeSet { return nil } +func (s *mockStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { return nil } +func (s *mockStorage) SplitNames() []string { return make([]string, 0) } +func (s *mockStorage) TrafficTypeExists(trafficType string) bool { return true } +func (s *mockStorage) ChangeNumber() (int64, error) { return 0, nil } func (s *mockStorage) GetNamesByFlagSets(sets []string) map[string][]string { return make(map[string][]string) } diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index d247ab7a..13162ec5 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -57,10 +57,10 @@ func (r *RuleBasedSegmentsStorageImpl) SetChangeNumber(till int64) error { } // ChangeNumber return the actual rule-based till -func (r *RuleBasedSegmentsStorageImpl) ChangeNumber() int64 { +func (r *RuleBasedSegmentsStorageImpl) ChangeNumber() (int64, error) { r.tillMutex.RLock() defer r.tillMutex.RUnlock() - return r.till + return r.till, nil } // All returns a list with a copy of each rule-based. @@ -87,7 +87,7 @@ func (r *RuleBasedSegmentsStorageImpl) RuleBasedSegmentNames() []string { } // SegmentNames returns a slice with the names of all segments referenced in rule-based -func (r *RuleBasedSegmentsStorageImpl) GetSegments() *set.ThreadUnsafeSet { +func (r *RuleBasedSegmentsStorageImpl) Segments() *set.ThreadUnsafeSet { segments := set.NewSet() r.mutex.RLock() @@ -109,6 +109,28 @@ func (r *RuleBasedSegmentsStorageImpl) GetSegments() *set.ThreadUnsafeSet { return segments } +func (r *RuleBasedSegmentsStorageImpl) LargeSegments() *set.ThreadUnsafeSet { + largeSegments := set.NewSet() + + r.mutex.RLock() + defer r.mutex.RUnlock() + for _, ruleBased := range r.data { + for _, condition := range ruleBased.Conditions { + for _, matcher := range condition.MatcherGroup.Matchers { + if matcher.UserDefinedLargeSegment != nil { + largeSegments.Add(matcher.UserDefinedSegment.SegmentName) + } + } + } + for _, excluded := range ruleBased.Excluded.Segments { + if excluded.Type == dtos.TypeStandard { + largeSegments.Add(excluded.Name) + } + } + } + return largeSegments +} + // Contains returns true or false if all the rule-based segment names are present func (r *RuleBasedSegmentsStorageImpl) Contains(ruleBasedSegmentNames []string) bool { if len(ruleBasedSegmentNames) == 0 { diff --git a/storage/inmemory/mutexmap/rulebasedsegment_test.go b/storage/inmemory/mutexmap/rulebasedsegment_test.go index 9e7a7a7d..cd5d0811 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment_test.go +++ b/storage/inmemory/mutexmap/rulebasedsegment_test.go @@ -13,7 +13,8 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { storage := NewRuleBasedSegmentsStorage() // Test initial state - assert.Equal(t, int64(-1), storage.ChangeNumber()) + changeNumber, _ := storage.ChangeNumber() + assert.Equal(t, int64(-1), changeNumber) assert.Empty(t, storage.All()) assert.Empty(t, storage.RuleBasedSegmentNames()) @@ -62,7 +63,8 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { // Test Update storage.Update([]dtos.RuleBasedSegmentDTO{ruleBased1, ruleBased2}, nil, 123) - assert.Equal(t, int64(123), storage.ChangeNumber()) + changeNumber, _ = storage.ChangeNumber() + assert.Equal(t, int64(123), changeNumber) assert.Len(t, storage.All(), 2) // Test RuleBasedSegmentNames @@ -71,7 +73,7 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { assert.Contains(t, names, "rule2") // Test GetSegments - segments := storage.GetSegments() + segments := storage.Segments() // Print segments for debugging t.Logf("Segments in set: %v", segments.List()) assert.True(t, segments.Has("segment1"), "segment1 should be in segments") @@ -85,7 +87,8 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { // Test Remove storage.Update(nil, []dtos.RuleBasedSegmentDTO{ruleBased1}, 124) - assert.Equal(t, int64(124), storage.ChangeNumber()) + changeNumber, _ = storage.ChangeNumber() + assert.Equal(t, int64(124), changeNumber) assert.Len(t, storage.All(), 1) assert.Contains(t, storage.RuleBasedSegmentNames(), "rule2") @@ -142,7 +145,8 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { storage.ReplaceAll([]dtos.RuleBasedSegmentDTO{newRuleBased}, 200) // Verify change number was updated - assert.Equal(t, int64(200), storage.ChangeNumber()) + changeNumber, _ := storage.ChangeNumber() + assert.Equal(t, int64(200), changeNumber) // Verify old data was removed oldSegment, err := storage.GetRuleBasedSegmentByName("initial") @@ -156,7 +160,7 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { assert.Equal(t, "new", newSegment.Name) // Verify segments set - segments := storage.GetSegments() + segments := storage.Segments() assert.True(t, segments.Has("segment2")) assert.False(t, segments.Has("segment1")) @@ -165,7 +169,8 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { // Verify storage is empty assert.Empty(t, storage.All()) - assert.Equal(t, int64(300), storage.ChangeNumber()) + changeNumber, _ = storage.ChangeNumber() + assert.Equal(t, int64(300), changeNumber) // Test ReplaceAll with multiple segments ruleBased1 := dtos.RuleBasedSegmentDTO{ @@ -206,11 +211,12 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { // Verify multiple segments were added assert.Len(t, storage.All(), 2) - assert.Equal(t, int64(400), storage.ChangeNumber()) + changeNumber, _ = storage.ChangeNumber() + assert.Equal(t, int64(400), changeNumber) assert.True(t, storage.Contains([]string{"rule1", "rule2"})) // Verify segments set contains both segments - segments = storage.GetSegments() + segments = storage.Segments() assert.True(t, segments.Has("segment3")) assert.True(t, segments.Has("segment4")) } @@ -221,7 +227,8 @@ func TestRuleBasedSegmentsStorageEdgeCases(t *testing.T) { // Test SetChangeNumber explicitly err := storage.SetChangeNumber(100) assert.NoError(t, err) - assert.Equal(t, int64(100), storage.ChangeNumber()) + changeNumber, _ := storage.ChangeNumber() + assert.Equal(t, int64(100), changeNumber) // Test GetSegments with different segment types ruleBased := dtos.RuleBasedSegmentDTO{ @@ -241,7 +248,7 @@ func TestRuleBasedSegmentsStorageEdgeCases(t *testing.T) { } storage.Update([]dtos.RuleBasedSegmentDTO{ruleBased}, nil, 101) - segments := storage.GetSegments() + segments := storage.Segments() assert.True(t, segments.Has("excluded1")) assert.False(t, segments.Has("excluded2")) // Should not include non-standard segments @@ -288,7 +295,7 @@ func TestRuleBasedSegmentsStorageConcurrent(t *testing.T) { defer wg.Done() _ = storage.All() _ = storage.RuleBasedSegmentNames() - _ = storage.GetSegments() + _ = storage.Segments() _ = storage.Contains([]string{"segment1"}) }() } diff --git a/storage/inmemory/mutexmap/splits.go b/storage/inmemory/mutexmap/splits.go index 5de3f907..37172a8c 100644 --- a/storage/inmemory/mutexmap/splits.go +++ b/storage/inmemory/mutexmap/splits.go @@ -224,6 +224,23 @@ func (m *MMSplitStorage) LargeSegmentNames() *set.ThreadUnsafeSet { return largeSegments } +func (m *MMSplitStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { + ruleBasedSegments := set.NewSet() + m.mutex.RLock() + defer m.mutex.RUnlock() + for _, split := range m.data { + for _, condition := range split.Conditions { + for _, matcher := range condition.MatcherGroup.Matchers { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == "IN_RULE_BASED_SEGMENT" { + ruleBasedSegments.Add(matcher.UserDefinedSegment.SegmentName) + } + + } + } + } + return ruleBasedSegments +} + // SetChangeNumber sets the till value belong to split func (m *MMSplitStorage) SetChangeNumber(till int64) error { m.tillMutex.Lock() @@ -270,7 +287,7 @@ func (m *MMSplitStorage) GetNamesByFlagSets(sets []string) map[string][]string { return toReturn } -func (m *MMSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { +func (m *MMSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error { // Get all current splits under read lock m.mutex.RLock() toRemove := make([]dtos.SplitDTO, 0) @@ -283,6 +300,7 @@ func (m *MMSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { m.mutex.Lock() defer m.mutex.Unlock() m.update(toAdd, toRemove, changeNumber) + return nil } var _ storage.SplitStorageConsumer = (*MMSplitStorage)(nil) diff --git a/storage/interfaces.go b/storage/interfaces.go index fd9d87f4..2382144c 100644 --- a/storage/interfaces.go +++ b/storage/interfaces.go @@ -13,7 +13,7 @@ type SplitStorageProducer interface { Update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) KillLocally(splitName string, defaultTreatment string, changeNumber int64) SetChangeNumber(changeNumber int64) error - ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) + ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error } // SplitStorageConsumer should be implemented by structs that offer reading splits from storage @@ -21,8 +21,9 @@ type SplitStorageConsumer interface { ChangeNumber() (int64, error) All() []dtos.SplitDTO FetchMany(splitNames []string) map[string]*dtos.SplitDTO - SegmentNames() *set.ThreadUnsafeSet // Not in Spec - LargeSegmentNames() *set.ThreadUnsafeSet // Not in Spec + SegmentNames() *set.ThreadUnsafeSet // Not in Spec + LargeSegmentNames() *set.ThreadUnsafeSet // Not in Spec + RuleBasedSegmentNames() *set.ThreadUnsafeSet // Not in Spec Split(splitName string) *dtos.SplitDTO SplitNames() []string TrafficTypeExists(trafficType string) bool @@ -205,14 +206,15 @@ type SplitStorage interface { SetChangeNumber(changeNumber int64) error All() []dtos.SplitDTO FetchMany(splitNames []string) map[string]*dtos.SplitDTO - SegmentNames() *set.ThreadUnsafeSet // Not in Spec - LargeSegmentNames() *set.ThreadUnsafeSet // Not in Spec + SegmentNames() *set.ThreadUnsafeSet // Not in Spec + LargeSegmentNames() *set.ThreadUnsafeSet // Not in Spec + RuleBasedSegmentNames() *set.ThreadUnsafeSet // Not in Spec Split(splitName string) *dtos.SplitDTO SplitNames() []string TrafficTypeExists(trafficType string) bool GetNamesByFlagSets(sets []string) map[string][]string GetAllFlagSetNames() []string - ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) + ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error } // SegmentStorage wraps consumer and producer interfaces @@ -273,16 +275,17 @@ type RuleBasedSegmentStorageProducer interface { SetChangeNumber(till int64) error Update(toAdd []dtos.RuleBasedSegmentDTO, toRemove []dtos.RuleBasedSegmentDTO, till int64) Clear() - ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) + ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) error } // RuleBasedStorageConsumer interface should be implemented by all structs that ofer reading rule-based segments type RuleBasedSegmentStorageConsumer interface { - ChangeNumber() int64 + ChangeNumber() (int64, error) All() []dtos.RuleBasedSegmentDTO RuleBasedSegmentNames() []string Contains(ruleBasedSegmentNames []string) bool - GetSegments() *set.ThreadUnsafeSet + Segments() *set.ThreadUnsafeSet + LargeSegments() *set.ThreadUnsafeSet GetRuleBasedSegmentByName(name string) (*dtos.RuleBasedSegmentDTO, error) } diff --git a/storage/mocks/rulebasedsegment.go b/storage/mocks/rulebasedsegment.go index e0c055d7..453e2520 100644 --- a/storage/mocks/rulebasedsegment.go +++ b/storage/mocks/rulebasedsegment.go @@ -13,9 +13,9 @@ type MockRuleBasedSegmentStorage struct { } // ChangeNumber mock -func (m *MockRuleBasedSegmentStorage) ChangeNumber() int64 { +func (m *MockRuleBasedSegmentStorage) ChangeNumber() (int64, error) { args := m.Called() - return args.Get(0).(int64) + return args.Get(0).(int64), nil } // All mock @@ -70,8 +70,19 @@ func (m *MockRuleBasedSegmentStorage) Clear() { m.Called() } -func (m *MockRuleBasedSegmentStorage) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) { - m.Called(toAdd, changeNumber) +func (m *MockRuleBasedSegmentStorage) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) error { + args := m.Called(toAdd, changeNumber) + return args.Error(0) +} + +func (m *MockRuleBasedSegmentStorage) Segments() *set.ThreadUnsafeSet { + args := m.Called() + return args.Get(0).(*set.ThreadUnsafeSet) +} + +func (m *MockRuleBasedSegmentStorage) LargeSegments() *set.ThreadUnsafeSet { + args := m.Called() + return args.Get(0).(*set.ThreadUnsafeSet) } var _ storage.RuleBasedSegmentsStorage = (*MockRuleBasedSegmentStorage)(nil) diff --git a/storage/mocks/split.go b/storage/mocks/split.go index b618f122..0032b9c3 100644 --- a/storage/mocks/split.go +++ b/storage/mocks/split.go @@ -9,21 +9,22 @@ import ( // MockSplitStorage is a mocked implementation of Split Storage type MockSplitStorage struct { - AllCall func() []dtos.SplitDTO - ChangeNumberCall func() (int64, error) - FetchManyCall func(splitNames []string) map[string]*dtos.SplitDTO - KillLocallyCall func(splitName string, defaultTreatment string, changeNumber int64) - UpdateCall func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) - RemoveCall func(splitName string) - SegmentNamesCall func() *set.ThreadUnsafeSet - LargeSegmentNamesCall func() *set.ThreadUnsafeSet - SetChangeNumberCall func(changeNumber int64) error - SplitCall func(splitName string) *dtos.SplitDTO - SplitNamesCall func() []string - TrafficTypeExistsCall func(trafficType string) bool - GetNamesByFlagSetsCall func(sets []string) map[string][]string - GetAllFlagSetNamesCall func() []string - ReplaceAllCall func(toAdd []dtos.SplitDTO, changeNumber int64) + AllCall func() []dtos.SplitDTO + ChangeNumberCall func() (int64, error) + FetchManyCall func(splitNames []string) map[string]*dtos.SplitDTO + KillLocallyCall func(splitName string, defaultTreatment string, changeNumber int64) + UpdateCall func(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, changeNumber int64) + RemoveCall func(splitName string) + SegmentNamesCall func() *set.ThreadUnsafeSet + LargeSegmentNamesCall func() *set.ThreadUnsafeSet + RuleBasedSegmentNamesCall func() *set.ThreadUnsafeSet + SetChangeNumberCall func(changeNumber int64) error + SplitCall func(splitName string) *dtos.SplitDTO + SplitNamesCall func() []string + TrafficTypeExistsCall func(trafficType string) bool + GetNamesByFlagSetsCall func(sets []string) map[string][]string + GetAllFlagSetNamesCall func() []string + ReplaceAllCall func(toAdd []dtos.SplitDTO, changeNumber int64) error } // All mock @@ -61,11 +62,16 @@ func (m MockSplitStorage) SegmentNames() *set.ThreadUnsafeSet { return m.SegmentNamesCall() } -// SegmentNames mock +// LargeSegmentNames mock func (m MockSplitStorage) LargeSegmentNames() *set.ThreadUnsafeSet { return m.LargeSegmentNamesCall() } +// RuleBasedSegmentNames mock +func (m MockSplitStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { + return m.RuleBasedSegmentNamesCall() +} + // SetChangeNumber mock func (m MockSplitStorage) SetChangeNumber(changeNumber int64) error { return m.SetChangeNumberCall(changeNumber) @@ -95,8 +101,9 @@ func (m MockSplitStorage) GetAllFlagSetNames() []string { return m.GetAllFlagSetNamesCall() } -func (m MockSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { +func (m MockSplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error { m.ReplaceAllCall(toAdd, changeNumber) + return nil } // SplitStorageMock is a mocked implementation of Split Storage with testify @@ -113,7 +120,7 @@ func (m *SplitStorageMock) All() []dtos.SplitDTO { // ChangeNumber mock func (m *SplitStorageMock) ChangeNumber() (int64, error) { args := m.Called() - return args.Get(0).(int64), args.Error(1) + return args.Get(0).(int64), nil } // FetchMany mock @@ -207,8 +214,17 @@ func (m *SplitStorageMock) GetAllFlagSetNames() []string { } // ReplaceAll mock -func (m *SplitStorageMock) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { - m.Called(toAdd, changeNumber) +func (m *SplitStorageMock) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error { + args := m.Called(toAdd, changeNumber) + return args.Error(0) +} + +func (m *SplitStorageMock) RuleBasedSegmentNames() *set.ThreadUnsafeSet { + args := m.Called() + if args.Get(0) == nil { + return nil + } + return args.Get(0).(*set.ThreadUnsafeSet) } var _ storage.SplitStorage = (*SplitStorageMock)(nil) diff --git a/storage/redis/splits.go b/storage/redis/splits.go index 8688ee0d..c8b68f7f 100644 --- a/storage/redis/splits.go +++ b/storage/redis/splits.go @@ -309,7 +309,7 @@ func (r *SplitStorage) SegmentNames() *set.ThreadUnsafeSet { for _, split := range splits { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil { + if matcher.UserDefinedSegment != nil && matcher.MatcherType != "IN_RULE_BASED_SEGMENT" { segmentNames.Add(matcher.UserDefinedSegment.SegmentName) } } @@ -325,6 +325,23 @@ func (r *SplitStorage) LargeSegmentNames() *set.ThreadUnsafeSet { return segments } +// RuleBasedSegmentNames returns a slice of strings with all the rule-baseed segment names +func (r *SplitStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { + segmentNames := set.NewSet() + splits := r.All() + + for _, split := range splits { + for _, condition := range split.Conditions { + for _, matcher := range condition.MatcherGroup.Matchers { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == "IN_RULE_BASED_SEGMENT" { + segmentNames.Add(matcher.UserDefinedSegment.SegmentName) + } + } + } + } + return segmentNames +} + // SetChangeNumber sets the till value belong to segmentName func (r *SplitStorage) SetChangeNumber(changeNumber int64) error { return r.client.Set(KeySplitTill, changeNumber, 0) @@ -493,8 +510,9 @@ func (r *SplitStorage) splitKeysClusterMode() ([]string, error) { return result, nil } -func (r *SplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) { +func (r *SplitStorage) ReplaceAll(toAdd []dtos.SplitDTO, changeNumber int64) error { //to do + return nil } var _ storage.SplitStorage = (*SplitStorage)(nil) diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 5e67f98b..bce5481f 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -135,7 +135,7 @@ func TestSyncAllErrorInSegments(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(4) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -228,7 +228,7 @@ func TestSyncAllOk(t *testing.T) { appMonitorMock := &hcMock.ApplicationMonitorMock{} appMonitorMock.On("NotifyEvent", mock.Anything).Return().Times(4) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) ruleBasedSegmentMockStorage.On("ChangeNumber").Maybe().Return(int64(-1)) ruleBasedSegmentMockStorage.On("Update", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(-1) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} diff --git a/synchronizer/worker/segment/segment.go b/synchronizer/worker/segment/segment.go index d313c083..1f8703d3 100644 --- a/synchronizer/worker/segment/segment.go +++ b/synchronizer/worker/segment/segment.go @@ -196,7 +196,7 @@ func (s *UpdaterImpl) SynchronizeSegment(name string, till *int64) (*UpdateResul // SynchronizeSegments syncs segments at once func (s *UpdaterImpl) SynchronizeSegments() (map[string]UpdateResult, error) { segmentNames := s.splitStorage.SegmentNames().List() - segmentNames = append(segmentNames, s.ruleBasedSegmentStorage.GetSegments().List()...) + segmentNames = append(segmentNames, s.ruleBasedSegmentStorage.Segments().List()...) s.logger.Debug("Segment Sync", segmentNames) s.hcMonitor.NotifyEvent(application.Segments) wg := sync.WaitGroup{} diff --git a/synchronizer/worker/segment/segment_test.go b/synchronizer/worker/segment/segment_test.go index d361e238..83f75791 100644 --- a/synchronizer/worker/segment/segment_test.go +++ b/synchronizer/worker/segment/segment_test.go @@ -71,7 +71,7 @@ func TestSegmentsSynchronizerError(t *testing.T) { }, } ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) segmentSync := NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, segmentMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock) @@ -184,7 +184,7 @@ func TestSegmentSynchronizer(t *testing.T) { }, } ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) segmentSync := NewSegmentUpdater(splitMockStorage, segmentMockStorage, ruleBasedSegmentMockStorage, segmentMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock) @@ -259,7 +259,7 @@ func TestSegmentSyncUpdate(t *testing.T) { }, } ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) runtimeTelemetry, _ := inmemory.NewTelemetryStorage() segmentSync := NewSegmentUpdater(splitStorage, segmentStorage, ruleBasedSegmentMockStorage, segmentMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), runtimeTelemetry, appMonitorMock) @@ -376,7 +376,7 @@ func TestSegmentSyncProcess(t *testing.T) { }, } ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) runtimeTelemetry, _ := inmemory.NewTelemetryStorage() segmentSync := NewSegmentUpdater(splitStorage, segmentStorage, ruleBasedSegmentMockStorage, segmentMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), runtimeTelemetry, appMonitorMock) @@ -656,7 +656,7 @@ func TestSegmentSyncConcurrencyLimit(t *testing.T) { segmentStorage := mutexmap.NewMMSegmentStorage() runtimeTelemetry, _ := inmemory.NewTelemetryStorage() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} - ruleBasedSegmentMockStorage.On("GetSegments").Return(set.NewSet()) + ruleBasedSegmentMockStorage.On("Segments").Return(set.NewSet()) segmentSync := NewSegmentUpdater(splitStorage, segmentStorage, ruleBasedSegmentMockStorage, segmentMockFetcher, logging.NewLogger(nil), runtimeTelemetry, &application.Dummy{}) _, err := segmentSync.SynchronizeSegments() diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index ad66e630..cb14eaab 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -28,6 +28,7 @@ const ( UpdateTypeSplitChange = "SPLIT_UPDATE" UpdateTypeRuleBasedChange = "RB_SEGMENT_UPDATE" TypeStandard = "standard" + TypeLargeSegment = "large" onDemandFetchBackoffBase = int64(10) // backoff base starting at 10 seconds onDemandFetchBackoffMaxWait = 60 * time.Second // don't sleep for more than 1 minute onDemandFetchBackoffMaxRetries = 10 @@ -51,12 +52,13 @@ type Updater interface { // UpdateResult encapsulates information regarding the split update performed type UpdateResult struct { - UpdatedSplits []string - ReferencedSegments []string - ReferencedLargeSegments []string - NewChangeNumber int64 - NewRBChangeNumber int64 - RequiresFetch bool + UpdatedSplits []string + UpdatedRuleBasedSegments []string + ReferencedSegments []string + ReferencedLargeSegments []string + NewChangeNumber int64 + NewRBChangeNumber int64 + RequiresFetch bool } type internalSplitSync struct { @@ -122,11 +124,10 @@ func (s *UpdaterImpl) processUpdate(splitChanges dtos.FFResponse) { s.splitStorage.Update(activeSplits, inactiveSplits, splitChanges.FFTill()) } -func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges dtos.FFResponse) []string { - activeRB, inactiveRB, segments := s.processRuleBasedSegmentChanges(splitChanges.RuleBasedSegments()) +func (s *UpdaterImpl) processRuleBasedUpdate(splitChanges dtos.FFResponse) { + activeRB, inactiveRB := s.processRuleBasedSegmentChanges(splitChanges.RuleBasedSegments()) // Add/Update active splits s.ruleBasedSegmentStorage.Update(activeRB, inactiveRB, splitChanges.RBTill()) - return segments } // fetchUntil Hit endpoint, update storage and return when since==till. @@ -134,6 +135,7 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda // just guessing sizes so the we don't realloc immediately segmentReferences := make([]string, 0, 10) updatedSplitNames := make([]string, 0, 10) + updatedRuleBasedsegmentNames := make([]string, 0, 10) largeSegmentReferences := make([]string, 0, 10) var err error var currentSince int64 @@ -141,7 +143,7 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda for { // Fetch until since==till currentSince, _ = s.splitStorage.ChangeNumber() - currentRBSince = s.ruleBasedSegmentStorage.ChangeNumber() + currentRBSince, _ = s.ruleBasedSegmentStorage.ChangeNumber() before := time.Now() var splitChanges dtos.FFResponse splitChanges, err = s.splitFetcher.Fetch(fetchOptions.WithChangeNumber(currentSince).WithChangeNumberRB(currentRBSince).WithSpecVersion(common.StringRef(s.specVersion))) @@ -158,21 +160,25 @@ func (s *UpdaterImpl) fetchUntil(fetchOptions *service.FlagRequestParams) (*Upda currentRBSince = splitChanges.RBTill() s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before)) s.processUpdate(splitChanges) - segmentReferences = s.processRuleBasedUpdate(splitChanges) + s.processRuleBasedUpdate(splitChanges) segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) + segmentReferences = append(segmentReferences, s.getSegmentsFromRuleBasedSegments(splitChanges.RuleBasedSegments())...) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges.FeatureFlags()) + updatedRuleBasedsegmentNames = appendRuleBasedNames(updatedRuleBasedsegmentNames, splitChanges.RuleBasedSegments()) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) + largeSegmentReferences = append(largeSegmentReferences, s.getLargeSegmentsFromRuleBasedSegments(splitChanges.RuleBasedSegments())...) if splitChanges.NeedsAnotherFetch() { s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC()) break } } return &UpdateResult{ - UpdatedSplits: common.DedupeStringSlice(updatedSplitNames), - ReferencedSegments: common.DedupeStringSlice(segmentReferences), - NewChangeNumber: currentSince, - NewRBChangeNumber: currentRBSince, - ReferencedLargeSegments: common.DedupeStringSlice(largeSegmentReferences), + UpdatedSplits: common.DedupeStringSlice(updatedSplitNames), + UpdatedRuleBasedSegments: common.DedupeStringSlice(updatedRuleBasedsegmentNames), + ReferencedSegments: common.DedupeStringSlice(segmentReferences), + NewChangeNumber: currentSince, + NewRBChangeNumber: currentRBSince, + ReferencedLargeSegments: common.DedupeStringSlice(largeSegmentReferences), }, err } @@ -197,7 +203,7 @@ func (s *UpdaterImpl) attemptSplitSync(fetchOptions *service.FlagRequestParams, func (s *UpdaterImpl) synchronizeSplits(till *int64) (*UpdateResult, error) { s.hcMonitor.NotifyEvent(application.Splits) currentSince, _ := s.splitStorage.ChangeNumber() - currentRBSince := s.ruleBasedSegmentStorage.ChangeNumber() + currentRBSince, _ := s.ruleBasedSegmentStorage.ChangeNumber() if till != nil && *till < currentSince && *till < currentRBSince { // the passed till is less than change_number, no need to perform updates return &UpdateResult{}, nil } @@ -230,6 +236,7 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { s.hcMonitor.NotifyEvent(application.Splits) // just guessing sizes so the we don't realloc immediately updatedSplitNames := make([]string, 0, 10) + updatedRuleBasedSegmentNames := make([]string, 0, 10) largeSegmentReferences := make([]string, 0, 10) currentSince := int64(-1) currentRBSince := int64(-1) @@ -256,13 +263,16 @@ func (s *UpdaterImpl) attemptLatestSync() (*UpdateResult, error) { segmentReferences := s.getSegmentsFromRuleBasedSegments(splitChanges.RuleBasedSegments()) segmentReferences = appendSegmentNames(segmentReferences, splitChanges.FeatureFlags()) updatedSplitNames = appendSplitNames(updatedSplitNames, splitChanges.FeatureFlags()) + updatedRuleBasedSegmentNames = appendRuleBasedNames(updatedRuleBasedSegmentNames, splitChanges.RuleBasedSegments()) largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, splitChanges.FeatureFlags()) + largeSegmentReferences = append(largeSegmentReferences, s.getLargeSegmentsFromRuleBasedSegments(splitChanges.RuleBasedSegments())...) return &UpdateResult{ - UpdatedSplits: common.DedupeStringSlice(updatedSplitNames), - ReferencedSegments: common.DedupeStringSlice(segmentReferences), - NewChangeNumber: currentSince, - NewRBChangeNumber: currentRBSince, - ReferencedLargeSegments: common.DedupeStringSlice(largeSegmentReferences), + UpdatedSplits: common.DedupeStringSlice(updatedSplitNames), + UpdatedRuleBasedSegments: common.DedupeStringSlice(updatedRuleBasedSegmentNames), + ReferencedSegments: common.DedupeStringSlice(segmentReferences), + NewChangeNumber: currentSince, + NewRBChangeNumber: currentRBSince, + ReferencedLargeSegments: common.DedupeStringSlice(largeSegmentReferences), }, err } @@ -287,11 +297,12 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64) (*UpdateResult, error) { return untilTillSince, err } return &UpdateResult{ - UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), - ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), - NewChangeNumber: untilTillSince.NewChangeNumber, - NewRBChangeNumber: untilTillSince.NewRBChangeNumber, - ReferencedLargeSegments: common.DedupeStringSlice(append(syncResult.ReferencedLargeSegments, untilTillSince.ReferencedLargeSegments...)), + UpdatedSplits: common.DedupeStringSlice(append(syncResult.UpdatedSplits, untilTillSince.UpdatedSplits...)), + UpdatedRuleBasedSegments: common.DedupeStringSlice(append(syncResult.UpdatedRuleBasedSegments, untilTillSince.UpdatedRuleBasedSegments...)), + ReferencedSegments: common.DedupeStringSlice(append(syncResult.ReferencedSegments, untilTillSince.ReferencedSegments...)), + NewChangeNumber: untilTillSince.NewChangeNumber, + NewRBChangeNumber: untilTillSince.NewRBChangeNumber, + ReferencedLargeSegments: common.DedupeStringSlice(append(syncResult.ReferencedLargeSegments, untilTillSince.ReferencedLargeSegments...)), }, nil } else { if !errors.Is(err, ErrProxy) { @@ -311,6 +322,13 @@ func appendSplitNames(dst []string, featureFlags []dtos.SplitDTO) []string { return dst } +func appendRuleBasedNames(dst []string, ruleBasedSegments []dtos.RuleBasedSegmentDTO) []string { + for idx := range ruleBasedSegments { + dst = append(dst, ruleBasedSegments[idx].Name) + } + return dst +} + func appendSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { for _, split := range featureFlags { for _, cond := range split.Conditions { @@ -345,9 +363,8 @@ func addIfNotExists(dst []string, seen map[string]struct{}, name string) []strin return dst } -func appendRuleBasedSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { +func appendRuleBasedSegmentNamesReferenced(dst []string, featureFlags []dtos.SplitDTO) []string { seen := make(map[string]struct{}) - // Inicializamos el mapa con lo que ya tiene dst para no duplicar tampoco ahí for _, name := range dst { seen[name] = struct{}{} } @@ -399,32 +416,35 @@ func (s *UpdaterImpl) processFFChange(ffChange dtos.SplitChangeUpdate) *UpdateRe return &UpdateResult{RequiresFetch: true} } - // If we have a feature flag, update it - segmentReferences := make([]string, 0, 10) - updatedSplitNames := make([]string, 0, 1) - largeSegmentReferences := make([]string, 0, 10) - ruleBasedSegmentReferences := make([]string, 0, 10) - s.logger.Debug(fmt.Sprintf("updating feature flag %s", ffChange.FeatureFlag().Name)) - featureFlags := make([]dtos.SplitDTO, 0, 1) - featureFlags = append(featureFlags, *ffChange.FeatureFlag()) - activeFFs, inactiveFFs := s.processFeatureFlagChanges(featureFlags) - s.splitStorage.Update(activeFFs, inactiveFFs, ffChange.BaseUpdate.ChangeNumber()) - s.runtimeTelemetry.RecordUpdatesFromSSE(telemetry.SplitUpdate) - updatedSplitNames = append(updatedSplitNames, ffChange.FeatureFlag().Name) - segmentReferences = appendSegmentNames(segmentReferences, featureFlags) - largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, featureFlags) - ruleBasedSegmentReferences = appendRuleBasedSegmentNames(ruleBasedSegmentReferences, featureFlags) - requiresFetch := false - if len(ruleBasedSegmentReferences) > 0 && !s.ruleBasedSegmentStorage.Contains(ruleBasedSegmentReferences) { - requiresFetch = true - } - return &UpdateResult{ - UpdatedSplits: updatedSplitNames, - ReferencedSegments: segmentReferences, - NewChangeNumber: ffChange.BaseUpdate.ChangeNumber(), - RequiresFetch: requiresFetch, - ReferencedLargeSegments: largeSegmentReferences, + if ffChange.FeatureFlag() != nil && *ffChange.PreviousChangeNumber() == changeNumber { + // If we have a feature flag, update it + segmentReferences := make([]string, 0, 10) + updatedSplitNames := make([]string, 0, 1) + largeSegmentReferences := make([]string, 0, 10) + ruleBasedSegmentReferences := make([]string, 0, 10) + s.logger.Debug(fmt.Sprintf("updating feature flag %s", ffChange.FeatureFlag().Name)) + featureFlags := make([]dtos.SplitDTO, 0, 1) + featureFlags = append(featureFlags, *ffChange.FeatureFlag()) + ruleBasedSegmentReferences = appendRuleBasedSegmentNamesReferenced(ruleBasedSegmentReferences, featureFlags) + if len(ruleBasedSegmentReferences) > 0 && !s.ruleBasedSegmentStorage.Contains(ruleBasedSegmentReferences) { + return &UpdateResult{RequiresFetch: true} + } + activeFFs, inactiveFFs := s.processFeatureFlagChanges(featureFlags) + s.splitStorage.Update(activeFFs, inactiveFFs, ffChange.BaseUpdate.ChangeNumber()) + s.runtimeTelemetry.RecordUpdatesFromSSE(telemetry.SplitUpdate) + updatedSplitNames = append(updatedSplitNames, ffChange.FeatureFlag().Name) + segmentReferences = appendSegmentNames(segmentReferences, featureFlags) + largeSegmentReferences = appendLargeSegmentNames(largeSegmentReferences, featureFlags) + return &UpdateResult{ + UpdatedSplits: updatedSplitNames, + ReferencedSegments: segmentReferences, + NewChangeNumber: ffChange.BaseUpdate.ChangeNumber(), + RequiresFetch: false, + ReferencedLargeSegments: largeSegmentReferences, + } } + s.logger.Debug("the feature flag was nil or the previous change number wasn't equal to the feature flag storage's change number") + return &UpdateResult{RequiresFetch: true} } func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) []string { @@ -448,20 +468,39 @@ func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) [] return segments } -func (s *UpdaterImpl) processRuleBasedSegmentChanges(ruleBasedSegments []dtos.RuleBasedSegmentDTO) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO, []string) { +func (s *UpdaterImpl) getLargeSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) []string { + seen := make(map[string]struct{}) + largeSegments := make([]string, 0) + + for _, segment := range ruleBasedSegment.Excluded.Segments { + if segment.Type == TypeLargeSegment { + largeSegments = addIfNotExists(largeSegments, seen, segment.Name) + } + } + + for _, cond := range ruleBasedSegment.Conditions { + for _, matcher := range cond.MatcherGroup.Matchers { + if matcher.MatcherType == matcherTypeInLargeSegment { + largeSegments = addIfNotExists(largeSegments, seen, matcher.UserDefinedSegment.SegmentName) + } + } + } + + return largeSegments +} + +func (s *UpdaterImpl) processRuleBasedSegmentChanges(ruleBasedSegments []dtos.RuleBasedSegmentDTO) ([]dtos.RuleBasedSegmentDTO, []dtos.RuleBasedSegmentDTO) { toRemove := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) toAdd := make([]dtos.RuleBasedSegmentDTO, 0, len(ruleBasedSegments)) - segments := make([]string, 0) for _, rbSegment := range ruleBasedSegments { if rbSegment.Status == Active { s.validator.ProcessRBMatchers(&rbSegment, s.logger) toAdd = append(toAdd, rbSegment) - segments = append(segments, s.getSegments(&rbSegment)...) } else { toRemove = append(toRemove, rbSegment) } } - return toAdd, toRemove, segments + return toAdd, toRemove } func (s *UpdaterImpl) getSegmentsFromRuleBasedSegments(ruleBasedSegments []dtos.RuleBasedSegmentDTO) []string { @@ -472,22 +511,42 @@ func (s *UpdaterImpl) getSegmentsFromRuleBasedSegments(ruleBasedSegments []dtos. return segments } +func (s *UpdaterImpl) getLargeSegmentsFromRuleBasedSegments(ruleBasedSegments []dtos.RuleBasedSegmentDTO) []string { + largeSegments := make([]string, 0) + for _, rbSegment := range ruleBasedSegments { + largeSegments = append(largeSegments, s.getLargeSegments(&rbSegment)...) + } + return largeSegments +} + func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitChangeUpdate) *UpdateResult { - changeNumber := s.ruleBasedSegmentStorage.ChangeNumber() + changeNumber, err := s.ruleBasedSegmentStorage.ChangeNumber() + if err != nil { + s.logger.Debug(fmt.Sprintf("problem getting change number from rule-based segments storage: %s", err.Error())) + return &UpdateResult{RequiresFetch: true} + } if changeNumber >= ruleBasedChange.BaseUpdate.ChangeNumber() { s.logger.Debug("the rule-based segment it's already updated") return &UpdateResult{RequiresFetch: true} } - ruleBasedSegments := make([]dtos.RuleBasedSegmentDTO, 0, 1) - ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) - toRemove, toAdd, segments := s.processRuleBasedSegmentChanges(ruleBasedSegments) - s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) - - return &UpdateResult{ - ReferencedSegments: segments, - NewRBChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), - RequiresFetch: false, + if ruleBasedChange.RuleBasedSegment() != nil && *ruleBasedChange.PreviousChangeNumber() == changeNumber { + ruleBasedSegments := make([]dtos.RuleBasedSegmentDTO, 0, 1) + ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) + toRemove, toAdd := s.processRuleBasedSegmentChanges(ruleBasedSegments) + segments := s.getSegmentsFromRuleBasedSegments(ruleBasedSegments) + //large segments + s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) + + return &UpdateResult{ + UpdatedRuleBasedSegments: []string{ruleBasedChange.RuleBasedSegment().Name}, + ReferencedSegments: segments, + //large segment referenced + NewRBChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), + RequiresFetch: false, + } } + s.logger.Debug("the rule-based segment was nil or the previous change number wasn't equal to the rule-based segment storage's change number") + return &UpdateResult{RequiresFetch: true} } func (s *UpdaterImpl) SynchronizeFeatureFlags(ffChange *dtos.SplitChangeUpdate) (*UpdateResult, error) { diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index b1bca597..cb7ee442 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -806,6 +806,9 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { ruleBasedSegmentMockStorage.AssertExpectations(t) appMonitorMock.AssertExpectations(t) }) +} + +func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { t.Run("Rule-based segment change number higher than current", func(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} @@ -837,13 +840,25 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { }, }, } + response := &dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Since: 3, + Till: 3, + }, + }, + } + pvChangeNumber := int64(100) baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") baseUpdate := dtos.NewBaseUpdate(baseMessage, changeNumber) - ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, nil, ruleBasedSegment) + ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, &pvChangeNumber, ruleBasedSegment) - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200)).Once() + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200)).Times(3) + splitMockStorage.On("ChangeNumber").Return(int64(200)).Twice() ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{*ruleBasedSegment}, []dtos.RuleBasedSegmentDTO{}, changeNumber).Return().Once() - + splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() + splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(3)).Once() + appMonitorMock.On("NotifyEvent", mock.Anything).Once() result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) assert.Nil(t, err) assert.False(t, result.RequiresFetch) From 2b389da7c06cc4bb8c168f06ce1a41cc08aef161 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 20 Oct 2025 15:17:06 -0300 Subject: [PATCH 32/39] Updated constants --- engine/engine_test.go | 16 +++--- engine/evaluator/evaluator_test.go | 17 ++++--- engine/grammar/condition_test.go | 3 +- engine/grammar/constants/constants.go | 51 +++++++++++++++++++ .../dependency_test/dependency_test.go | 17 ++++--- engine/grammar/inlargesegment_test.go | 17 ++++--- engine/grammar/matchers.go | 51 ------------------- engine/grammar/matchers_test.go | 7 +-- engine/grammar/rulebuilder.go | 49 +++++++++--------- engine/grammar/semver_test.go | 39 +++++++------- engine/grammar/split_test.go | 6 +-- engine/validator/matchers.go | 5 +- engine/validator/matchers_test.go | 31 +++++------ service/api/specs/splitversionfilter.go | 14 ++--- service/api/specs/splitversionfilter_test.go | 16 +++--- storage/inmemory/mutexmap/rulebasedsegment.go | 5 +- storage/inmemory/mutexmap/splits.go | 5 +- storage/redis/splits.go | 5 +- synchronizer/local_test.go | 17 ++++--- synchronizer/worker/split/split.go | 17 +++---- synchronizer/worker/split/split_test.go | 23 +++++---- tasks/splitsync_test.go | 17 ++++--- 22 files changed, 220 insertions(+), 208 deletions(-) diff --git a/engine/engine_test.go b/engine/engine_test.go index 981ebf2c..beff4799 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -16,14 +16,14 @@ import ( "github.com/splitio/go-toolkit/v5/logging" ) -var syncProxyFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} -var syncProxyRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} +var syncProxyFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} +var syncProxyRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} func TestProperHashFunctionIsUsed(t *testing.T) { eng := Engine{} diff --git a/engine/evaluator/evaluator_test.go b/engine/evaluator/evaluator_test.go index c542a1ae..44557cf7 100644 --- a/engine/evaluator/evaluator_test.go +++ b/engine/evaluator/evaluator_test.go @@ -7,6 +7,7 @@ import ( "github.com/splitio/go-split-commons/v7/engine" "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" "github.com/splitio/go-split-commons/v7/storage/mocks" @@ -16,14 +17,14 @@ import ( "github.com/stretchr/testify/assert" ) -var syncProxyFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} -var syncProxyRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} +var syncProxyFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} +var syncProxyRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} type mockStorage struct{} diff --git a/engine/grammar/condition_test.go b/engine/grammar/condition_test.go index 05bf627b..c4fc14bf 100644 --- a/engine/grammar/condition_test.go +++ b/engine/grammar/condition_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" @@ -209,7 +210,7 @@ func TestConditionMatcherWithNilStringWrapperObject(t *testing.T) { Matchers: []dtos.MatcherDTO{ { Negate: false, - MatcherType: MatcherTypeStartsWith, + MatcherType: constants.MatcherTypeStartsWith, KeySelector: &dtos.KeySelectorDTO{ Attribute: nil, TrafficType: "something", diff --git a/engine/grammar/constants/constants.go b/engine/grammar/constants/constants.go index f3031837..6c7de375 100644 --- a/engine/grammar/constants/constants.go +++ b/engine/grammar/constants/constants.go @@ -12,3 +12,54 @@ const ( // SplitAlgoMurmur represents the murmur implementation of the hash funcion for bucketing SplitAlgoMurmur = 2 ) + +const ( + // MatcherTypeAllKeys string value + MatcherTypeAllKeys = "ALL_KEYS" + // MatcherTypeInSegment string value + MatcherTypeInSegment = "IN_SEGMENT" + // MatcherTypeWhitelist string value + MatcherTypeWhitelist = "WHITELIST" + // MatcherTypeEqualTo string value + MatcherTypeEqualTo = "EQUAL_TO" + // MatcherTypeGreaterThanOrEqualTo string value + MatcherTypeGreaterThanOrEqualTo = "GREATER_THAN_OR_EQUAL_TO" + // MatcherTypeLessThanOrEqualTo string value + MatcherTypeLessThanOrEqualTo = "LESS_THAN_OR_EQUAL_TO" + // MatcherTypeBetween string value + MatcherTypeBetween = "BETWEEN" + // MatcherTypeEqualToSet string value + MatcherTypeEqualToSet = "EQUAL_TO_SET" + // MatcherTypePartOfSet string value + MatcherTypePartOfSet = "PART_OF_SET" + // MatcherTypeContainsAllOfSet string value + MatcherTypeContainsAllOfSet = "CONTAINS_ALL_OF_SET" + // MatcherTypeContainsAnyOfSet string value + MatcherTypeContainsAnyOfSet = "CONTAINS_ANY_OF_SET" + // MatcherTypeStartsWith string value + MatcherTypeStartsWith = "STARTS_WITH" + // MatcherTypeEndsWith string value + MatcherTypeEndsWith = "ENDS_WITH" + // MatcherTypeContainsString string value + MatcherTypeContainsString = "CONTAINS_STRING" + // MatcherTypeInSplitTreatment string value + MatcherTypeInSplitTreatment = "IN_SPLIT_TREATMENT" + // MatcherTypeEqualToBoolean string value + MatcherTypeEqualToBoolean = "EQUAL_TO_BOOLEAN" + // MatcherTypeMatchesString string value + MatcherTypeMatchesString = "MATCHES_STRING" + // MatcherEqualToSemver string value + MatcherEqualToSemver = "EQUAL_TO_SEMVER" + // MatcherTypeGreaterThanOrEqualToSemver string value + MatcherTypeGreaterThanOrEqualToSemver = "GREATER_THAN_OR_EQUAL_TO_SEMVER" + // MatcherTypeLessThanOrEqualToSemver string value + MatcherTypeLessThanOrEqualToSemver = "LESS_THAN_OR_EQUAL_TO_SEMVER" + // MatcherTypeBetweenSemver string value + MatcherTypeBetweenSemver = "BETWEEN_SEMVER" + // MatcherTypeInListSemver string value + MatcherTypeInListSemver = "IN_LIST_SEMVER" + // MatcherInLargeSegment string value + MatcherTypeInLargeSegment = "IN_LARGE_SEGMENT" + // MatcherInRuleBasedSegment string value + MatcherTypeInRuleBasedSegment = "IN_RULE_BASED_SEGMENT" +) diff --git a/engine/grammar/dependency_test/dependency_test.go b/engine/grammar/dependency_test/dependency_test.go index 7a64c665..7f9520cf 100644 --- a/engine/grammar/dependency_test/dependency_test.go +++ b/engine/grammar/dependency_test/dependency_test.go @@ -11,20 +11,21 @@ import ( "github.com/splitio/go-split-commons/v7/engine" "github.com/splitio/go-split-commons/v7/engine/evaluator" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/logging" ) -var syncProxyFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} -var syncProxyRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} +var syncProxyFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} +var syncProxyRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} type mockEvaluator struct { t *testing.T diff --git a/engine/grammar/inlargesegment_test.go b/engine/grammar/inlargesegment_test.go index 7a064b52..c16a1b50 100644 --- a/engine/grammar/inlargesegment_test.go +++ b/engine/grammar/inlargesegment_test.go @@ -5,18 +5,19 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/storage/inmemory/mutexmap" "github.com/splitio/go-toolkit/v5/logging" ) -var SyncProxyFeatureFlagsRules = []string{MatcherTypeAllKeys, MatcherTypeInSegment, MatcherTypeWhitelist, MatcherTypeEqualTo, MatcherTypeGreaterThanOrEqualTo, MatcherTypeLessThanOrEqualTo, MatcherTypeBetween, - MatcherTypeEqualToSet, MatcherTypePartOfSet, MatcherTypeContainsAllOfSet, MatcherTypeContainsAnyOfSet, MatcherTypeStartsWith, MatcherTypeEndsWith, MatcherTypeContainsString, MatcherTypeInSplitTreatment, - MatcherTypeEqualToBoolean, MatcherTypeMatchesString, MatcherEqualToSemver, MatcherTypeGreaterThanOrEqualToSemver, MatcherTypeLessThanOrEqualToSemver, MatcherTypeBetweenSemver, MatcherTypeInListSemver, MatcherTypeInLargeSegment, - MatcherTypeInRuleBasedSegment} -var SyncProxyRuleBasedSegmentRules = []string{MatcherTypeAllKeys, MatcherTypeInSegment, MatcherTypeWhitelist, MatcherTypeEqualTo, MatcherTypeGreaterThanOrEqualTo, MatcherTypeLessThanOrEqualTo, MatcherTypeBetween, - MatcherTypeEqualToSet, MatcherTypePartOfSet, MatcherTypeContainsAllOfSet, MatcherTypeContainsAnyOfSet, MatcherTypeStartsWith, MatcherTypeEndsWith, MatcherTypeContainsString, - MatcherTypeEqualToBoolean, MatcherTypeMatchesString, MatcherEqualToSemver, MatcherTypeGreaterThanOrEqualToSemver, MatcherTypeLessThanOrEqualToSemver, MatcherTypeBetweenSemver, MatcherTypeInListSemver, MatcherTypeInLargeSegment, - MatcherTypeInRuleBasedSegment} +var SyncProxyFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} +var SyncProxyRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} func TestInLargeSegmentMatcher(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) diff --git a/engine/grammar/matchers.go b/engine/grammar/matchers.go index 2f19ba57..3304e880 100644 --- a/engine/grammar/matchers.go +++ b/engine/grammar/matchers.go @@ -13,57 +13,6 @@ var ErrInvalidLTOESemver = errors.New("semver is required for LESS_THAN_OR_EQUAL var ErrInvalidLBetweenSemver = errors.New("semver is required for BETWEEN_SEMVER matcher type") var ErrInvalidLInListSemver = errors.New("semver is required for IN_LIST_SEMVER matcher type") -const ( - // MatcherTypeAllKeys string value - MatcherTypeAllKeys = "ALL_KEYS" - // MatcherTypeInSegment string value - MatcherTypeInSegment = "IN_SEGMENT" - // MatcherTypeWhitelist string value - MatcherTypeWhitelist = "WHITELIST" - // MatcherTypeEqualTo string value - MatcherTypeEqualTo = "EQUAL_TO" - // MatcherTypeGreaterThanOrEqualTo string value - MatcherTypeGreaterThanOrEqualTo = "GREATER_THAN_OR_EQUAL_TO" - // MatcherTypeLessThanOrEqualTo string value - MatcherTypeLessThanOrEqualTo = "LESS_THAN_OR_EQUAL_TO" - // MatcherTypeBetween string value - MatcherTypeBetween = "BETWEEN" - // MatcherTypeEqualToSet string value - MatcherTypeEqualToSet = "EQUAL_TO_SET" - // MatcherTypePartOfSet string value - MatcherTypePartOfSet = "PART_OF_SET" - // MatcherTypeContainsAllOfSet string value - MatcherTypeContainsAllOfSet = "CONTAINS_ALL_OF_SET" - // MatcherTypeContainsAnyOfSet string value - MatcherTypeContainsAnyOfSet = "CONTAINS_ANY_OF_SET" - // MatcherTypeStartsWith string value - MatcherTypeStartsWith = "STARTS_WITH" - // MatcherTypeEndsWith string value - MatcherTypeEndsWith = "ENDS_WITH" - // MatcherTypeContainsString string value - MatcherTypeContainsString = "CONTAINS_STRING" - // MatcherTypeInSplitTreatment string value - MatcherTypeInSplitTreatment = "IN_SPLIT_TREATMENT" - // MatcherTypeEqualToBoolean string value - MatcherTypeEqualToBoolean = "EQUAL_TO_BOOLEAN" - // MatcherTypeMatchesString string value - MatcherTypeMatchesString = "MATCHES_STRING" - // MatcherEqualToSemver string value - MatcherEqualToSemver = "EQUAL_TO_SEMVER" - // MatcherTypeGreaterThanOrEqualToSemver string value - MatcherTypeGreaterThanOrEqualToSemver = "GREATER_THAN_OR_EQUAL_TO_SEMVER" - // MatcherTypeLessThanOrEqualToSemver string value - MatcherTypeLessThanOrEqualToSemver = "LESS_THAN_OR_EQUAL_TO_SEMVER" - // MatcherTypeBetweenSemver string value - MatcherTypeBetweenSemver = "BETWEEN_SEMVER" - // MatcherTypeInListSemver string value - MatcherTypeInListSemver = "IN_LIST_SEMVER" - // MatcherInLargeSegment string value - MatcherTypeInLargeSegment = "IN_LARGE_SEGMENT" - // MatcherInRuleBasedSegment string value - MatcherTypeInRuleBasedSegment = "IN_RULE_BASED_SEGMENT" -) - // MatcherInterface should be implemented by all matchers type MatcherInterface interface { Match(key string, attributes map[string]interface{}, bucketingKey *string) bool diff --git a/engine/grammar/matchers_test.go b/engine/grammar/matchers_test.go index 9fb9d25f..d7c1e532 100644 --- a/engine/grammar/matchers_test.go +++ b/engine/grammar/matchers_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/logging" "github.com/stretchr/testify/assert" ) @@ -18,7 +19,7 @@ func TestBuildMatcher_InRuleBasedSegment(t *testing.T) { { name: "valid rule-based segment matcher", dto: &dtos.MatcherDTO{ - MatcherType: MatcherTypeInRuleBasedSegment, + MatcherType: constants.MatcherTypeInRuleBasedSegment, Negate: false, UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", @@ -29,7 +30,7 @@ func TestBuildMatcher_InRuleBasedSegment(t *testing.T) { { name: "missing UserDefinedSegment", dto: &dtos.MatcherDTO{ - MatcherType: MatcherTypeInRuleBasedSegment, + MatcherType: constants.MatcherTypeInRuleBasedSegment, Negate: false, }, wantErr: true, @@ -38,7 +39,7 @@ func TestBuildMatcher_InRuleBasedSegment(t *testing.T) { { name: "with attribute name", dto: &dtos.MatcherDTO{ - MatcherType: MatcherTypeInRuleBasedSegment, + MatcherType: constants.MatcherTypeInRuleBasedSegment, Negate: true, UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", diff --git a/engine/grammar/rulebuilder.go b/engine/grammar/rulebuilder.go index 40cb8450..e70dd163 100644 --- a/engine/grammar/rulebuilder.go +++ b/engine/grammar/rulebuilder.go @@ -7,6 +7,7 @@ import ( "golang.org/x/exp/slices" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-toolkit/v5/logging" @@ -53,11 +54,11 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error } switch dto.MatcherType { - case MatcherTypeAllKeys: + case constants.MatcherTypeAllKeys: r.logger.Debug(fmt.Sprintf("Building AllKeysMatcher with negate=%t", dto.Negate)) matcher = NewAllKeysMatcher(dto.Negate) - case MatcherTypeEqualTo: + case constants.MatcherTypeEqualTo: if dto.UnaryNumeric == nil { return nil, errors.New("UnaryNumeric is required for EQUAL_TO matcher type") } @@ -72,7 +73,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeInSegment: + case constants.MatcherTypeInSegment: if dto.UserDefinedSegment == nil { return nil, errors.New("UserDefinedSegment is required for IN_SEGMENT matcher type") } @@ -87,7 +88,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error r.segmentStorage, ) - case MatcherTypeWhitelist: + case constants.MatcherTypeWhitelist: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for WHITELIST matcher type") } @@ -101,7 +102,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeGreaterThanOrEqualTo: + case constants.MatcherTypeGreaterThanOrEqualTo: if dto.UnaryNumeric == nil { return nil, errors.New("UnaryNumeric is required for GREATER_THAN_OR_EQUAL_TO matcher type") } @@ -116,7 +117,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeLessThanOrEqualTo: + case constants.MatcherTypeLessThanOrEqualTo: if dto.UnaryNumeric == nil { return nil, errors.New("UnaryNumeric is required for LESS_THAN_OR_EQUAL_TO matcher type") } @@ -131,7 +132,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeBetween: + case constants.MatcherTypeBetween: if dto.Between == nil { return nil, errors.New("Between is required for BETWEEN matcher type") } @@ -147,7 +148,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeEqualToSet: + case constants.MatcherTypeEqualToSet: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for EQUAL_TO_SET matcher type") } @@ -161,7 +162,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypePartOfSet: + case constants.MatcherTypePartOfSet: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for PART_OF_SET matcher type") } @@ -175,7 +176,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeContainsAllOfSet: + case constants.MatcherTypeContainsAllOfSet: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for CONTAINS_ALL_OF_SET matcher type") } @@ -189,7 +190,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeContainsAnyOfSet: + case constants.MatcherTypeContainsAnyOfSet: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for CONTAINS_ANY_OF_SET matcher type") } @@ -203,7 +204,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeStartsWith: + case constants.MatcherTypeStartsWith: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for STARTS_WITH matcher type") } @@ -217,7 +218,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeEndsWith: + case constants.MatcherTypeEndsWith: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for ENDS_WITH matcher type") } @@ -231,7 +232,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeContainsString: + case constants.MatcherTypeContainsString: if dto.Whitelist == nil { return nil, errors.New("Whitelist is required for CONTAINS_STRING matcher type") } @@ -245,7 +246,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeInSplitTreatment: + case constants.MatcherTypeInSplitTreatment: if dto.Dependency == nil { return nil, errors.New("Dependency is required for IN_SPLIT_TREATMENT matcher type") } @@ -260,7 +261,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error r.dependencyEvaluator, ) - case MatcherTypeEqualToBoolean: + case constants.MatcherTypeEqualToBoolean: if dto.Boolean == nil { return nil, errors.New("Boolean is required for EQUAL_TO_BOOLEAN matcher type") } @@ -274,7 +275,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, ) - case MatcherTypeMatchesString: + case constants.MatcherTypeMatchesString: if dto.String == nil { return nil, errors.New("String is required for MATCHES_STRING matcher type") } @@ -287,7 +288,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error *dto.String, attributeName, ) - case MatcherEqualToSemver: + case constants.MatcherEqualToSemver: if dto.String == nil { return nil, ErrInvalidEqualSemver } @@ -301,7 +302,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.logger, ) - case MatcherTypeGreaterThanOrEqualToSemver: + case constants.MatcherTypeGreaterThanOrEqualToSemver: if dto.String == nil { return nil, ErrInvalidGTOESemver } @@ -315,7 +316,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.logger, ) - case MatcherTypeLessThanOrEqualToSemver: + case constants.MatcherTypeLessThanOrEqualToSemver: if dto.String == nil { return nil, ErrInvalidLTOESemver } @@ -329,7 +330,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.logger, ) - case MatcherTypeBetweenSemver: + case constants.MatcherTypeBetweenSemver: if dto.BetweenString.Start == nil || dto.BetweenString.End == nil { return nil, ErrInvalidLBetweenSemver } @@ -344,7 +345,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.logger, ) - case MatcherTypeInListSemver: + case constants.MatcherTypeInListSemver: if dto.Whitelist == nil { return nil, ErrInvalidLInListSemver } @@ -358,7 +359,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.logger, ) - case MatcherTypeInLargeSegment: + case constants.MatcherTypeInLargeSegment: if dto.UserDefinedLargeSegment == nil { return nil, errors.New("UserDefinedLargeSegment is required for IN_LARGE_SEGMENT matcher type") } @@ -372,7 +373,7 @@ func (r RuleBuilder) BuildMatcher(dto *dtos.MatcherDTO) (MatcherInterface, error attributeName, r.largeSegmentStorage, ) - case MatcherTypeInRuleBasedSegment: + case constants.MatcherTypeInRuleBasedSegment: if dto.UserDefinedSegment == nil { return nil, errors.New("UserDefinedSegment is required for IN_RULE_BASED_SEGMENT matcher type") } diff --git a/engine/grammar/semver_test.go b/engine/grammar/semver_test.go index ee1a908c..8b34da65 100644 --- a/engine/grammar/semver_test.go +++ b/engine/grammar/semver_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/logging" ) @@ -73,7 +74,7 @@ func TestEqualToSemverMatcher(t *testing.T) { attrName := "version" str := "1.0.0" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -99,7 +100,7 @@ func TestPatchDiffers(t *testing.T) { attrName := "version" str := "1.0.0" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -125,7 +126,7 @@ func TestPreReleaseShouldReturnTrueWhenVersionsAreEqual(t *testing.T) { attrName := "version" str := "1.2.3----RC-SNAPSHOT.12.9.1--.12.88" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -151,7 +152,7 @@ func TestPreReleaseShouldReturnFalseWhenSemverIsNil(t *testing.T) { attrName := "version" str := "1.2-SNAPSHOT" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -176,7 +177,7 @@ func TestPreReleaseShouldReturnFalseWhenVersionsDiffer(t *testing.T) { attrName := "version" str := "1.2.3----RC-SNAPSHOT.12.9.1--.12.88" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -202,7 +203,7 @@ func TestMetadataShouldReturnTrueWhenVersionsAreEqual(t *testing.T) { attrName := "version" str := "2.2.2-rc.2+metadata-lalala" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -228,7 +229,7 @@ func TestMetadataShouldReturnFalseWhenVersionsDiffer(t *testing.T) { attrName := "version" str := "2.2.2-rc.2+metadata-lalala" dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: &str, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -252,7 +253,7 @@ func TestMetadataShouldReturnFalseWhenVersionsDiffer(t *testing.T) { func TestShouldReturnErrorWithNilSemver(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) dto := &dtos.MatcherDTO{ - MatcherType: MatcherEqualToSemver, + MatcherType: constants.MatcherEqualToSemver, String: nil, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -273,7 +274,7 @@ func TestGreaterThanOrEqualToSemverMatcher(t *testing.T) { for _, twoSemvers := range semvers { dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeGreaterThanOrEqualToSemver, + MatcherType: constants.MatcherTypeGreaterThanOrEqualToSemver, String: &twoSemvers.semver1, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -307,7 +308,7 @@ func TestGreaterThanOrEqualToSemverMatcherWithNilSemver(t *testing.T) { KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, }, - MatcherType: MatcherTypeGreaterThanOrEqualToSemver, + MatcherType: constants.MatcherTypeGreaterThanOrEqualToSemver, String: &semvers, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -334,7 +335,7 @@ func TestLessThanOrEqualToSemverMatcher(t *testing.T) { for _, twoSemvers := range semvers { dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeLessThanOrEqualToSemver, + MatcherType: constants.MatcherTypeLessThanOrEqualToSemver, String: &twoSemvers.semver2, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, @@ -363,7 +364,7 @@ func TestLessThanOrEqualToSemverMatcher(t *testing.T) { func TestLessThanOrEqualToSemverMatcherWithInvalidSemver(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeLessThanOrEqualToSemver, + MatcherType: constants.MatcherTypeLessThanOrEqualToSemver, String: nil, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -382,7 +383,7 @@ func TestLessThanOrEqualToSemverMatcherWithNilSemver(t *testing.T) { KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, }, - MatcherType: MatcherTypeLessThanOrEqualToSemver, + MatcherType: constants.MatcherTypeLessThanOrEqualToSemver, String: &semvers, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -409,7 +410,7 @@ func TestBetweenSemverMatcher(t *testing.T) { for _, threeSemvers := range semvers { dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeBetweenSemver, + MatcherType: constants.MatcherTypeBetweenSemver, BetweenString: &dtos.BetweenStringMatcherDataDTO{ Start: &threeSemvers.semver1, End: &threeSemvers.semver3, @@ -441,7 +442,7 @@ func TestBetweenSemverMatcher(t *testing.T) { func TestBetweenSemverWithNilSemvers(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeBetweenSemver, + MatcherType: constants.MatcherTypeBetweenSemver, BetweenString: &dtos.BetweenStringMatcherDataDTO{ Start: nil, End: nil, @@ -461,7 +462,7 @@ func TestBetweenSemverWithInvalidSemvers(t *testing.T) { start := "1.alpha.2" end := "3.4.5" dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeBetweenSemver, + MatcherType: constants.MatcherTypeBetweenSemver, BetweenString: &dtos.BetweenStringMatcherDataDTO{ Start: &start, End: &end, @@ -495,7 +496,7 @@ func TestInListSemvers(t *testing.T) { KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, }, - MatcherType: MatcherTypeInListSemver, + MatcherType: constants.MatcherTypeInListSemver, Whitelist: &dtos.WhitelistMatcherDataDTO{Whitelist: semvers}, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -528,7 +529,7 @@ func TestInListSemversNotMatch(t *testing.T) { KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, }, - MatcherType: MatcherTypeInListSemver, + MatcherType: constants.MatcherTypeInListSemver, Whitelist: &dtos.WhitelistMatcherDataDTO{Whitelist: semvers}, } ruleBuilder := NewRuleBuilder(nil, nil, nil, SyncProxyFeatureFlagsRules, SyncProxyRuleBasedSegmentRules, logger, nil) @@ -559,7 +560,7 @@ func TestInListInvalidSemvers(t *testing.T) { semvers = append(semvers, "alpha.beta.1") semvers = append(semvers, "1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788") dto := &dtos.MatcherDTO{ - MatcherType: MatcherTypeInListSemver, + MatcherType: constants.MatcherTypeInListSemver, Whitelist: &dtos.WhitelistMatcherDataDTO{Whitelist: semvers}, KeySelector: &dtos.KeySelectorDTO{ Attribute: &attrName, diff --git a/engine/grammar/split_test.go b/engine/grammar/split_test.go index 63ee1b58..ff6cef06 100644 --- a/engine/grammar/split_test.go +++ b/engine/grammar/split_test.go @@ -70,7 +70,7 @@ func TestSplitCreationWithConditionsMatcher(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "off", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Combiner: "AND", - Matchers: []dtos.MatcherDTO{{MatcherType: MatcherTypeAllKeys, Negate: false}}, + Matchers: []dtos.MatcherDTO{{MatcherType: constants.MatcherTypeAllKeys, Negate: false}}, }, }, { ConditionType: ConditionTypeWhitelist, @@ -78,7 +78,7 @@ func TestSplitCreationWithConditionsMatcher(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Combiner: "AND", - Matchers: []dtos.MatcherDTO{{MatcherType: MatcherTypeAllKeys, Negate: false}}, + Matchers: []dtos.MatcherDTO{{MatcherType: constants.MatcherTypeAllKeys, Negate: false}}, }, }}, DefaultTreatment: "def", @@ -148,7 +148,7 @@ func TestSplitCreationWithUnsupportedMatcher(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Combiner: "AND", - Matchers: []dtos.MatcherDTO{{MatcherType: MatcherTypeAllKeys, Negate: false}}, + Matchers: []dtos.MatcherDTO{{MatcherType: constants.MatcherTypeAllKeys, Negate: false}}, }, }}, DefaultTreatment: "def", diff --git a/engine/validator/matchers.go b/engine/validator/matchers.go index 1767ea01..76f8e53c 100644 --- a/engine/validator/matchers.go +++ b/engine/validator/matchers.go @@ -5,6 +5,7 @@ import ( "github.com/splitio/go-split-commons/v7/engine/evaluator" "github.com/splitio/go-split-commons/v7/engine/evaluator/impressionlabels" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/engine/grammar/datatypes" "github.com/splitio/go-toolkit/v5/logging" ) @@ -26,7 +27,7 @@ var unsupportedMatcherConditionReplacement []dtos.ConditionDTO = []dtos.Conditio Partitions: []dtos.PartitionDTO{{Treatment: evaluator.Control, Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Combiner: "AND", - Matchers: []dtos.MatcherDTO{{MatcherType: grammar.MatcherTypeAllKeys, Negate: false}}, + Matchers: []dtos.MatcherDTO{{MatcherType: constants.MatcherTypeAllKeys, Negate: false}}, }, }} @@ -35,7 +36,7 @@ var unsupportedMatcherRBConditionReplacement []dtos.RuleBasedConditionDTO = []dt ConditionType: grammar.ConditionTypeWhitelist, MatcherGroup: dtos.MatcherGroupDTO{ Combiner: "AND", - Matchers: []dtos.MatcherDTO{{MatcherType: grammar.MatcherTypeAllKeys, Negate: false}}, + Matchers: []dtos.MatcherDTO{{MatcherType: constants.MatcherTypeAllKeys, Negate: false}}, }, }} diff --git a/engine/validator/matchers_test.go b/engine/validator/matchers_test.go index c272d6ac..d0377db7 100644 --- a/engine/validator/matchers_test.go +++ b/engine/validator/matchers_test.go @@ -5,18 +5,19 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/common" "github.com/splitio/go-toolkit/v5/logging" ) -var goClientFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} -var goClientRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} +var goClientFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} +var goClientRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} func TestProcessRBMatchers(t *testing.T) { // Test case 1: Rule-based segment with unsupported matcher @@ -42,7 +43,7 @@ func TestProcessRBMatchers(t *testing.T) { if ruleBased.Conditions[0].ConditionType != grammar.ConditionTypeWhitelist { t.Error("ConditionType should be WHITELIST") } - if ruleBased.Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeAllKeys { + if ruleBased.Conditions[0].MatcherGroup.Matchers[0].MatcherType != constants.MatcherTypeAllKeys { t.Error("MatcherType should be ALL_KEYS") } @@ -55,7 +56,7 @@ func TestProcessRBMatchers(t *testing.T) { ConditionType: grammar.ConditionTypeRollout, MatcherGroup: dtos.MatcherGroupDTO{ Matchers: []dtos.MatcherDTO{ - {MatcherType: grammar.MatcherTypeEndsWith, KeySelector: nil, String: common.StringRef("test")}, + {MatcherType: constants.MatcherTypeEndsWith, KeySelector: nil, String: common.StringRef("test")}, }, }, }, @@ -68,7 +69,7 @@ func TestProcessRBMatchers(t *testing.T) { if ruleBased.Conditions[0].ConditionType != grammar.ConditionTypeRollout { t.Error("ConditionType should be ROLLOUT") } - if ruleBased.Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeEndsWith { + if ruleBased.Conditions[0].MatcherGroup.Matchers[0].MatcherType != constants.MatcherTypeEndsWith { t.Error("MatcherType should be ENDS_WITH") } } @@ -81,7 +82,7 @@ func TestProcessMatchers(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Matchers: []dtos.MatcherDTO{ - {MatcherType: grammar.MatcherTypeEndsWith, KeySelector: nil, String: common.StringRef("test")}, + {MatcherType: constants.MatcherTypeEndsWith, KeySelector: nil, String: common.StringRef("test")}, }, }, }, @@ -104,7 +105,7 @@ func TestProcessMatchers(t *testing.T) { if split.Conditions[0].ConditionType != grammar.ConditionTypeWhitelist { t.Error("ConditionType should be WHITELIST") } - if split.Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeAllKeys { + if split.Conditions[0].MatcherGroup.Matchers[0].MatcherType != constants.MatcherTypeAllKeys { t.Error("MatcherType should be ALL_KEYS") } @@ -115,7 +116,7 @@ func TestProcessMatchers(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Matchers: []dtos.MatcherDTO{ - {MatcherType: grammar.MatcherTypeAllKeys, KeySelector: nil}, + {MatcherType: constants.MatcherTypeAllKeys, KeySelector: nil}, }, }, }, @@ -126,7 +127,7 @@ func TestProcessMatchers(t *testing.T) { if split.Conditions[0].ConditionType != grammar.ConditionTypeRollout { t.Error("ConditionType should be ROLLOUT") } - if split.Conditions[0].MatcherGroup.Matchers[0].MatcherType != grammar.MatcherTypeAllKeys { + if split.Conditions[0].MatcherGroup.Matchers[0].MatcherType != constants.MatcherTypeAllKeys { t.Error("MatcherType should be ALL_KEYS") } } diff --git a/service/api/specs/splitversionfilter.go b/service/api/specs/splitversionfilter.go index be2e401e..aff894e6 100644 --- a/service/api/specs/splitversionfilter.go +++ b/service/api/specs/splitversionfilter.go @@ -1,7 +1,7 @@ package specs import ( - "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" ) type SplitVersionFilter struct { @@ -10,13 +10,13 @@ type SplitVersionFilter struct { } func NewSplitVersionFilter() SplitVersionFilter { - v1_1 := map[string]bool{grammar.MatcherTypeInLargeSegment: true} + v1_1 := map[string]bool{constants.MatcherTypeInLargeSegment: true} v1_0 := mergeMaps(map[string]bool{ - grammar.MatcherEqualToSemver: true, - grammar.MatcherTypeLessThanOrEqualToSemver: true, - grammar.MatcherTypeGreaterThanOrEqualToSemver: true, - grammar.MatcherTypeBetweenSemver: true, - grammar.MatcherTypeInListSemver: true, + constants.MatcherEqualToSemver: true, + constants.MatcherTypeLessThanOrEqualToSemver: true, + constants.MatcherTypeGreaterThanOrEqualToSemver: true, + constants.MatcherTypeBetweenSemver: true, + constants.MatcherTypeInListSemver: true, }, v1_1) return SplitVersionFilter{ diff --git a/service/api/specs/splitversionfilter_test.go b/service/api/specs/splitversionfilter_test.go index 43680447..30d00854 100644 --- a/service/api/specs/splitversionfilter_test.go +++ b/service/api/specs/splitversionfilter_test.go @@ -3,7 +3,7 @@ package specs import ( "testing" - "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" ) func TestParseAndValidate(t *testing.T) { @@ -30,37 +30,37 @@ func TestParseAndValidate(t *testing.T) { func TestSplitVersionFilter(t *testing.T) { filter := NewSplitVersionFilter() - shouldFilter := filter.ShouldFilter(grammar.MatcherTypeBetweenSemver, FLAG_V1_0) + shouldFilter := filter.ShouldFilter(constants.MatcherTypeBetweenSemver, FLAG_V1_0) if !shouldFilter { t.Error("It should filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeEqualTo, FLAG_V1_0) + shouldFilter = filter.ShouldFilter(constants.MatcherTypeEqualTo, FLAG_V1_0) if shouldFilter { t.Error("It should not filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeBetweenSemver, FLAG_V1_1) + shouldFilter = filter.ShouldFilter(constants.MatcherTypeBetweenSemver, FLAG_V1_1) if shouldFilter { t.Error("It should not filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeInLargeSegment, FLAG_V1_0) + shouldFilter = filter.ShouldFilter(constants.MatcherTypeInLargeSegment, FLAG_V1_0) if !shouldFilter { t.Error("It should filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeInLargeSegment, FLAG_V1_1) + shouldFilter = filter.ShouldFilter(constants.MatcherTypeInLargeSegment, FLAG_V1_1) if !shouldFilter { t.Error("It should filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeInLargeSegment, FLAG_V1_2) + shouldFilter = filter.ShouldFilter(constants.MatcherTypeInLargeSegment, FLAG_V1_2) if shouldFilter { t.Error("It should not filtered") } - shouldFilter = filter.ShouldFilter(grammar.MatcherTypeInLargeSegment, "4.3") + shouldFilter = filter.ShouldFilter(constants.MatcherTypeInLargeSegment, "4.3") if shouldFilter { t.Error("It should not filtered") } diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index 13162ec5..cee1d095 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-toolkit/v5/datastructures/set" ) @@ -95,7 +96,7 @@ func (r *RuleBasedSegmentsStorageImpl) Segments() *set.ThreadUnsafeSet { for _, ruleBased := range r.data { for _, condition := range ruleBased.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType != "IN_RULE_BASED_SEGMENT" { + if matcher.UserDefinedSegment != nil && matcher.MatcherType != constants.MatcherTypeInRuleBasedSegment { segments.Add(matcher.UserDefinedSegment.SegmentName) } } @@ -123,7 +124,7 @@ func (r *RuleBasedSegmentsStorageImpl) LargeSegments() *set.ThreadUnsafeSet { } } for _, excluded := range ruleBased.Excluded.Segments { - if excluded.Type == dtos.TypeStandard { + if excluded.Type == dtos.TypeLarge { largeSegments.Add(excluded.Name) } } diff --git a/storage/inmemory/mutexmap/splits.go b/storage/inmemory/mutexmap/splits.go index 37172a8c..ac45852f 100644 --- a/storage/inmemory/mutexmap/splits.go +++ b/storage/inmemory/mutexmap/splits.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" @@ -197,7 +198,7 @@ func (m *MMSplitStorage) SegmentNames() *set.ThreadUnsafeSet { for _, split := range m.data { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType != "IN_RULE_BASED_SEGMENT" { + if matcher.UserDefinedSegment != nil && matcher.MatcherType != constants.MatcherTypeInRuleBasedSegment { segments.Add(matcher.UserDefinedSegment.SegmentName) } @@ -231,7 +232,7 @@ func (m *MMSplitStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { for _, split := range m.data { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType == "IN_RULE_BASED_SEGMENT" { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == constants.MatcherTypeInRuleBasedSegment { ruleBasedSegments.Add(matcher.UserDefinedSegment.SegmentName) } diff --git a/storage/redis/splits.go b/storage/redis/splits.go index c8b68f7f..86d69f97 100644 --- a/storage/redis/splits.go +++ b/storage/redis/splits.go @@ -9,6 +9,7 @@ import ( "sync" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/storage" "github.com/splitio/go-toolkit/v5/datastructures/set" @@ -309,7 +310,7 @@ func (r *SplitStorage) SegmentNames() *set.ThreadUnsafeSet { for _, split := range splits { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType != "IN_RULE_BASED_SEGMENT" { + if matcher.UserDefinedSegment != nil && matcher.MatcherType != constants.MatcherTypeInRuleBasedSegment { segmentNames.Add(matcher.UserDefinedSegment.SegmentName) } } @@ -333,7 +334,7 @@ func (r *SplitStorage) RuleBasedSegmentNames() *set.ThreadUnsafeSet { for _, split := range splits { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType == "IN_RULE_BASED_SEGMENT" { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == constants.MatcherTypeInRuleBasedSegment { segmentNames.Add(matcher.UserDefinedSegment.SegmentName) } } diff --git a/synchronizer/local_test.go b/synchronizer/local_test.go index 6fb044fb..8ed5a912 100644 --- a/synchronizer/local_test.go +++ b/synchronizer/local_test.go @@ -7,6 +7,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/service" @@ -22,14 +23,14 @@ import ( "github.com/stretchr/testify/mock" ) -var goClientFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} -var goClientRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} +var goClientFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} +var goClientRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} func TestLocalSyncAllError(t *testing.T) { logger := logging.NewLogger(&logging.LoggerOptions{}) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index cb14eaab..765ec90c 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -8,6 +8,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/engine/validator" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/healthcheck/application" @@ -22,12 +23,8 @@ import ( ) const ( - matcherTypeInSegment = "IN_SEGMENT" - matcherTypeInLargeSegment = "IN_LARGE_SEGMENT" - matcherTypeInRuleBasedSegment = "IN_RULE_BASED_SEGMENT" UpdateTypeSplitChange = "SPLIT_UPDATE" UpdateTypeRuleBasedChange = "RB_SEGMENT_UPDATE" - TypeStandard = "standard" TypeLargeSegment = "large" onDemandFetchBackoffBase = int64(10) // backoff base starting at 10 seconds onDemandFetchBackoffMaxWait = 60 * time.Second // don't sleep for more than 1 minute @@ -333,7 +330,7 @@ func appendSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []string { for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { - if matcher.MatcherType == matcherTypeInSegment && matcher.UserDefinedSegment != nil { + if matcher.MatcherType == constants.MatcherTypeInSegment && matcher.UserDefinedSegment != nil { dst = append(dst, matcher.UserDefinedSegment.SegmentName) } } @@ -346,7 +343,7 @@ func appendLargeSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []strin for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { - if matcher.MatcherType == matcherTypeInLargeSegment && matcher.UserDefinedLargeSegment != nil { + if matcher.MatcherType == constants.MatcherTypeInLargeSegment && matcher.UserDefinedLargeSegment != nil { dst = append(dst, matcher.UserDefinedLargeSegment.LargeSegmentName) } } @@ -372,7 +369,7 @@ func appendRuleBasedSegmentNamesReferenced(dst []string, featureFlags []dtos.Spl for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { - if matcher.MatcherType == matcherTypeInRuleBasedSegment && matcher.UserDefinedSegment != nil { + if matcher.MatcherType == constants.MatcherTypeInRuleBasedSegment && matcher.UserDefinedSegment != nil { dst = addIfNotExists(dst, seen, matcher.UserDefinedSegment.SegmentName) } } @@ -452,14 +449,14 @@ func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) [] segments := make([]string, 0) for _, segment := range ruleBasedSegment.Excluded.Segments { - if segment.Type == TypeStandard { + if segment.Type == dtos.TypeStandard { segments = addIfNotExists(segments, seen, segment.Name) } } for _, cond := range ruleBasedSegment.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { - if matcher.MatcherType == matcherTypeInSegment && matcher.UserDefinedSegment != nil { + if matcher.MatcherType == constants.MatcherTypeInSegment && matcher.UserDefinedSegment != nil { segments = addIfNotExists(segments, seen, matcher.UserDefinedSegment.SegmentName) } } @@ -480,7 +477,7 @@ func (s *UpdaterImpl) getLargeSegments(ruleBasedSegment *dtos.RuleBasedSegmentDT for _, cond := range ruleBasedSegment.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { - if matcher.MatcherType == matcherTypeInLargeSegment { + if matcher.MatcherType == constants.MatcherTypeInLargeSegment { largeSegments = addIfNotExists(largeSegments, seen, matcher.UserDefinedSegment.SegmentName) } } diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index cb7ee442..0504736b 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -8,6 +8,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/service" @@ -25,14 +26,14 @@ import ( "github.com/stretchr/testify/mock" ) -var syncProxyFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} -var syncProxyRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, grammar.MatcherTypeInLargeSegment, - grammar.MatcherTypeInRuleBasedSegment} +var syncProxyFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} +var syncProxyRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, constants.MatcherTypeInLargeSegment, + constants.MatcherTypeInRuleBasedSegment} func TestSplitSynchronizerError(t *testing.T) { splitMockStorage := &mocks.SplitStorageMock{} @@ -903,7 +904,7 @@ func TestProcessMatchers(t *testing.T) { Partitions: []dtos.PartitionDTO{{Treatment: "on", Size: 100}}, MatcherGroup: dtos.MatcherGroupDTO{ Matchers: []dtos.MatcherDTO{ - {MatcherType: grammar.MatcherTypeAllKeys, KeySelector: nil}, + {MatcherType: constants.MatcherTypeAllKeys, KeySelector: nil}, }, }, }, @@ -911,9 +912,9 @@ func TestProcessMatchers(t *testing.T) { }} toAdd, _ := splitUpdater.processFeatureFlagChanges(featureFlags) assert.Equal(t, grammar.ConditionTypeWhitelist, toAdd[0].Conditions[0].ConditionType) - assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) + assert.Equal(t, constants.MatcherTypeAllKeys, toAdd[0].Conditions[0].MatcherGroup.Matchers[0].MatcherType) assert.Equal(t, grammar.ConditionTypeRollout, toAdd[1].Conditions[0].ConditionType) - assert.Equal(t, grammar.MatcherTypeAllKeys, toAdd[1].Conditions[0].MatcherGroup.Matchers[0].MatcherType) + assert.Equal(t, constants.MatcherTypeAllKeys, toAdd[1].Conditions[0].MatcherGroup.Matchers[0].MatcherType) } func TestSplitProxyDowngrade(t *testing.T) { diff --git a/tasks/splitsync_test.go b/tasks/splitsync_test.go index 8adc752c..cf78a597 100644 --- a/tasks/splitsync_test.go +++ b/tasks/splitsync_test.go @@ -6,6 +6,7 @@ import ( "github.com/splitio/go-split-commons/v7/dtos" "github.com/splitio/go-split-commons/v7/engine/grammar" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" "github.com/splitio/go-split-commons/v7/service/api/specs" @@ -19,14 +20,14 @@ import ( "github.com/stretchr/testify/mock" ) -var goClientFeatureFlagsRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, grammar.MatcherTypeInSplitTreatment, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} -var goClientRuleBasedSegmentRules = []string{grammar.MatcherTypeAllKeys, grammar.MatcherTypeInSegment, grammar.MatcherTypeWhitelist, grammar.MatcherTypeEqualTo, grammar.MatcherTypeGreaterThanOrEqualTo, grammar.MatcherTypeLessThanOrEqualTo, grammar.MatcherTypeBetween, - grammar.MatcherTypeEqualToSet, grammar.MatcherTypePartOfSet, grammar.MatcherTypeContainsAllOfSet, grammar.MatcherTypeContainsAnyOfSet, grammar.MatcherTypeStartsWith, grammar.MatcherTypeEndsWith, grammar.MatcherTypeContainsString, - grammar.MatcherTypeEqualToBoolean, grammar.MatcherTypeMatchesString, grammar.MatcherEqualToSemver, grammar.MatcherTypeGreaterThanOrEqualToSemver, grammar.MatcherTypeLessThanOrEqualToSemver, grammar.MatcherTypeBetweenSemver, grammar.MatcherTypeInListSemver, - grammar.MatcherTypeInRuleBasedSegment} +var goClientFeatureFlagsRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, constants.MatcherTypeInSplitTreatment, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} +var goClientRuleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.MatcherTypeInSegment, constants.MatcherTypeWhitelist, constants.MatcherTypeEqualTo, constants.MatcherTypeGreaterThanOrEqualTo, constants.MatcherTypeLessThanOrEqualTo, constants.MatcherTypeBetween, + constants.MatcherTypeEqualToSet, constants.MatcherTypePartOfSet, constants.MatcherTypeContainsAllOfSet, constants.MatcherTypeContainsAnyOfSet, constants.MatcherTypeStartsWith, constants.MatcherTypeEndsWith, constants.MatcherTypeContainsString, + constants.MatcherTypeEqualToBoolean, constants.MatcherTypeMatchesString, constants.MatcherEqualToSemver, constants.MatcherTypeGreaterThanOrEqualToSemver, constants.MatcherTypeLessThanOrEqualToSemver, constants.MatcherTypeBetweenSemver, constants.MatcherTypeInListSemver, + constants.MatcherTypeInRuleBasedSegment} func TestSplitSyncTask(t *testing.T) { mockedSplit1 := dtos.SplitDTO{Name: "split1", Killed: false, Status: "ACTIVE", TrafficTypeName: "one"} From 2736845caaa257265a0390e8c5d312302907c68b Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 20 Oct 2025 15:52:16 -0300 Subject: [PATCH 33/39] Updated conditions --- storage/inmemory/mutexmap/rulebasedsegment.go | 4 ++-- storage/inmemory/mutexmap/splits.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index cee1d095..48e39f02 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -96,7 +96,7 @@ func (r *RuleBasedSegmentsStorageImpl) Segments() *set.ThreadUnsafeSet { for _, ruleBased := range r.data { for _, condition := range ruleBased.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType != constants.MatcherTypeInRuleBasedSegment { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == constants.MatcherTypeInSegment { segments.Add(matcher.UserDefinedSegment.SegmentName) } } @@ -119,7 +119,7 @@ func (r *RuleBasedSegmentsStorageImpl) LargeSegments() *set.ThreadUnsafeSet { for _, condition := range ruleBased.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { if matcher.UserDefinedLargeSegment != nil { - largeSegments.Add(matcher.UserDefinedSegment.SegmentName) + largeSegments.Add(matcher.UserDefinedLargeSegment.LargeSegmentName) } } } diff --git a/storage/inmemory/mutexmap/splits.go b/storage/inmemory/mutexmap/splits.go index ac45852f..9905a0b4 100644 --- a/storage/inmemory/mutexmap/splits.go +++ b/storage/inmemory/mutexmap/splits.go @@ -198,7 +198,7 @@ func (m *MMSplitStorage) SegmentNames() *set.ThreadUnsafeSet { for _, split := range m.data { for _, condition := range split.Conditions { for _, matcher := range condition.MatcherGroup.Matchers { - if matcher.UserDefinedSegment != nil && matcher.MatcherType != constants.MatcherTypeInRuleBasedSegment { + if matcher.UserDefinedSegment != nil && matcher.MatcherType == constants.MatcherTypeInSegment { segments.Add(matcher.UserDefinedSegment.SegmentName) } From 3f87bfc878c09ba59ce078cbd2e020ab336f2b6d Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 20 Oct 2025 15:58:12 -0300 Subject: [PATCH 34/39] fixed test --- synchronizer/worker/split/split_test.go | 27 +++++++------------------ 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 0504736b..8c4702df 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -811,7 +811,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdate(t *testing.T) { func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { - t.Run("Rule-based segment change number higher than current", func(t *testing.T) { + t.Run("Rule-based segment pcn matches", func(t *testing.T) { ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} splitMockStorage := &mocks.SplitStorageMock{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} @@ -828,10 +828,9 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) - changeNumber := int64(300) ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ Name: "test-segment", - ChangeNumber: changeNumber, + ChangeNumber: int64(300), Conditions: []dtos.RuleBasedConditionDTO{ { ConditionType: "WHITELIST", @@ -841,29 +840,17 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { }, }, } - response := &dtos.FFResponseV13{ - SplitChanges: dtos.SplitChangesDTO{ - FeatureFlags: dtos.FeatureFlagsDTO{ - Since: 3, - Till: 3, - }, - }, - } - pvChangeNumber := int64(100) + pvChangeNumber := int64(200) baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") - baseUpdate := dtos.NewBaseUpdate(baseMessage, changeNumber) + baseUpdate := dtos.NewBaseUpdate(baseMessage, 300) ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, &pvChangeNumber, ruleBasedSegment) - ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200)).Times(3) - splitMockStorage.On("ChangeNumber").Return(int64(200)).Twice() - ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{*ruleBasedSegment}, []dtos.RuleBasedSegmentDTO{}, changeNumber).Return().Once() - splitMockFetcher.On("Fetch", mock.Anything).Return(response, nil).Once() - splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(3)).Once() - appMonitorMock.On("NotifyEvent", mock.Anything).Once() + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200), nil).Times(1) + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{*ruleBasedSegment}, []dtos.RuleBasedSegmentDTO{}, int64(300)).Return().Once() result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) assert.Nil(t, err) assert.False(t, result.RequiresFetch) - assert.Equal(t, changeNumber, result.NewRBChangeNumber) + assert.Equal(t, int64(300), result.NewRBChangeNumber) splitMockFetcher.AssertExpectations(t) splitMockStorage.AssertExpectations(t) From 6dbf5625bf5ec82fc567889d71a1d61cf45b0854 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 20 Oct 2025 16:05:08 -0300 Subject: [PATCH 35/39] added pcn not cn --- synchronizer/worker/split/split_test.go | 68 +++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index 8c4702df..da28a086 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -816,11 +816,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { splitMockStorage := &mocks.SplitStorageMock{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} - telemetryMockStorage := mocks.MockTelemetryStorage{ - RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, - RecordSuccessfulSyncCall: func(resource int, timestamp time.Time) {}, - RecordSyncErrorCall: func(resource, status int) {}, - } + telemetryMockStorage := mocks.MockTelemetryStorage{} appMonitorMock := &hcMock.ApplicationMonitorMock{} largeSegmentStorage := &mocks.MockLargeSegmentStorage{} @@ -857,6 +853,68 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { ruleBasedSegmentMockStorage.AssertExpectations(t) appMonitorMock.AssertExpectations(t) }) + + t.Run("Rule-based segment pcn does not match", func(t *testing.T) { + ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} + splitMockStorage := &mocks.SplitStorageMock{} + splitMockStorage.On("ChangeNumber").Return(int64(200), nil).Times(2) + splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(300)).Return().Once() + splitMockFetcher := &fetcherMock.MockSplitFetcher{} + splitMockFetcher.On("Fetch", mock.Anything).Return(&dtos.FFResponseV13{ + SplitChanges: dtos.SplitChangesDTO{ + FeatureFlags: dtos.FeatureFlagsDTO{ + Splits: []dtos.SplitDTO{}, + Since: 300, + Till: 300, + }, + RuleBasedSegments: dtos.RuleBasedSegmentsDTO{ + RuleBasedSegments: []dtos.RuleBasedSegmentDTO{}, + Since: 300, + Till: 300, + }, + }, + }, nil).Once() + + telemetryMockStorage := mocks.MockTelemetryStorage{ + RecordSyncLatencyCall: func(resource int, latency time.Duration) {}, + RecordSuccessfulSyncCall: func(resource int, timestamp time.Time) {}, + RecordSyncErrorCall: func(resource, status int) {}, + } + appMonitorMock := &hcMock.ApplicationMonitorMock{} + appMonitorMock.On("NotifyEvent", mock.Anything).Return().Once() + largeSegmentStorage := &mocks.MockLargeSegmentStorage{} + ruleBuilder := grammar.NewRuleBuilder(nil, ruleBasedSegmentMockStorage, largeSegmentStorage, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logging.NewLogger(&logging.LoggerOptions{}), nil) + + splitUpdater := NewSplitUpdater(splitMockStorage, ruleBasedSegmentMockStorage, splitMockFetcher, logging.NewLogger(&logging.LoggerOptions{}), telemetryMockStorage, appMonitorMock, flagsets.NewFlagSetFilter(nil), ruleBuilder, false, specs.FLAG_V1_3) + + ruleBasedSegment := &dtos.RuleBasedSegmentDTO{ + Name: "test-segment", + ChangeNumber: int64(300), + Conditions: []dtos.RuleBasedConditionDTO{ + { + ConditionType: "WHITELIST", + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{}, + }, + }, + }, + } + pvChangeNumber := int64(100) + baseMessage := dtos.NewBaseMessage(time.Now().Unix(), "test-channel") + baseUpdate := dtos.NewBaseUpdate(baseMessage, 300) + ffChange := *dtos.NewRuleBasedSegmentChangeUpdate(baseUpdate, &pvChangeNumber, ruleBasedSegment) + + ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(200), nil).Times(3) + ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(300)).Return().Once() + result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) + assert.Nil(t, err) + assert.True(t, result.RequiresFetch) + + splitMockFetcher.AssertExpectations(t) + splitMockStorage.AssertExpectations(t) + ruleBasedSegmentMockStorage.AssertExpectations(t) + appMonitorMock.AssertExpectations(t) + }) } func TestProcessMatchers(t *testing.T) { From 6c57997eaa8cd31278df92c3b080d058d80bc6c1 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 20 Oct 2025 16:24:24 -0300 Subject: [PATCH 36/39] fixed tests due lack o matcher type --- .../mutexmap/rulebasedsegment_test.go | 28 +++++++++++++++++-- synchronizer/worker/segment/segment_test.go | 4 +++ synchronizer/worker/split/split_test.go | 10 +++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/storage/inmemory/mutexmap/rulebasedsegment_test.go b/storage/inmemory/mutexmap/rulebasedsegment_test.go index cd5d0811..7d4cb6b9 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment_test.go +++ b/storage/inmemory/mutexmap/rulebasedsegment_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/stretchr/testify/assert" ) @@ -29,10 +30,16 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, }, + { + MatcherGroup: dtos.MatcherGroupDTO{ + Matchers: []dtos.MatcherDTO{ + {UserDefinedLargeSegment: &dtos.UserDefinedLargeSegmentMatcherDataDTO{LargeSegmentName: "ls1"}, MatcherType: constants.MatcherTypeInLargeSegment}}}, + }, }, Excluded: dtos.ExcludedDTO{ Segments: []dtos.ExcludedSegmentDTO{ @@ -40,6 +47,14 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { Name: "excluded1", Type: dtos.TypeStandard, }, + { + Name: "excluded2", + Type: dtos.TypeRuleBased, + }, + { + Name: "excluded3", + Type: dtos.TypeLarge, + }, }, }, } @@ -54,6 +69,7 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment2", }, + MatcherType: constants.MatcherTypeInRuleBasedSegment, }, }, }, @@ -74,12 +90,13 @@ func TestRuleBasedSegmentsStorage(t *testing.T) { // Test GetSegments segments := storage.Segments() - // Print segments for debugging - t.Logf("Segments in set: %v", segments.List()) assert.True(t, segments.Has("segment1"), "segment1 should be in segments") - assert.True(t, segments.Has("segment2"), "segment2 should be in segments") assert.True(t, segments.Has("excluded1"), "excluded1 should be in segments") + ls := storage.LargeSegments() + assert.True(t, ls.Has("excluded3"), "excluded3 should be in large segments") + assert.True(t, ls.Has("ls1"), "ls1 should be in large segments") + // Test Contains assert.True(t, storage.Contains([]string{"rule1", "rule2"}), "should contain rule1 and rule2") assert.True(t, storage.Contains([]string{"rule1"}), "should contain rule1") @@ -113,6 +130,7 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -134,6 +152,7 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment2", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -183,6 +202,7 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment3", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -200,6 +220,7 @@ func TestRuleBasedSegmentsStorageReplaceAll(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment4", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -278,6 +299,7 @@ func TestRuleBasedSegmentsStorageConcurrent(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, diff --git a/synchronizer/worker/segment/segment_test.go b/synchronizer/worker/segment/segment_test.go index 83f75791..007f5f80 100644 --- a/synchronizer/worker/segment/segment_test.go +++ b/synchronizer/worker/segment/segment_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/splitio/go-split-commons/v7/dtos" + "github.com/splitio/go-split-commons/v7/engine/grammar/constants" "github.com/splitio/go-split-commons/v7/flagsets" "github.com/splitio/go-split-commons/v7/healthcheck/application" hcMock "github.com/splitio/go-split-commons/v7/healthcheck/mocks" @@ -225,6 +226,7 @@ func TestSegmentSyncUpdate(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -322,6 +324,7 @@ func TestSegmentSyncProcess(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment1", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, @@ -341,6 +344,7 @@ func TestSegmentSyncProcess(t *testing.T) { UserDefinedSegment: &dtos.UserDefinedSegmentMatcherDataDTO{ SegmentName: "segment2", }, + MatcherType: constants.MatcherTypeInSegment, }, }, }, diff --git a/synchronizer/worker/split/split_test.go b/synchronizer/worker/split/split_test.go index da28a086..df28875c 100644 --- a/synchronizer/worker/split/split_test.go +++ b/synchronizer/worker/split/split_test.go @@ -908,7 +908,7 @@ func TestSynchronizeFeatureFlagsRuleBasedUpdateSecond(t *testing.T) { ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(300)).Return().Once() result, err := splitUpdater.SynchronizeFeatureFlags(&ffChange) assert.Nil(t, err) - assert.True(t, result.RequiresFetch) + assert.False(t, result.RequiresFetch) splitMockFetcher.AssertExpectations(t) splitMockStorage.AssertExpectations(t) @@ -1057,10 +1057,10 @@ func TestSplitProxyDowngrade(t *testing.T) { splitMockStorage := &mocks.SplitStorageMock{} splitMockStorage.On("ChangeNumber").Return(int64(3), nil).Times(2) - splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once() + splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once().Return(nil) ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) - ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once() + ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once().Return(nil) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} splitMockFetcher.On("Fetch", service.MakeFlagRequestParams().WithSpecVersion(common.StringRef(specs.FLAG_V1_3)).WithChangeNumber(-1).WithChangeNumberRB(-1)).Return(response, nil).Once() @@ -1125,11 +1125,11 @@ func TestSplitProxyDowngrade(t *testing.T) { splitMockStorage := &mocks.SplitStorageMock{} splitMockStorage.On("ChangeNumber").Return(int64(3), nil).Times(2) - splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once() + splitMockStorage.On("ReplaceAll", []dtos.SplitDTO{mockedSplit1}, int64(3)).Once().Return(nil) splitMockStorage.On("Update", []dtos.SplitDTO{}, []dtos.SplitDTO{}, int64(3)).Once() ruleBasedSegmentMockStorage := &mocks.MockRuleBasedSegmentStorage{} ruleBasedSegmentMockStorage.On("ChangeNumber").Return(int64(3)).Times(2) - ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once() + ruleBasedSegmentMockStorage.On("ReplaceAll", []dtos.RuleBasedSegmentDTO{mockedRuleBased1}, int64(3)).Once().Return(nil) ruleBasedSegmentMockStorage.On("Update", []dtos.RuleBasedSegmentDTO{}, []dtos.RuleBasedSegmentDTO{}, int64(3)).Once().Return(3) largeSegmentStorage := &mocks.MockLargeSegmentStorage{} splitMockFetcher := &fetcherMock.MockSplitFetcher{} From 1d8038d22be6f2bb3704ce3a138a8388491bf1cc Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Mon, 20 Oct 2025 16:34:47 -0300 Subject: [PATCH 37/39] small changes --- synchronizer/worker/split/split.go | 35 +++++++++--------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/synchronizer/worker/split/split.go b/synchronizer/worker/split/split.go index 765ec90c..0744db8e 100644 --- a/synchronizer/worker/split/split.go +++ b/synchronizer/worker/split/split.go @@ -352,25 +352,12 @@ func appendLargeSegmentNames(dst []string, featureFlags []dtos.SplitDTO) []strin return dst } -func addIfNotExists(dst []string, seen map[string]struct{}, name string) []string { - if _, exists := seen[name]; !exists { - seen[name] = struct{}{} - dst = append(dst, name) - } - return dst -} - func appendRuleBasedSegmentNamesReferenced(dst []string, featureFlags []dtos.SplitDTO) []string { - seen := make(map[string]struct{}) - for _, name := range dst { - seen[name] = struct{}{} - } - for _, split := range featureFlags { for _, cond := range split.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == constants.MatcherTypeInRuleBasedSegment && matcher.UserDefinedSegment != nil { - dst = addIfNotExists(dst, seen, matcher.UserDefinedSegment.SegmentName) + dst = append(dst, matcher.UserDefinedSegment.SegmentName) } } } @@ -445,19 +432,18 @@ func (s *UpdaterImpl) processFFChange(ffChange dtos.SplitChangeUpdate) *UpdateRe } func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) []string { - seen := make(map[string]struct{}) segments := make([]string, 0) for _, segment := range ruleBasedSegment.Excluded.Segments { if segment.Type == dtos.TypeStandard { - segments = addIfNotExists(segments, seen, segment.Name) + segments = append(segments, segment.Name) } } for _, cond := range ruleBasedSegment.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == constants.MatcherTypeInSegment && matcher.UserDefinedSegment != nil { - segments = addIfNotExists(segments, seen, matcher.UserDefinedSegment.SegmentName) + segments = append(segments, matcher.UserDefinedSegment.SegmentName) } } } @@ -466,19 +452,18 @@ func (s *UpdaterImpl) getSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) [] } func (s *UpdaterImpl) getLargeSegments(ruleBasedSegment *dtos.RuleBasedSegmentDTO) []string { - seen := make(map[string]struct{}) largeSegments := make([]string, 0) for _, segment := range ruleBasedSegment.Excluded.Segments { if segment.Type == TypeLargeSegment { - largeSegments = addIfNotExists(largeSegments, seen, segment.Name) + largeSegments = append(largeSegments, segment.Name) } } for _, cond := range ruleBasedSegment.Conditions { for _, matcher := range cond.MatcherGroup.Matchers { if matcher.MatcherType == constants.MatcherTypeInLargeSegment { - largeSegments = addIfNotExists(largeSegments, seen, matcher.UserDefinedSegment.SegmentName) + largeSegments = append(largeSegments, matcher.UserDefinedSegment.SegmentName) } } } @@ -531,15 +516,15 @@ func (s *UpdaterImpl) processRuleBasedChangeUpdate(ruleBasedChange dtos.SplitCha ruleBasedSegments = append(ruleBasedSegments, *ruleBasedChange.RuleBasedSegment()) toRemove, toAdd := s.processRuleBasedSegmentChanges(ruleBasedSegments) segments := s.getSegmentsFromRuleBasedSegments(ruleBasedSegments) - //large segments + largeSegments := s.getLargeSegmentsFromRuleBasedSegments(ruleBasedSegments) s.ruleBasedSegmentStorage.Update(toAdd, toRemove, ruleBasedChange.BaseUpdate.ChangeNumber()) return &UpdateResult{ UpdatedRuleBasedSegments: []string{ruleBasedChange.RuleBasedSegment().Name}, - ReferencedSegments: segments, - //large segment referenced - NewRBChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), - RequiresFetch: false, + ReferencedSegments: common.DedupeStringSlice(segments), + ReferencedLargeSegments: common.DedupeStringSlice(largeSegments), + NewRBChangeNumber: ruleBasedChange.BaseUpdate.ChangeNumber(), + RequiresFetch: false, } } s.logger.Debug("the rule-based segment was nil or the previous change number wasn't equal to the rule-based segment storage's change number") From 0c5ee482203be90395725b876fad28503204c592 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 20 Oct 2025 18:12:10 -0300 Subject: [PATCH 38/39] Updated ReplaceAll --- storage/inmemory/mutexmap/rulebasedsegment.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/inmemory/mutexmap/rulebasedsegment.go b/storage/inmemory/mutexmap/rulebasedsegment.go index 48e39f02..325cf75d 100644 --- a/storage/inmemory/mutexmap/rulebasedsegment.go +++ b/storage/inmemory/mutexmap/rulebasedsegment.go @@ -168,7 +168,7 @@ func (r *RuleBasedSegmentsStorageImpl) GetRuleBasedSegmentByName(name string) (* return nil, fmt.Errorf("rule-based segment %s not found in storage", name) } -func (r *RuleBasedSegmentsStorageImpl) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) { +func (r *RuleBasedSegmentsStorageImpl) ReplaceAll(toAdd []dtos.RuleBasedSegmentDTO, changeNumber int64) error { // Get all current splits under read lock r.mutex.RLock() toRemove := make([]dtos.RuleBasedSegmentDTO, 0) @@ -181,4 +181,5 @@ func (r *RuleBasedSegmentsStorageImpl) ReplaceAll(toAdd []dtos.RuleBasedSegmentD r.mutex.Lock() defer r.mutex.Unlock() r.update(toAdd, toRemove, changeNumber) + return nil } From f68a272b4cc5b420f3ea1b7b6232d05059e70b93 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 21 Oct 2025 11:26:11 -0300 Subject: [PATCH 39/39] Updated ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b68c837c..007e3a8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: fetch-depth: 0 - name: Set up Go version - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '1.21'