Skip to content

Commit

Permalink
Merge pull request #12 from splitio/feat/manager_calls
Browse files Browse the repository at this point in the history
add support for `getTreatment(s)WithConfig` & manager methods
  • Loading branch information
mredolatti authored Sep 19, 2023
2 parents 78f9c83 + 03375ea commit 1472745
Show file tree
Hide file tree
Showing 42 changed files with 1,728 additions and 633 deletions.
5 changes: 5 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
1.1.0 (Sep 19, 2023):
- Add support for Client/GetTreatment(s)WithConfig operations.
- Add support for Manager operations.
- Use bump default buffer sizes to 200k (linux default)

1.0.1 (Sep 5, 2023):
- Add support for .track
- Fixed issue where impressions could take too long to evict even with the queue full
Expand Down
46 changes: 43 additions & 3 deletions cmd/splitcli/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/json"
"fmt"
"os"
"strings"
Expand Down Expand Up @@ -80,10 +81,49 @@ func executeCall(c types.ClientInterface, a *conf.CliArgs) (string, error) {
}
return sb.String(), err
case "track":
return "", c.Track(a.Key, a.TrafficType, a.EventType, a.EventVal, nil)
case "treatmentWithConfig", "treatmentsWithConfig":
return "", fmt.Errorf("method '%s' is not yet implemented", a.Method)
return "", c.Track(a.Key, a.TrafficType, a.EventType, a.EventVal, nil)
case "treatment-with-config":
res, err := c.TreatmentWithConfig(a.Key, a.BucketingKey, a.Feature, a.Attributes)
return formatWithConfig(res.Treatment, res.Config), err
case "treatments-with-config":
res, err := c.TreatmentsWithConfig(a.Key, a.BucketingKey, a.Features, a.Attributes)
var sb strings.Builder
for _, result := range res {
s := formatWithConfig(result.Treatment, result.Config)
if sb.Len() == 0 { // first item doesn't require a leading ','
sb.WriteString(s)
} else {
sb.WriteString("," + s)
}
}
return sb.String(), err
case "split-names":
names, err := c.SplitNames()
return strings.Join(names, ","), err
case "split":
split, err := c.Split(a.Feature)
if err != nil {
return "", err
}
asJson, err := json.Marshal(split)
return string(asJson), err
case "splits":
splits, err := c.Splits()
fmt.Println(splits)
if err != nil {
return "", err
}
asJson, err := json.Marshal(splits)
return string(asJson), err
default:
return "", fmt.Errorf("unknwon method '%s'", a.Method)
}
}

func formatWithConfig(treatment string, config *string) string {
var emtpyCfg string = ""
if config == nil {
config = &emtpyCfg
}
return fmt.Sprintf("[%s -- %s]", treatment, *config)
}
24 changes: 24 additions & 0 deletions external/commons/mocks/evaluator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package mocks

import (
"github.com/splitio/go-client/v6/splitio/engine/evaluator"
"github.com/stretchr/testify/mock"
)

type EvaluatorMock struct {
mock.Mock
}

// EvaluateFeature implements evaluator.Interface
func (e *EvaluatorMock) EvaluateFeature(key string, bucketingKey *string, feature string, attributes map[string]interface{}) *evaluator.Result {
args := e.Called(key, bucketingKey, feature, attributes)
return args.Get(0).(*evaluator.Result)
}

// EvaluateFeatures implements evaluator.Interface
func (e *EvaluatorMock) EvaluateFeatures(key string, bucketingKey *string, features []string, attributes map[string]interface{}) evaluator.Results {
args := e.Called(key, bucketingKey, features, attributes)
return args.Get(0).(evaluator.Results)
}

var _ evaluator.Interface = (*EvaluatorMock)(nil)
25 changes: 25 additions & 0 deletions external/commons/mocks/impmanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mocks

import (
"github.com/splitio/go-split-commons/v4/dtos"
"github.com/splitio/go-split-commons/v4/provisional"
"github.com/stretchr/testify/mock"
)

type ImpressionManagerMock struct {
mock.Mock
}

// ProcessImpressions implements provisional.ImpressionManager
func (m *ImpressionManagerMock) ProcessImpressions(impressions []dtos.Impression) ([]dtos.Impression, []dtos.Impression) {
args := m.Called(impressions)
return args.Get(0).([]dtos.Impression), args.Get(1).([]dtos.Impression)
}

// ProcessSingle implements provisional.ImpressionManager
func (m *ImpressionManagerMock) ProcessSingle(impression *dtos.Impression) bool {
args := m.Called(impression)
return args.Bool(0)
}

var _ provisional.ImpressionManager = (*ImpressionManagerMock)(nil)
25 changes: 25 additions & 0 deletions external/commons/mocks/imprecorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package mocks

