Skip to content

Commit

Permalink
merge with master
Browse files Browse the repository at this point in the history
  • Loading branch information
mredolatti committed Dec 6, 2023
2 parents cf3da63 + 1cd638d commit 6daf2c0
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 52 deletions.
7 changes: 7 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
- Updated Syncrhonizer to properly handle flagsets in redis.
- Added configuration options to specify which flagsets to use as a filter when downloading flag definitions. Please refer to our docs to learn more

5.4.2 (Nov 7, 2023)
- Updated docker images for vulnerability fixes.
- Updated dependencies for vulnerability fixes.

5.4.1 (Oct 31, 2023)
- Fix issue in split proxy where removed segment keys would be returned as active at startup

5.4.0 (July 18, 2023)
- Improved streaming architecture implementation to apply feature flag updates from the notification received which is now enhanced, improving efficiency and reliability of the whole update system.
- Fixed possible edge case issue where deleting a feature flag doesn’t propagate immediately.
Expand Down
12 changes: 8 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ test: $(sources) go.sum
test_coverage: $(sources) go.sum
$(GO) test -v -cover -coverprofile=coverage.out $(ARGS) ./...

## display unit test coverage derived from last test run (use `make test display-coverage` for up-to-date results)
display-coverage: coverage.out
go tool cover -html=coverage.out

## Generate binaires for all architectures, ready to upload for distribution (with and without version)
release_assets: \
$(BUILD)/synchronizer \
Expand Down Expand Up @@ -96,10 +100,6 @@ images_release: # entrypoints
@echo "$(DOCKER) push splitsoftware/split-proxy:$(version)"
@echo "$(DOCKER) push splitsoftware/split-proxy:latest"

## display unit test coverage derived from last test run (use `make test display-coverage` for up-to-date results)
display-coverage: coverage.out
go tool cover -html=coverage.out

# --------------------------------------------------------------------------
#
# Internal targets:
Expand Down Expand Up @@ -172,6 +172,10 @@ table_header:
@echo "| **Command line option** | **JSON option** | **Environment variable** (container-only) | **Description** |"
@echo "| --- | --- | --- | --- |"

coverage.out: test_coverage



# Help target borrowed from: https://docs.cloudposse.com/reference/best-practices/make-best-practices/
## This help screen
help:
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -143,8 +143,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down
2 changes: 1 addition & 1 deletion splitio/commitversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ This file is created automatically, please do not edit
*/

// CommitVersion is the version of the last commit previous to release
const CommitVersion = "fccb322"
const CommitVersion = "cf3da63"
28 changes: 28 additions & 0 deletions splitio/proxy/storage/persistent/mocks/segment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package mocks

import (
"github.com/splitio/go-toolkit/v5/datastructures/set"
"github.com/splitio/split-synchronizer/v5/splitio/proxy/storage/persistent"
"github.com/stretchr/testify/mock"
)

type SegmentChangesCollectionMock struct {
mock.Mock
}

func (s *SegmentChangesCollectionMock) Update(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, cn int64) error {
return s.Called(name, toAdd, toRemove, cn).Error(0)
}

func (s *SegmentChangesCollectionMock) Fetch(name string) (*persistent.SegmentChangesItem, error) {
args := s.Called(name)
return args.Get(0).(*persistent.SegmentChangesItem), args.Error(1)
}

func (s *SegmentChangesCollectionMock) ChangeNumber(segment string) int64 {
return s.Called(segment).Get(0).(int64)
}

func (s *SegmentChangesCollectionMock) SetChangeNumber(segment string, cn int64) {
s.Called(segment, cn)
}
59 changes: 27 additions & 32 deletions splitio/proxy/storage/persistent/segments.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,32 @@ type SegmentChangesItem struct {
Keys map[string]SegmentKey
}

