Skip to content

Commit

Permalink
Adding storage and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sanzmauro committed Oct 22, 2024
1 parent 319e79e commit 4e310d3
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
82 changes: 82 additions & 0 deletions splitio/proxy/storage/large_segments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package storage

import (
"sort"
"sync"

"github.com/splitio/go-toolkit/v5/logging"
)

type LargeSegmentsStorage interface {
Count() int
SegmentsForUser(key string) []string
Update(lsName string, userKeys []string)
}

// MySegmentsCacheImpl implements the MySegmentsCache interface
type LargeSegmentsStorageImpl struct {
largeSegments map[string][]string
mutex *sync.RWMutex
logger logging.LoggerInterface
}

// NewMySegmentsCache constructs a new MySegments cache
func NewLargeSegmentsStorage(logger logging.LoggerInterface) *LargeSegmentsStorageImpl {
return &LargeSegmentsStorageImpl{
largeSegments: make(map[string][]string),
mutex: &sync.RWMutex{},
logger: logger,
}
}

func (s *LargeSegmentsStorageImpl) Count() int {
s.mutex.RLock()
defer s.mutex.RUnlock()
return len(s.largeSegments)
}

func (s *LargeSegmentsStorageImpl) SegmentsForUser(key string) []string {
s.mutex.RLock()
defer s.mutex.RUnlock()

toReturn := make([]string, 0)
lsNames := s.names()

for _, name := range lsNames {
if s.exists(name, key) {
toReturn = append(toReturn, name)
}
}

return toReturn
}

func (s *LargeSegmentsStorageImpl) Update(lsName string, userKeys []string) {
s.mutex.Lock()
defer s.mutex.Unlock()

s.largeSegments[lsName] = userKeys
}

func (s *LargeSegmentsStorageImpl) names() []string {
toReturn := make([]string, 0, len(s.largeSegments))
for key := range s.largeSegments {
toReturn = append(toReturn, key)
}

return toReturn
}

func (s *LargeSegmentsStorageImpl) exists(lsName string, userKey string) bool {
data := s.largeSegments[lsName]
length := len(data)
if length == 0 {
return false
}

i := sort.Search(length, func(i int) bool {
return data[i] >= userKey
})

return i < len(data) && data[i] == userKey
}
56 changes: 56 additions & 0 deletions splitio/proxy/storage/large_segments_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package storage

import (
"sort"
"testing"

"github.com/google/uuid"
"github.com/splitio/go-toolkit/v5/logging"
"github.com/stretchr/testify/assert"
)

func sortedKeys(count int, shared *string) []string {
keys := make([]string, 0, count)
for i := 0; i < count; i++ {
keys = append(keys, uuid.New().String())
}

if shared != nil {
keys = append(keys, *shared)
}

sort.Strings(keys)
return keys
}

func TestLatgeSegmentStorage(t *testing.T) {
storage := NewLargeSegmentsStorage(logging.NewLogger(nil))

keys1 := sortedKeys(10000, nil)
storage.Update("ls_test_1", keys1)

sharedKey := &keys1[5000]
keys2 := sortedKeys(20000, sharedKey)
storage.Update("ls_test_2", keys2)

keys3 := sortedKeys(30000, sharedKey)
storage.Update("ls_test_3", keys3)

assert.Equal(t, 3, storage.Count())

result := storage.SegmentsForUser(*sharedKey)
sort.Strings(result)
assert.Equal(t, []string{"ls_test_1", "ls_test_2", "ls_test_3"}, result)

result = storage.SegmentsForUser(keys1[100])
assert.Equal(t, []string{"ls_test_1"}, result)

result = storage.SegmentsForUser(keys2[100])
assert.Equal(t, []string{"ls_test_2"}, result)

result = storage.SegmentsForUser(keys3[100])
assert.Equal(t, []string{"ls_test_3"}, result)

result = storage.SegmentsForUser("mauro-test")
assert.Equal(t, []string{}, result)
}

0 comments on commit 4e310d3

Please sign in to comment.