diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 55eb1323a..abac59a28 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] Changes that have landed but are not yet released. Changes that have landed but are not yet released. +## [1.2.0] - May 21st, 2020 +## New Features +- feat: support for multi-rule rollouts [#247](https://github.com/optimizely/go-sdk/pull/247) + +## [1.1.3] - April 22th, 2020 +## Bug Fix +- logger not set for httpDispatcher [#254](https://github.com/optimizely/go-sdk/pull/254) + ## [1.1.2] - March 26th, 2020 ## New Features - refact: Update logging field keys to be consumable in structured logs [#246](https://github.com/optimizely/go-sdk/pull/246) diff --git a/pkg/decision/helpers_test.go b/pkg/decision/helpers_test.go index f4b352832..7a1499050 100644 --- a/pkg/decision/helpers_test.go +++ b/pkg/decision/helpers_test.go @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2019, Optimizely, Inc. and contributors * + * Copyright 2019-2020, Optimizely, Inc. and contributors * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * @@ -150,6 +150,48 @@ var testExp1112 = entities.Experiment{ entities.Range{EntityID: "2222", EndOfRange: 10000}, }, } +var testExp1117Var2223 = entities.Variation{ID: "2223", Key: "2223"} +var testAudience5556 = entities.Audience{ID: "5556"} +var testExp1117 = entities.Experiment{ + AudienceConditionTree: &entities.TreeNode{ + Operator: "and", + Nodes: []*entities.TreeNode{ + &entities.TreeNode{Item: "test_audience_5556"}, + }, + }, + ID: "1117", + Key: testExp1111Key, + Variations: map[string]entities.Variation{ + "2223": testExp1117Var2223, + }, + VariationKeyToIDMap: map[string]string{ + "2223": "2223", + }, + TrafficAllocation: []entities.Range{ + entities.Range{EntityID: "2223", EndOfRange: 10000}, + }, +} +var testExp1118Var2224 = entities.Variation{ID: "2224", Key: "2224"} +var testAudience5557 = entities.Audience{ID: "5557"} +var testExp1118 = entities.Experiment{ + AudienceConditionTree: &entities.TreeNode{ + Operator: "and", + Nodes: []*entities.TreeNode{ + &entities.TreeNode{Item: "test_audience_5557"}, + }, + }, + ID: "1118", + Key: testExp1111Key, + Variations: map[string]entities.Variation{ + "2224": testExp1118Var2224, + }, + VariationKeyToIDMap: map[string]string{ + "2224": "2224", + }, + TrafficAllocation: []entities.Range{ + entities.Range{EntityID: "2224", EndOfRange: 10000}, + }, +} const testFeatRollout3334Key = "test_feature_rollout_3334_key" @@ -158,7 +200,7 @@ var testFeatRollout3334 = entities.Feature{ Key: testFeatRollout3334Key, Rollout: entities.Rollout{ ID: "4444", - Experiments: []entities.Experiment{testExp1112}, + Experiments: []entities.Experiment{testExp1112, testExp1117, testExp1118}, }, } diff --git a/pkg/decision/rollout_service.go b/pkg/decision/rollout_service.go index f7245eb22..17dca3769 100644 --- a/pkg/decision/rollout_service.go +++ b/pkg/decision/rollout_service.go @@ -30,13 +30,13 @@ import ( type RolloutService struct { audienceTreeEvaluator evaluator.TreeEvaluator experimentBucketerService ExperimentService - logger logging.OptimizelyLogProducer + logger logging.OptimizelyLogProducer } // NewRolloutService returns a new instance of the Rollout service func NewRolloutService(sdkKey string) *RolloutService { return &RolloutService{ - logger:logging.GetLogger(sdkKey, "RolloutService"), + logger: logging.GetLogger(sdkKey, "RolloutService"), audienceTreeEvaluator: evaluator.NewMixedTreeEvaluator(), experimentBucketerService: NewExperimentBucketerService(logging.GetLogger(sdkKey, "ExperimentBucketerService")), } @@ -44,11 +44,47 @@ func NewRolloutService(sdkKey string) *RolloutService { // GetDecision returns a decision for the given feature and user context func (r RolloutService) GetDecision(decisionContext FeatureDecisionContext, userContext entities.UserContext) (FeatureDecision, error) { + featureDecision := FeatureDecision{ Source: Rollout, } feature := decisionContext.Feature rollout := feature.Rollout + + evaluateConditionTree := func(experiment *entities.Experiment) bool { + condTreeParams := entities.NewTreeParameters(&userContext, decisionContext.ProjectConfig.GetAudienceMap()) + evalResult, _ := r.audienceTreeEvaluator.Evaluate(experiment.AudienceConditionTree, condTreeParams) + if !evalResult { + featureDecision.Reason = reasons.FailedRolloutTargeting + r.logger.Debug(fmt.Sprintf(`User "%s" failed targeting for feature rollout with key "%s".`, userContext.ID, feature.Key)) + } + return evalResult + } + + getFeatureDecision := func(experiment *entities.Experiment, decision *ExperimentDecision) (FeatureDecision, error) { + // translate the experiment reason into a more rollouts-appropriate reason + switch decision.Reason { + case reasons.NotBucketedIntoVariation: + featureDecision.Decision = Decision{Reason: reasons.FailedRolloutBucketing} + case reasons.BucketedIntoVariation: + featureDecision.Decision = Decision{Reason: reasons.BucketedIntoRollout} + default: + featureDecision.Decision = decision.Decision + } + + featureDecision.Experiment = *experiment + featureDecision.Variation = decision.Variation + r.logger.Debug(fmt.Sprintf(`Decision made for user "%s" for feature rollout with key "%s": %s.`, userContext.ID, feature.Key, featureDecision.Reason)) + return featureDecision, nil + } + + getExperimentDecisionContext := func(experiment *entities.Experiment) ExperimentDecisionContext { + return ExperimentDecisionContext{ + Experiment: experiment, + ProjectConfig: decisionContext.ProjectConfig, + } + } + if rollout.ID == "" { featureDecision.Reason = reasons.NoRolloutForFeature return featureDecision, nil @@ -60,38 +96,30 @@ func (r RolloutService) GetDecision(decisionContext FeatureDecisionContext, user return featureDecision, nil } - // For now, Rollouts is just a single experiment layer - experiment := rollout.Experiments[0] - experimentDecisionContext := ExperimentDecisionContext{ - Experiment: &experiment, - ProjectConfig: decisionContext.ProjectConfig, - } - - // if user fails rollout targeting rule we return out of it - if experiment.AudienceConditionTree != nil { - condTreeParams := entities.NewTreeParameters(&userContext, decisionContext.ProjectConfig.GetAudienceMap()) - evalResult, _ := r.audienceTreeEvaluator.Evaluate(experiment.AudienceConditionTree, condTreeParams) - if !evalResult { - featureDecision.Reason = reasons.FailedRolloutTargeting - r.logger.Debug(fmt.Sprintf(`User "%s" failed targeting for feature rollout with key "%s".`, userContext.ID, feature.Key)) - return featureDecision, nil + for index := 0; index < numberOfExperiments-1; index++ { + experiment := &rollout.Experiments[index] + experimentDecisionContext := getExperimentDecisionContext(experiment) + // Move to next evaluation if condition tree is available and evaluation fails + if experiment.AudienceConditionTree != nil && !evaluateConditionTree(experiment) { + // Evaluate this user for the next rule + continue + } + decision, _ := r.experimentBucketerService.GetDecision(experimentDecisionContext, userContext) + if decision.Variation == nil { + // Evaluate fall back rule / last rule now + break } + return getFeatureDecision(experiment, &decision) } - decision, _ := r.experimentBucketerService.GetDecision(experimentDecisionContext, userContext) - // translate the experiment reason into a more rollouts-appropriate reason - switch decision.Reason { - case reasons.NotBucketedIntoVariation: - featureDecision.Decision = Decision{Reason: reasons.FailedRolloutBucketing} - case reasons.BucketedIntoVariation: - featureDecision.Decision = Decision{Reason: reasons.BucketedIntoRollout} - default: - featureDecision.Decision = decision.Decision + // fall back rule / last rule + experiment := &rollout.Experiments[numberOfExperiments-1] + experimentDecisionContext := getExperimentDecisionContext(experiment) + // Move to bucketing if conditionTree is unavailable or evaluation passes + if experiment.AudienceConditionTree == nil || evaluateConditionTree(experiment) { + decision, _ := r.experimentBucketerService.GetDecision(experimentDecisionContext, userContext) + return getFeatureDecision(experiment, &decision) } - featureDecision.Experiment = experiment - featureDecision.Variation = decision.Variation - r.logger.Debug(fmt.Sprintf(`Decision made for user "%s" for feature rollout with key "%s": %s.`, userContext.ID, feature.Key, featureDecision.Reason)) - return featureDecision, nil } diff --git a/pkg/decision/rollout_service_test.go b/pkg/decision/rollout_service_test.go index b487ddd44..48fe33bdd 100644 --- a/pkg/decision/rollout_service_test.go +++ b/pkg/decision/rollout_service_test.go @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2019, Optimizely, Inc. and contributors * + * Copyright 2019-2020, Optimizely, Inc. and contributors * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * @@ -26,25 +26,24 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - ) type RolloutServiceTestSuite struct { suite.Suite - mockConfig *mockProjectConfig - mockAudienceTreeEvaluator *MockAudienceTreeEvaluator - mockExperimentService *MockExperimentDecisionService - testExperimentDecisionContext ExperimentDecisionContext - testFeatureDecisionContext FeatureDecisionContext - testConditionTreeParams *entities.TreeParameters - testUserContext entities.UserContext + mockConfig *mockProjectConfig + mockAudienceTreeEvaluator *MockAudienceTreeEvaluator + mockExperimentService *MockExperimentDecisionService + testExperiment1112DecisionContext ExperimentDecisionContext + testFeatureDecisionContext FeatureDecisionContext + testConditionTreeParams *entities.TreeParameters + testUserContext entities.UserContext } func (s *RolloutServiceTestSuite) SetupTest() { s.mockConfig = new(mockProjectConfig) s.mockAudienceTreeEvaluator = new(MockAudienceTreeEvaluator) s.mockExperimentService = new(MockExperimentDecisionService) - s.testExperimentDecisionContext = ExperimentDecisionContext{ + s.testExperiment1112DecisionContext = ExperimentDecisionContext{ Experiment: &testExp1112, ProjectConfig: s.mockConfig, } @@ -55,6 +54,8 @@ func (s *RolloutServiceTestSuite) SetupTest() { testAudienceMap := map[string]entities.Audience{ "5555": testAudience5555, + "5556": testAudience5556, + "5557": testAudience5557, } s.testUserContext = entities.UserContext{ ID: "test_user", @@ -63,6 +64,40 @@ func (s *RolloutServiceTestSuite) SetupTest() { s.mockConfig.On("GetAudienceMap").Return(testAudienceMap) } +func (s *RolloutServiceTestSuite) TestGetDecisionWithEmptyRolloutID() { + + testRolloutService := RolloutService{} + feature := testFeatRollout3334 + feature.Rollout.ID = "" + featureDecisionContext := FeatureDecisionContext{ + Feature: &feature, + ProjectConfig: s.mockConfig, + } + expectedFeatureDecision := FeatureDecision{ + Source: Rollout, + Decision: Decision{Reason: reasons.NoRolloutForFeature}, + } + decision, _ := testRolloutService.GetDecision(featureDecisionContext, s.testUserContext) + s.Equal(expectedFeatureDecision, decision) +} + +func (s *RolloutServiceTestSuite) TestGetDecisionWithNoExperiments() { + + testRolloutService := RolloutService{} + feature := testFeatRollout3334 + feature.Rollout.Experiments = []entities.Experiment{} + featureDecisionContext := FeatureDecisionContext{ + Feature: &feature, + ProjectConfig: s.mockConfig, + } + expectedFeatureDecision := FeatureDecision{ + Source: Rollout, + Decision: Decision{Reason: reasons.RolloutHasNoExperiments}, + } + decision, _ := testRolloutService.GetDecision(featureDecisionContext, s.testUserContext) + s.Equal(expectedFeatureDecision, decision) +} + func (s *RolloutServiceTestSuite) TestGetDecisionHappyPath() { // Test experiment passes targeting and bucketing testExperimentBucketerDecision := ExperimentDecision{ @@ -70,12 +105,12 @@ func (s *RolloutServiceTestSuite) TestGetDecisionHappyPath() { Decision: Decision{Reason: reasons.BucketedIntoVariation}, } s.mockAudienceTreeEvaluator.On("Evaluate", testExp1112.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) - s.mockExperimentService.On("GetDecision", s.testExperimentDecisionContext, s.testUserContext).Return(testExperimentBucketerDecision, nil) + s.mockExperimentService.On("GetDecision", s.testExperiment1112DecisionContext, s.testUserContext).Return(testExperimentBucketerDecision, nil) testRolloutService := RolloutService{ audienceTreeEvaluator: s.mockAudienceTreeEvaluator, experimentBucketerService: s.mockExperimentService, - logger:logging.GetLogger("sdkKey", "RolloutService"), + logger: logging.GetLogger("sdkKey", "RolloutService"), } expectedFeatureDecision := FeatureDecision{ Experiment: testExp1112, @@ -89,27 +124,96 @@ func (s *RolloutServiceTestSuite) TestGetDecisionHappyPath() { s.mockExperimentService.AssertExpectations(s.T()) } -func (s *RolloutServiceTestSuite) TestGetDecisionFailsBucketing() { - // Test experiment passes targeting but not bucketing - testExperimentBucketerDecision := ExperimentDecision{ +func (s *RolloutServiceTestSuite) TestGetDecisionFallbacksToLastWhenFailsBucketing() { + testExperiment1112BucketerDecision := ExperimentDecision{ Decision: Decision{ Reason: reasons.NotBucketedIntoVariation, }, } - + testExperiment1118BucketerDecision := ExperimentDecision{ + Variation: &testExp1118Var2224, + Decision: Decision{Reason: reasons.BucketedIntoVariation}, + } + experiment1118DecisionContext := ExperimentDecisionContext{ + Experiment: &testExp1118, + ProjectConfig: s.mockConfig, + } s.mockAudienceTreeEvaluator.On("Evaluate", testExp1112.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) - s.mockExperimentService.On("GetDecision", s.testExperimentDecisionContext, s.testUserContext).Return(testExperimentBucketerDecision, nil) + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1118.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) + s.mockExperimentService.On("GetDecision", s.testExperiment1112DecisionContext, s.testUserContext).Return(testExperiment1112BucketerDecision, nil) + s.mockExperimentService.On("GetDecision", experiment1118DecisionContext, s.testUserContext).Return(testExperiment1118BucketerDecision, nil) + testRolloutService := RolloutService{ audienceTreeEvaluator: s.mockAudienceTreeEvaluator, experimentBucketerService: s.mockExperimentService, - logger:logging.GetLogger("sdkKey", "RolloutService"), + logger: logging.GetLogger("sdkKey", "RolloutService"), } expectedFeatureDecision := FeatureDecision{ + Experiment: testExp1118, + Variation: &testExp1118Var2224, + Source: Rollout, + Decision: Decision{Reason: reasons.BucketedIntoRollout}, + } + decision, _ := testRolloutService.GetDecision(s.testFeatureDecisionContext, s.testUserContext) + s.Equal(expectedFeatureDecision, decision) + s.mockAudienceTreeEvaluator.AssertExpectations(s.T()) + s.mockExperimentService.AssertExpectations(s.T()) +} + +func (s *RolloutServiceTestSuite) TestGetDecisionWhenFallbackBucketingFails() { + testExperiment1112BucketerDecision := ExperimentDecision{ Decision: Decision{ - Reason: reasons.FailedRolloutBucketing, + Reason: reasons.NotBucketedIntoVariation, }, - Experiment: testExp1112, + } + testExperiment1118DecisionContext := ExperimentDecisionContext{ + Experiment: &testExp1118, + ProjectConfig: s.mockConfig, + } + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1112.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1118.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) + s.mockExperimentService.On("GetDecision", s.testExperiment1112DecisionContext, s.testUserContext).Return(testExperiment1112BucketerDecision, nil) + s.mockExperimentService.On("GetDecision", testExperiment1118DecisionContext, s.testUserContext).Return(testExperiment1112BucketerDecision, nil) + + testRolloutService := RolloutService{ + audienceTreeEvaluator: s.mockAudienceTreeEvaluator, + experimentBucketerService: s.mockExperimentService, + logger: logging.GetLogger("sdkKey", "RolloutService"), + } + expectedFeatureDecision := FeatureDecision{ + Experiment: testExp1118, Source: Rollout, + Decision: Decision{Reason: reasons.FailedRolloutBucketing}, + } + decision, _ := testRolloutService.GetDecision(s.testFeatureDecisionContext, s.testUserContext) + s.Equal(expectedFeatureDecision, decision) + s.mockAudienceTreeEvaluator.AssertExpectations(s.T()) + s.mockExperimentService.AssertExpectations(s.T()) +} + +func (s *RolloutServiceTestSuite) TestEvaluatesNextIfPreviousTargetingFails() { + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1112.AudienceConditionTree, s.testConditionTreeParams).Return(false, true) + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1117.AudienceConditionTree, s.testConditionTreeParams).Return(true, true) + experiment1117DecisionContext := ExperimentDecisionContext{ + Experiment: &testExp1117, + ProjectConfig: s.mockConfig, + } + testExperimentBucketerDecision := ExperimentDecision{ + Variation: &testExp1117Var2223, + Decision: Decision{Reason: reasons.BucketedIntoVariation}, + } + s.mockExperimentService.On("GetDecision", experiment1117DecisionContext, s.testUserContext).Return(testExperimentBucketerDecision, nil) + + testRolloutService := RolloutService{ + audienceTreeEvaluator: s.mockAudienceTreeEvaluator, + experimentBucketerService: s.mockExperimentService, + logger: logging.GetLogger("sdkKey", "RolloutService"), + } + expectedFeatureDecision := FeatureDecision{ + Experiment: testExp1117, + Variation: &testExp1117Var2223, + Source: Rollout, + Decision: Decision{Reason: reasons.BucketedIntoRollout}, } decision, _ := testRolloutService.GetDecision(s.testFeatureDecisionContext, s.testUserContext) s.Equal(expectedFeatureDecision, decision) @@ -119,10 +223,12 @@ func (s *RolloutServiceTestSuite) TestGetDecisionFailsBucketing() { func (s *RolloutServiceTestSuite) TestGetDecisionFailsTargeting() { s.mockAudienceTreeEvaluator.On("Evaluate", testExp1112.AudienceConditionTree, s.testConditionTreeParams).Return(false, true) + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1117.AudienceConditionTree, s.testConditionTreeParams).Return(false, true) + s.mockAudienceTreeEvaluator.On("Evaluate", testExp1118.AudienceConditionTree, s.testConditionTreeParams).Return(false, true) testRolloutService := RolloutService{ audienceTreeEvaluator: s.mockAudienceTreeEvaluator, experimentBucketerService: s.mockExperimentService, - logger:logging.GetLogger("sdkKey", "RolloutService"), + logger: logging.GetLogger("sdkKey", "RolloutService"), } expectedFeatureDecision := FeatureDecision{ Decision: Decision{ @@ -139,7 +245,7 @@ func (s *RolloutServiceTestSuite) TestGetDecisionFailsTargeting() { func TestNewRolloutService(t *testing.T) { rolloutService := NewRolloutService("") assert.IsType(t, &evaluator.MixedTreeEvaluator{}, rolloutService.audienceTreeEvaluator) - assert.IsType(t, &ExperimentBucketerService{logger:logging.GetLogger("sdkKey", "ExperimentBucketerService")}, rolloutService.experimentBucketerService) + assert.IsType(t, &ExperimentBucketerService{logger: logging.GetLogger("sdkKey", "ExperimentBucketerService")}, rolloutService.experimentBucketerService) } func TestRolloutServiceTestSuite(t *testing.T) { diff --git a/pkg/event/dispatcher.go b/pkg/event/dispatcher.go index 58026f80d..611b6aae2 100644 --- a/pkg/event/dispatcher.go +++ b/pkg/event/dispatcher.go @@ -37,14 +37,14 @@ type Dispatcher interface { DispatchEvent(event LogEvent) (bool, error) } -// HTTPEventDispatcher is the HTTP implementation of the Dispatcher interface -type HTTPEventDispatcher struct { +// httpEventDispatcher is the HTTP implementation of the Dispatcher interface +type httpEventDispatcher struct { requester *utils.HTTPRequester logger logging.OptimizelyLogProducer } // DispatchEvent dispatches event with callback -func (ed *HTTPEventDispatcher) DispatchEvent(event LogEvent) (bool, error) { +func (ed *httpEventDispatcher) DispatchEvent(event LogEvent) (bool, error) { _, _, code, err := ed.requester.Post(event.EndPoint, event.Event) @@ -65,6 +65,18 @@ func (ed *HTTPEventDispatcher) DispatchEvent(event LogEvent) (bool, error) { return success, err } +// NewHTTPEventDispatcher creates a full http dispatcher. The requester and logger parameters can be nil. +func NewHTTPEventDispatcher(sdkKey string, requester *utils.HTTPRequester, logger logging.OptimizelyLogProducer) Dispatcher { + if requester == nil { + requester = utils.NewHTTPRequester(logging.GetLogger(sdkKey, "HTTPRequester")) + } + if logger == nil { + logger = logging.GetLogger(sdkKey, "httpEventDispatcher") + } + + return &httpEventDispatcher{requester: requester, logger: logger} +} + // QueueEventDispatcher is a queued version of the event Dispatcher that queues, returns success, and dispatches events in the background type QueueEventDispatcher struct { eventQueue Queue @@ -161,9 +173,8 @@ func NewQueueEventDispatcher(sdkKey string, metricsRegistry metrics.Registry) *Q } return &QueueEventDispatcher{ - eventQueue: NewInMemoryQueue(defaultQueueSize), - Dispatcher: &HTTPEventDispatcher{requester: utils.NewHTTPRequester(logging.GetLogger(sdkKey, "HTTPRequester"))}, - + eventQueue: NewInMemoryQueue(defaultQueueSize), + Dispatcher: NewHTTPEventDispatcher(sdkKey, nil, nil), queueSize: dispatcherMetricsRegistry.GetGauge(metrics.DispatcherQueueSize), retryFlushCounter: dispatcherMetricsRegistry.GetCounter(metrics.DispatcherRetryFlush), failFlushCounter: dispatcherMetricsRegistry.GetCounter(metrics.DispatcherFailedFlush), diff --git a/pkg/event/dispatcher_test.go b/pkg/event/dispatcher_test.go index c2e86c20e..c15a2ee73 100644 --- a/pkg/event/dispatcher_test.go +++ b/pkg/event/dispatcher_test.go @@ -104,6 +104,13 @@ func TestQueueEventDispatcher_DispatchEvent(t *testing.T) { metricsRegistry := NewMetricsRegistry() q := NewQueueEventDispatcher("", metricsRegistry) + + assert.True(t, q.Dispatcher != nil) + if d,ok := q.Dispatcher.(*httpEventDispatcher); ok { + assert.True(t, d.requester != nil && d.logger != nil) + } else { + assert.True(t, false) + } sender := &MockDispatcher{Events: NewInMemoryQueue(100)} q.Dispatcher = sender diff --git a/pkg/event/processor_test.go b/pkg/event/processor_test.go index 0fbc3a6db..f73563524 100644 --- a/pkg/event/processor_test.go +++ b/pkg/event/processor_test.go @@ -425,7 +425,7 @@ func TestChanQueueEventProcessor_ProcessImpression(t *testing.T) { processor := NewBatchEventProcessor( WithQueueSize(100), WithQueue(NewInMemoryQueue(100)), - WithEventDispatcher(&HTTPEventDispatcher{requester: utils.NewHTTPRequester(logging.GetLogger("", "NewHTTPRequester"))})) + WithEventDispatcher(NewHTTPEventDispatcher("", nil, nil))) eg.Go(processor.Start) diff --git a/pkg/event/version.go b/pkg/event/version.go index 061c845ca..f6ca90f8d 100644 --- a/pkg/event/version.go +++ b/pkg/event/version.go @@ -18,7 +18,7 @@ package event // Version is the current version of the client -var Version = "1.1.1" +var Version = "1.2.0" // ClientName is the name of the client var ClientName = "go-sdk"