// SegmentChangesCollection represents a collection of SplitChangesItem
type SegmentChangesCollection struct {
type SegmentChangesCollection interface {
Update(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, cn int64) error
Fetch(name string) (*SegmentChangesItem, error)
ChangeNumber(segment string) int64
SetChangeNumber(segment string, cn int64)
}

// SegmentChangesCollectionImpl represents a collection of SplitChangesItem
type SegmentChangesCollectionImpl struct {
collection CollectionWrapper
segmentsTill map[string]int64
logger logging.LoggerInterface
mutex sync.RWMutex
}

// NewSegmentChangesCollection returns an instance of SegmentChangesCollection
func NewSegmentChangesCollection(db DBWrapper, logger logging.LoggerInterface) *SegmentChangesCollection {
return &SegmentChangesCollection{
func NewSegmentChangesCollection(db DBWrapper, logger logging.LoggerInterface) *SegmentChangesCollectionImpl {
return &SegmentChangesCollectionImpl{
collection: &BoltDBCollectionWrapper{db: db, name: segmentChangesCollectionName, logger: logger},
segmentsTill: make(map[string]int64, 0),
logger: logger,
}
}

// Update persists a segmentChanges update
func (c *SegmentChangesCollection) Update(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, cn int64) error {
func (c *SegmentChangesCollectionImpl) Update(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, cn int64) error {
c.mutex.Lock()
defer c.mutex.Unlock()

Expand All @@ -63,17 +70,10 @@ func (c *SegmentChangesCollection) Update(name string, toAdd *set.ThreadUnsafeSe
continue
}
c.logger.Debug("Removing", strKey, "from", name)
if _, exists := segmentItem.Keys[strKey]; exists {
itemAux := segmentItem.Keys[strKey]
itemAux.Removed = true
itemAux.ChangeNumber = cn
segmentItem.Keys[strKey] = itemAux
} else {
segmentItem.Keys[strKey] = SegmentKey{
Name: strKey,
Removed: true,
ChangeNumber: cn,
}
segmentItem.Keys[strKey] = SegmentKey{
Name: strKey,
Removed: true,
ChangeNumber: cn,
}

}
Expand All @@ -85,17 +85,10 @@ func (c *SegmentChangesCollection) Update(name string, toAdd *set.ThreadUnsafeSe
continue
}
c.logger.Debug("Adding", strKey, "in", name)
if _, exists := segmentItem.Keys[strKey]; exists {
itemAux := segmentItem.Keys[strKey]
itemAux.Removed = false
itemAux.ChangeNumber = cn
segmentItem.Keys[strKey] = itemAux
} else {
segmentItem.Keys[strKey] = SegmentKey{
Name: strKey,
Removed: false,
ChangeNumber: cn,
}
segmentItem.Keys[strKey] = SegmentKey{
Name: strKey,
Removed: false,
ChangeNumber: cn,
}
}

Expand All @@ -108,13 +101,13 @@ func (c *SegmentChangesCollection) Update(name string, toAdd *set.ThreadUnsafeSe
}

// Fetch return a SegmentChangesItem
func (c *SegmentChangesCollection) Fetch(name string) (*SegmentChangesItem, error) {
func (c *SegmentChangesCollectionImpl) Fetch(name string) (*SegmentChangesItem, error) {
c.mutex.RLock()
defer c.mutex.RUnlock()
return c.fetch(name)
}

func (c *SegmentChangesCollection) fetch(name string) (*SegmentChangesItem, error) {
func (c *SegmentChangesCollectionImpl) fetch(name string) (*SegmentChangesItem, error) {
item, err := c.collection.FetchBy([]byte(name))
if err != nil {
return nil, err
Expand All @@ -133,7 +126,7 @@ func (c *SegmentChangesCollection) fetch(name string) (*SegmentChangesItem, erro
}

// FetchAll return a list of SegmentChangesItem
func (c *SegmentChangesCollection) FetchAll() ([]SegmentChangesItem, error) {
func (c *SegmentChangesCollectionImpl) FetchAll() ([]SegmentChangesItem, error) {
c.mutex.RLock()
defer c.mutex.RUnlock()
items, err := c.collection.FetchAll()
Expand Down Expand Up @@ -163,7 +156,7 @@ func (c *SegmentChangesCollection) FetchAll() ([]SegmentChangesItem, error) {
}

// ChangeNumber returns changeNumber
func (c *SegmentChangesCollection) ChangeNumber(segment string) int64 {
func (c *SegmentChangesCollectionImpl) ChangeNumber(segment string) int64 {
c.mutex.RLock()
defer c.mutex.RUnlock()
value, exists := c.segmentsTill[segment]
Expand All @@ -174,8 +167,10 @@ func (c *SegmentChangesCollection) ChangeNumber(segment string) int64 {
}

// SetChangeNumber returns changeNumber
func (c *SegmentChangesCollection) SetChangeNumber(segment string, cn int64) {
func (c *SegmentChangesCollectionImpl) SetChangeNumber(segment string, cn int64) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.segmentsTill[segment] = cn
}

var _ SegmentChangesCollection = (*SegmentChangesCollectionImpl)(nil)
16 changes: 10 additions & 6 deletions splitio/proxy/storage/segments.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type ProxySegmentStorage interface {
type ProxySegmentStorageImpl struct {
logger logging.LoggerInterface
nameCountCache *observability.ActiveSegmentTracker
db *persistent.SegmentChangesCollection
db persistent.SegmentChangesCollection
mysegments optimized.MySegmentsCache
}

Expand Down Expand Up @@ -68,21 +68,25 @@ func (s *ProxySegmentStorageImpl) ChangesSince(name string, since int64) (*dtos.

// Horrible loop borrowed from sdk-api
for _, skey := range item.Keys {

if skey.ChangeNumber <= since { // if the key was updated in a previous/current CN, we don't need to return it
continue
}

if skey.Removed && since < 0 {
// removed keys should not be returned on initialization payloads
continue
}

// Add the key to the corresponding list
if skey.Removed && since > 0 {
if skey.Removed {
removed = append(removed, skey.Name)
} else {
added = append(added, skey.Name)
}

// Update the till to be returned if necessary
if since > 0 && skey.ChangeNumber > till {
till = skey.ChangeNumber
} else if !skey.Removed && skey.ChangeNumber > till {
if skey.ChangeNumber > till {
till = skey.ChangeNumber
}
}
Expand Down Expand Up @@ -177,7 +181,7 @@ func (s *ProxySegmentStorageImpl) NamesAndCount() map[string]int {
func populateCachesFromDisk(
dst optimized.MySegmentsCache,
names *observability.ActiveSegmentTracker,
src *persistent.SegmentChangesCollection,
src *persistent.SegmentChangesCollectionImpl,
logger logging.LoggerInterface,
) {
all, err := src.FetchAll()
Expand Down
75 changes: 75 additions & 0 deletions splitio/proxy/storage/segments_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package storage

import (
"testing"

"github.com/splitio/go-toolkit/v5/logging"
"github.com/splitio/split-synchronizer/v5/splitio/proxy/storage/optimized"
"github.com/splitio/split-synchronizer/v5/splitio/proxy/storage/persistent"
"github.com/splitio/split-synchronizer/v5/splitio/proxy/storage/persistent/mocks"
"github.com/stretchr/testify/assert"
)

func TestSegmentStorage(t *testing.T) {

psm := &mocks.SegmentChangesCollectionMock{}
psm.On("Fetch", "some").Return(&persistent.SegmentChangesItem{
Name: "some",
Keys: map[string]persistent.SegmentKey{
"k1": {Name: "k1", ChangeNumber: 1, Removed: false},
"k2": {Name: "k2", ChangeNumber: 1, Removed: true},
"k3": {Name: "k3", ChangeNumber: 2, Removed: false},
"k4": {Name: "k4", ChangeNumber: 2, Removed: true},
"k5": {Name: "k5", ChangeNumber: 3, Removed: false},
"k6": {Name: "k6", ChangeNumber: 3, Removed: true},
"k7": {Name: "k7", ChangeNumber: 4, Removed: false},
},
}, nil)

ss := ProxySegmentStorageImpl{
logger: logging.NewLogger(nil),
db: psm,
mysegments: optimized.NewMySegmentsCache(),
}

changes, err := ss.ChangesSince("some", -1)
assert.Nil(t, err)
assert.Equal(t, "some", changes.Name)
assert.ElementsMatch(t, []string{"k1", "k3", "k5", "k7"}, changes.Added)
assert.ElementsMatch(t, []string{}, changes.Removed)
assert.Equal(t, int64(-1), changes.Since)
assert.Equal(t, int64(4), changes.Till)

changes, err = ss.ChangesSince("some", 1)
assert.Nil(t, err)
assert.Equal(t, "some", changes.Name)
assert.ElementsMatch(t, []string{"k3", "k5", "k7"}, changes.Added)
assert.ElementsMatch(t, []string{"k4", "k6"}, changes.Removed)
assert.Equal(t, int64(1), changes.Since)
assert.Equal(t, int64(4), changes.Till)

changes, err = ss.ChangesSince("some", 2)
assert.Nil(t, err)
assert.Equal(t, "some", changes.Name)
assert.ElementsMatch(t, []string{"k5", "k7"}, changes.Added)
assert.ElementsMatch(t, []string{"k6"}, changes.Removed)
assert.Equal(t, int64(2), changes.Since)
assert.Equal(t, int64(4), changes.Till)

changes, err = ss.ChangesSince("some", 3)
assert.Nil(t, err)
assert.Equal(t, "some", changes.Name)
assert.ElementsMatch(t, []string{"k7"}, changes.Added)
assert.ElementsMatch(t, []string{}, changes.Removed)
assert.Equal(t, int64(3), changes.Since)
assert.Equal(t, int64(4), changes.Till)

changes, err = ss.ChangesSince("some", 4)
assert.Nil(t, err)
assert.Equal(t, "some", changes.Name)
assert.ElementsMatch(t, []string{}, changes.Added)
assert.ElementsMatch(t, []string{}, changes.Removed)
assert.Equal(t, int64(4), changes.Since)
assert.Equal(t, int64(4), changes.Till)

}

0 comments on commit 6daf2c0

Please sign in to comment.