Skip to content

Commit

Permalink
add test for multiple exporters
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Poignant <[email protected]>
  • Loading branch information
thomaspoignant committed Mar 6, 2025
1 parent a9bd61a commit 0c0996f
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 216 deletions.
198 changes: 0 additions & 198 deletions exporter/data_exporter_manager.go

This file was deleted.

7 changes: 0 additions & 7 deletions exporter/exporter_manager.go

This file was deleted.

22 changes: 14 additions & 8 deletions exporter/exporter_manager_impl.go → exporter/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"github.com/thomaspoignant/go-feature-flag/utils/fflog"
)

type ManagerImpl[T any] struct {
logger *fflog.FFLogger
consumers []dataExporterImpl[T]
eventStore *EventStore[T]
type Manager[T any] interface {
AddEvent(event T)
StartDaemon()
Close()
}

func NewManager[T any](ctx context.Context, exporters []Config, logger *fflog.FFLogger) Manager[T] {
Expand All @@ -27,14 +27,20 @@ func NewManager[T any](ctx context.Context, exporters []Config, logger *fflog.FF
consumers[index] = exp
evStore.AddConsumer(consumerId)
}
return &ManagerImpl[T]{
return &managerImpl[T]{
logger: logger,
consumers: consumers,
eventStore: &evStore,
}
}

func (m *ManagerImpl[T]) AddEvent(event T) {
type managerImpl[T any] struct {
logger *fflog.FFLogger
consumers []dataExporterImpl[T]
eventStore *EventStore[T]
}

func (m *managerImpl[T]) AddEvent(event T) {
store := *m.eventStore
store.Add(event)
for _, consumer := range m.consumers {
Expand All @@ -56,13 +62,13 @@ func (m *ManagerImpl[T]) AddEvent(event T) {
}
}

func (m *ManagerImpl[T]) StartDaemon() {
func (m *managerImpl[T]) StartDaemon() {
for _, consumer := range m.consumers {
go consumer.Start()
}
}

func (m *ManagerImpl[T]) Close() {
func (m *managerImpl[T]) Close() {
for _, consumer := range m.consumers {
consumer.Stop()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,85 @@ func TestAddExporterMetadataFromContextToExporter(t *testing.T) {
})
}
}

func TestDataExporterManager_multipleExporters(t *testing.T) {
mockExporter1 := mock.Exporter{Bulk: false}
mockExporter2 := mock.Exporter{Bulk: true}
dataExporterMock := []exporter.Config{
{
FlushInterval: 0,
MaxEventInMemory: 0,
Exporter: &mockExporter1,
},
{
FlushInterval: 200 * time.Millisecond,
MaxEventInMemory: 200,
Exporter: &mockExporter2,
},
}
dc := exporter.NewManager[exporter.FeatureEvent](context.Background(), dataExporterMock, nil)
go dc.StartDaemon()
defer dc.Close()

// Initialize inputEvents slice
var inputEvents []exporter.FeatureEvent
for i := 0; i < 100; i++ {
inputEvents = append(inputEvents, exporter.NewFeatureEvent(
ffcontext.NewEvaluationContextBuilder("ABCD").AddCustom("anonymous", true).Build(),
"random-key", "YO", "defaultVar", false, "", "SERVER", nil))
}
for _, event := range inputEvents {
dc.AddEvent(event)
// we have to wait because we are opening a new thread to slow down the flag evaluation.
time.Sleep(1 * time.Millisecond)
}

assert.Equal(t, inputEvents[:100], mockExporter1.GetExportedEvents())
assert.Equal(t, 0, len(mockExporter2.GetExportedEvents()))
time.Sleep(250 * time.Millisecond)
assert.Equal(t, inputEvents[:100], mockExporter2.GetExportedEvents())
}

func TestDataExporterManager_multipleExportersWithDifferentFlushInterval(t *testing.T) {
mockExporter1 := mock.Exporter{Bulk: true}
mockExporter2 := mock.Exporter{Bulk: true}
dataExporterMock := []exporter.Config{
{
FlushInterval: 50 * time.Millisecond,
MaxEventInMemory: 0,
Exporter: &mockExporter1,
},
{
FlushInterval: 0 * time.Millisecond,
MaxEventInMemory: 100,
Exporter: &mockExporter2,
},
}
dc := exporter.NewManager[exporter.FeatureEvent](context.Background(), dataExporterMock, nil)
go dc.StartDaemon()
defer dc.Close()

// Initialize inputEvents slice
var inputEvents []exporter.FeatureEvent
for i := 0; i < 100; i++ {
inputEvents = append(inputEvents, exporter.NewFeatureEvent(
ffcontext.NewEvaluationContextBuilder("ABCD").AddCustom("anonymous", true).Build(),
"random-key", "YO", "defaultVar", false, "", "SERVER", nil))
}
go func(dc exporter.Manager[exporter.FeatureEvent]) {
for _, event := range inputEvents {
dc.AddEvent(event)
// we have to wait because we are opening a new thread to slow down the flag evaluation.
time.Sleep(1 * time.Millisecond)
}
}(dc)

assert.Equal(t, 0, len(mockExporter2.GetExportedEvents()))
assert.Equal(t, 0, len(mockExporter1.GetExportedEvents()))
time.Sleep(70 * time.Millisecond)
assert.True(t, len(mockExporter1.GetExportedEvents()) > 0)
assert.True(t, len(mockExporter2.GetExportedEvents()) == 0)
time.Sleep(200 * time.Millisecond)
assert.True(t, len(mockExporter1.GetExportedEvents()) > 0)
assert.True(t, len(mockExporter2.GetExportedEvents()) > 0)
}
10 changes: 7 additions & 3 deletions exporter/package_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
// DataExporter: ffclient.DataExporter{
// FlushInterval: 10 * time.Second,
// MaxEventInMemory: 1000,
// DeprecatedExporter: &fileexporter.DeprecatedExporter{
// OutputDir: "/output-data/",
// },
// Exporter: &s3exporterv2.Exporter{
// Format: "json",
// Bucket: "my-test-bucket",
// S3Path: "/go-feature-flag/variations/",
// Filename: "flag-variation-{{ .Timestamp}}.{{ .Format}}",
// AwsConfig: &awsConfig,
// },
// },
// //...
// })
Expand Down

0 comments on commit 0c0996f

Please sign in to comment.