import (
"github.com/splitio/go-split-commons/v4/dtos"
"github.com/splitio/go-split-commons/v4/service"
"github.com/stretchr/testify/mock"
)

type ImpressionRecorderMock struct {
mock.Mock
}

// Record implements service.ImpressionsRecorder
func (m *ImpressionRecorderMock) Record(impressions []dtos.ImpressionsDTO, metadata dtos.Metadata, extraHeaders map[string]string) error {
args := m.Called(impressions, metadata, extraHeaders)
return args.Error(0)
}

// RecordImpressionsCount implements service.ImpressionsRecorder
func (m *ImpressionRecorderMock) RecordImpressionsCount(pf dtos.ImpressionsCountDTO, metadata dtos.Metadata) error {
args := m.Called(pf, metadata)
return args.Error(0)
}

var _ service.ImpressionsRecorder = (*ImpressionRecorderMock)(nil)
61 changes: 61 additions & 0 deletions external/commons/mocks/splitstorage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package mocks

import (
"github.com/splitio/go-split-commons/v4/dtos"
"github.com/splitio/go-split-commons/v4/storage"
"github.com/splitio/go-toolkit/v5/datastructures/set"
"github.com/stretchr/testify/mock"
)

type SplitStorageMock struct{ mock.Mock }

func (m *SplitStorageMock) All() []dtos.SplitDTO {
args := m.Called()
return args.Get(0).([]dtos.SplitDTO)
}

func (m *SplitStorageMock) ChangeNumber() (int64, error) {
args := m.Called()
return args.Get(0).(int64), args.Error(1)
}

func (m *SplitStorageMock) FetchMany(names []string) map[string]*dtos.SplitDTO {
args := m.Called(names)
return args.Get(0).(map[string]*dtos.SplitDTO)
}

func (m *SplitStorageMock) KillLocally(name string, defaultTreatment string, newCn int64) {
m.Called(name, defaultTreatment, newCn)
}

func (m *SplitStorageMock) SegmentNames() *set.ThreadUnsafeSet {
args := m.Called()
return args.Get(0).(*set.ThreadUnsafeSet)
}

func (m *SplitStorageMock) SetChangeNumber(changeNumber int64) error {
args := m.Called(changeNumber)
return args.Error(0)

}

func (m *SplitStorageMock) Split(splitName string) *dtos.SplitDTO {
args := m.Called(splitName)
return args.Get(0).(*dtos.SplitDTO)
}

func (m *SplitStorageMock) SplitNames() []string {
args := m.Called()
return args.Get(0).([]string)
}

func (m *SplitStorageMock) Update(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, newCN int64) {
m.Called()
}

func (m *SplitStorageMock) TrafficTypeExists(trafficType string) bool {
args := m.Called(trafficType)
return args.Bool(0)
}

