Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion infra/sidecar.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ----- Builder image
ARG GOLANG_VERSION=1.23.6
ARG GOLANG_VERSION=1.24.0
FROM golang:${GOLANG_VERSION}-bookworm AS builder

ARG FIPS_MODE
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 = "a651b23"
const CommitSHA = "eba3941"
61 changes: 36 additions & 25 deletions splitio/conf/splitcli.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ type CliArgs struct {
WriteTimeoutMS int

// command
Method string
Key string
BucketingKey string
Feature string
Features []string
TrafficType string
EventType string
EventVal *float64
Attributes map[string]interface{}
Method string
Key string
BucketingKey string
Feature string
Features []string
TrafficType string
EventType string
EventVal *float64
Attributes map[string]interface{}
ImpressionProperties map[string]interface{}
}

func (a *CliArgs) LinkOpts() (*link.ConsumerOptions, error) {
Expand Down Expand Up @@ -85,6 +86,7 @@ func ParseCliArgs() (*CliArgs, error) {
et := cliFlags.String("event-type", "", "event type")
ev := cliFlags.String("value", "", "event associated value")
at := cliFlags.String("attributes", "", "json representation of attributes")
pr := cliFlags.String("impression-properties", "", "json representation of")
err := cliFlags.Parse(os.Args[1:])
if err != nil {
return nil, fmt.Errorf("error parsing arguments: %w", err)
Expand All @@ -107,22 +109,31 @@ func ParseCliArgs() (*CliArgs, error) {
return nil, fmt.Errorf("error parsing attributes: %w", err)
}

if *pr == "" {
*pr = "null"
}
impressionPorperties := make(map[string]interface{})
if err = json.Unmarshal([]byte(*pr), &impressionPorperties); err != nil {
return nil, fmt.Errorf("error parsing impression properties: %w", err)
}

return &CliArgs{
ID: *id,
Serialization: *s,
Protocol: *p,
LogLevel: *ll,
ConnType: *ct,
ConnAddr: *ca,
BufSize: *bs,
Method: *m,
Key: *k,
BucketingKey: *bk,
Feature: *f,
Features: strings.Split(*fs, ","),
TrafficType: *tt,
EventType: *et,
EventVal: eventVal,
Attributes: attrs,
ID: *id,
Serialization: *s,
Protocol: *p,
LogLevel: *ll,
ConnType: *ct,
ConnAddr: *ca,
BufSize: *bs,
Method: *m,
Key: *k,
BucketingKey: *bk,
Feature: *f,
Features: strings.Split(*fs, ","),
TrafficType: *tt,
EventType: *et,
EventVal: eventVal,
Attributes: attrs,
ImpressionProperties: impressionPorperties,
}, nil
}
2 changes: 2 additions & 0 deletions splitio/conf/splitcli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func TestCliConfig(t *testing.T) {
"-event-type=someEventType",
"-value=0.123",
`-attributes={"some": "attribute"}`,
`-impression-properties={"userId": "123", "age": 30, "premium": true, "balance": 99.5}`,
}

parsed, err := ParseCliArgs()
Expand All @@ -42,6 +43,7 @@ func TestCliConfig(t *testing.T) {
assert.Equal(t, "someEventType", parsed.EventType)
assert.Equal(t, lang.Ref(float64(0.123)), parsed.EventVal)
assert.Equal(t, map[string]interface{}{"some": "attribute"}, parsed.Attributes)
assert.Equal(t, map[string]interface{}{"userId": "123", "age": float64(30), "premium": true, "balance": 99.5}, parsed.ImpressionProperties)

// test bad buffer size
os.Args = []string{os.Args[0], "-buffer-size=sarasa"}
Expand Down
14 changes: 10 additions & 4 deletions splitio/link/client/types/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
)

type ClientInterface interface {
Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*Result, error)
Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}) (Results, error)
TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*Result, error)
TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}) (Results, error)
Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...OptFn) (*Result, error)
Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...OptFn) (Results, error)
TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...OptFn) (*Result, error)
TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...OptFn) (Results, error)
Track(key string, trafficType string, eventType string, value *float64, properties map[string]interface{}) error
SplitNames() ([]string, error)
Split(name string) (*sdk.SplitView, error)
Expand All @@ -24,3 +24,9 @@ type Result struct {
}

type Results = map[string]Result

type Options struct {
EvaluationOptions *dtos.EvaluationOptions
}

type OptFn = func(o *Options)
44 changes: 34 additions & 10 deletions splitio/link/client/v1/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ type Impl struct {
listenerFeedback bool
}

func (c *Impl) WithEvaluationOptions(e *dtos.EvaluationOptions) types.OptFn {
return func(o *types.Options) { o.EvaluationOptions = e }
}

func defaultOpts() types.Options {
return types.Options{
EvaluationOptions: nil,
}
}

func New(id string, logger logging.LoggerInterface, conn transfer.RawConn, serializer serializer.Interface, listenerFeedback bool) (*Impl, error) {
i := &Impl{
logger: logger,
Expand All @@ -43,23 +53,27 @@ func New(id string, logger logging.LoggerInterface, conn transfer.RawConn, seria
}

// Treatment implements Interface
func (c *Impl) Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*types.Result, error) {
return c.treatment(key, bucketingKey, feature, attrs, false)
func (c *Impl) Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...types.OptFn) (*types.Result, error) {
options := getOptions(optFns...)
return c.treatment(key, bucketingKey, feature, attrs, false, options.EvaluationOptions)
}

// TreatmentWithConfig implements types.ClientInterface
func (c *Impl) TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*types.Result, error) {
return c.treatment(key, bucketingKey, feature, attrs, true)
func (c *Impl) TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...types.OptFn) (*types.Result, error) {
options := getOptions(optFns...)
return c.treatment(key, bucketingKey, feature, attrs, true, options.EvaluationOptions)
}