var _ storage.SplitStorage = (*SplitStorageMock)(nil)
1 change: 1 addition & 0 deletions infra/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ accum=$(yq '.sdk.apikey = env(SPLITD_APIKEY) | .link.address = env(SPLITD_LINK_A
[ ! -z ${SPLITD_LINK_READ_TIMEOUT_MS+x} ] && accum=$(echo "${accum}" | yq '.link.readTimeoutMS = env(SPLITD_LINK_READ_TIMEOUT_MS)')
[ ! -z ${SPLITD_LINK_WRITE_TIMEOUT_MS+x} ] && accum=$(echo "${accum}" | yq '.link.writeTimeoutMS = env(SPLITD_LINK_WRITE_TIMEOUT_MS)')
[ ! -z ${SPLITD_LINK_ACCEPT_TIMEOUT_MS+x} ] && accum=$(echo "${accum}" | yq '.link.acceptTimeoutMS = env(SPLITD_LINK_ACCEPT_TIMEOUT_MS)')
[ ! -z ${SPLITD_LINK_BUFFER_SIZE+x} ] && accum=$(echo "${accum}" | yq '.link.bufferSize = env(SPLITD_LINK_BUFFER_SIZE)')

# logger configs
[ ! -z ${SPLITD_LOG_LEVEL+x} ] && accum=$(echo "${accum}" | yq '.logging.level = env(SPLITD_LOG_LEVEL)')
Expand Down
2 changes: 2 additions & 0 deletions infra/test/test_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function testAllVars {
export SPLITD_LINK_READ_TIMEOUT_MS=2
export SPLITD_LINK_WRITE_TIMEOUT_MS=3
export SPLITD_LINK_ACCEPT_TIMEOUT_MS=4
export SPLITD_LINK_BUFFER_SIZE=5
export SPLITD_LOG_LEVEL="WARNING"
export SPLITD_LOG_OUTPUT="/dev/stderr"

Expand Down Expand Up @@ -92,6 +93,7 @@ function testAllVars {
assert_eq "2" $(echo "$conf_json" | jq '.Link.ReadTimeoutMS') "incorrect read timeout"
assert_eq "3" $(echo "$conf_json" | jq '.Link.WriteTimeoutMS') "incorrect write timeout"
assert_eq "4" $(echo "$conf_json" | jq '.Link.AcceptTimeoutMS') "incorrect accept timeout"
assert_eq "5" $(echo "$conf_json" | jq '.Link.BufferSize') "incorrect buffer size"

# ---

Expand Down
2 changes: 1 addition & 1 deletion splitio/commitsha.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package splitio

const CommitSHA = "e1ecfc9"
const CommitSHA = "29ff22d"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package conf
package lang

func SetIfNotNil[T any](dst *T, src *T) {
if src != nil {
Expand Down
32 changes: 32 additions & 0 deletions splitio/common/lang/functools_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package lang

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestConfHelpers(t *testing.T) {
var x int
SetIfNotEmpty(&x, Ref(0))
assert.Equal(t, 0, x)
SetIfNotNil(&x, nil)
assert.Equal(t, 0, x)

SetIfNotEmpty(&x, Ref(5))
assert.Equal(t, 5, x)
SetIfNotNil(&x, Ref(25))
assert.Equal(t, 25, x)

x = 0
MapIfNotEmpty(&x, Ref(0), func(z int) int { return z + 1 })
assert.Equal(t, 0, x)
MapIfNotNil(&x, nil, func(z int) int { return z + 1 })
assert.Equal(t, 0, x)
MapIfNotNil(&x, Ref(10), func(z int) int { return z + 1 })
assert.Equal(t, 11, x)

MapIfNotEmpty(&x, Ref(1), func(z int) int { return z + 1 })
assert.Equal(t, 2, x)
MapIfNotEmpty(&x, Ref(2), func(z int) int { return z + 1 })
assert.Equal(t, 3, x)
}
5 changes: 5 additions & 0 deletions splitio/common/lang/ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package lang

func Ref[T any](t T) *T {
return &t
}
6 changes: 3 additions & 3 deletions splitio/util/conf/parsers.go → splitio/conf/parsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
"github.com/splitio/splitd/splitio/link/transfer"
)

func ParseProtocolVersion(p string) (protocol.Version, error) {
func parseProtocolVersion(p string) (protocol.Version, error) {
switch p {
case "v1":
return protocol.V1, nil
}
return 0, fmt.Errorf("unkown protocol version '%s'", p)
}

func ParseConnType(t string) (transfer.ConnType, error) {
func parseConnType(t string) (transfer.ConnType, error) {
switch t {
case "unix-seqpacket":
return transfer.ConnTypeUnixSeqPacket, nil
Expand All @@ -26,7 +26,7 @@ func ParseConnType(t string) (transfer.ConnType, error) {
return 0, fmt.Errorf("unknown listener type '%s'", t)
}

func ParseSerializer(s string) (serializer.Mechanism, error) {
func parseSerializer(s string) (serializer.Mechanism, error) {
switch s {
case "msgpack":
return serializer.MsgPack, nil
Expand Down
46 changes: 46 additions & 0 deletions splitio/conf/parsers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package conf

import (
"testing"

"github.com/splitio/splitd/splitio/link/protocol"
"github.com/splitio/splitd/splitio/link/serializer"
"github.com/splitio/splitd/splitio/link/transfer"
"github.com/stretchr/testify/assert"
)

func TestParseProtocol(t *testing.T) {
pv, err := parseProtocolVersion("v1")
assert.Nil(t, err)
assert.Equal(t, protocol.V1, pv)

pv, err = parseProtocolVersion("v2")
assert.NotNil(t, err)
assert.NotEqual(t, pv, protocol.V1)
}

func TestParseConnType(t *testing.T) {
ct, err := parseConnType("unix-stream")
assert.Nil(t, err)
assert.Equal(t, transfer.ConnTypeUnixStream, ct)

ct, err = parseConnType("unix-seqpacket")
assert.Nil(t, err)
assert.Equal(t, transfer.ConnTypeUnixSeqPacket, ct)

ct, err = parseConnType("something-else")
assert.NotNil(t, err)
assert.NotEqual(t, transfer.ConnTypeUnixSeqPacket, ct)
assert.NotEqual(t, transfer.ConnTypeUnixStream, ct)
}

func TestParseSerializer(t *testing.T) {
sm, err := parseSerializer("msgpack")
assert.Nil(t, err)
assert.Equal(t, serializer.MsgPack, sm)

sm, err = parseSerializer("something_esle")
assert.NotNil(t, err)
assert.NotEqual(t, serializer.MsgPack, sm)

}
Loading

0 comments on commit 1472745

Please sign in to comment.