// Treatment implements Interface
func (c *Impl) Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}) (types.Results, error) {
return c.treatments(key, bucketingKey, features, attrs, false)
func (c *Impl) Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...types.OptFn) (types.Results, error) {
options := getOptions(optFns...)
return c.treatments(key, bucketingKey, features, attrs, false, options.EvaluationOptions)
}

// TreatmentsWithConfig implements types.ClientInterface
func (c *Impl) TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}) (types.Results, error) {
return c.treatments(key, bucketingKey, features, attrs, true)
func (c *Impl) TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...types.OptFn) (types.Results, error) {
options := getOptions(optFns...)
return c.treatments(key, bucketingKey, features, attrs, true, options.EvaluationOptions)
}

// Track implements types.ClientInterface
Expand Down Expand Up @@ -139,7 +153,7 @@ func (c *Impl) Splits() ([]sdk.SplitView, error) {
return views, nil
}

func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, withConfig bool) (*types.Result, error) {
func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, withConfig bool, evaluationOptions *dtos.EvaluationOptions) (*types.Result, error) {
var bkp *string
if bucketingKey != "" {
bkp = &bucketingKey
Expand Down Expand Up @@ -174,6 +188,7 @@ func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs
ChangeNumber: resp.Payload.ListenerData.ChangeNumber,
Label: resp.Payload.ListenerData.Label,
BucketingKey: bucketingKey,
Properties: sdk.SerializeProperties(evaluationOptions),
}
}

Expand All @@ -185,7 +200,7 @@ func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs
return toRet, nil
}

func (c *Impl) treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, withConfig bool) (types.Results, error) {
func (c *Impl) treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, withConfig bool, evaluationOptions *dtos.EvaluationOptions) (types.Results, error) {
var bkp *string
if bucketingKey != "" {
bkp = &bucketingKey
Expand Down Expand Up @@ -221,6 +236,7 @@ func (c *Impl) treatments(key string, bucketingKey string, features []string, at
ChangeNumber: resp.Payload.Results[idx].ListenerData.ChangeNumber,
Label: resp.Payload.Results[idx].ListenerData.Label,
BucketingKey: bucketingKey,
Properties: sdk.SerializeProperties(evaluationOptions),
}
}

Expand Down Expand Up @@ -286,4 +302,12 @@ func (c *Impl) Shutdown() error {
return c.conn.Shutdown()
}

func getOptions(optFns ...types.OptFn) types.Options {
options := defaultOpts()
for _, optFn := range optFns {
optFn(&options)
}
return options
}

var _ types.ClientInterface = (*Impl)(nil)
15 changes: 11 additions & 4 deletions splitio/link/client/v1/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestClientGetTreatmentNoImpression(t *testing.T) {
*args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk}
}).Once()

serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, false)).
serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, false)).
Return([]byte("treatmentMessage"), nil).Once()
serializerMock.On("Parse", []byte("treatmentResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) {
*args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestClientGetTreatmentWithConfig(t *testing.T) {
*args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk}
}).Once()

serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, true)).
serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, true)).
Return([]byte("treatmentWithConfigMessage"), nil).Once()
serializerMock.On("Parse", []byte("treatmentWithConfigResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) {
*args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{
Expand Down Expand Up @@ -129,7 +129,7 @@ func TestClientGetTreatmentWithImpression(t *testing.T) {
*args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk}
}).Once()

serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, false)).
serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, false)).
Return([]byte("treatmentMessage"), nil).Once()
serializerMock.On("Parse", []byte("treatmentResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) {
*args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{
Expand All @@ -144,7 +144,12 @@ func TestClientGetTreatmentWithImpression(t *testing.T) {
assert.NotNil(t, client)
assert.Nil(t, err)

res, err := client.Treatment("key1", "buck1", "feat1", map[string]interface{}{"a": 1})
opts := dtos.EvaluationOptions{
Properties: map[string]interface{}{
"pleassssse": "holaaaaa",
},
}
res, err := client.Treatment("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, client.WithEvaluationOptions(&opts))
assert.Nil(t, err)
assert.Equal(t, "on", res.Treatment)
validateImpression(t, &dtos.Impression{
Expand All @@ -155,6 +160,7 @@ func TestClientGetTreatmentWithImpression(t *testing.T) {
Label: "l1",
ChangeNumber: 1234,
Time: 123,
Properties: "{\"pleassssse\":\"holaaaaa\"}",
}, res.Impression)

}
Expand Down Expand Up @@ -435,5 +441,6 @@ func validateImpression(t *testing.T, expected *dtos.Impression, actual *dtos.Im
assert.Equal(t, expected.Time, actual.Time)
assert.Equal(t, expected.Treatment, actual.Treatment)
assert.Equal(t, expected.Label, actual.Label)
assert.Equal(t, expected.Properties, actual.Properties)

}
4 changes: 2 additions & 2 deletions splitio/link/protocol/v1/mocks/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ func NewRegisterRPC(id string, listener bool) *v1.RPC {
}
}

func NewTreatmentRPC(key string, bucketing string, feature string, attrs map[string]interface{}, withConfig bool) *v1.RPC {
func NewTreatmentRPC(key string, bucketing string, feature string, attrs map[string]interface{}, impressionProperties map[string]interface{}, withConfig bool) *v1.RPC {
rpc := &v1.RPC{
RPCBase: protocol.RPCBase{Version: protocol.V1},
OpCode: v1.OCTreatment,
Args: []interface{}{key, bucketing, feature, attrs},
Args: []interface{}{key, bucketing, feature, attrs, impressionProperties},
}
if withConfig {
rpc.OpCode = v1.OCTreatmentWithConfig
Expand Down
Loading