Skip to content

Commit

Permalink
move from builtin map to struct
Browse files Browse the repository at this point in the history
  • Loading branch information
atoulme committed Dec 21, 2023
1 parent 1d6718b commit eb539b5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
26 changes: 19 additions & 7 deletions internal/sharedcomponent/sharedcomponent.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@ import (
)

// Map keeps reference of all created instances for a given shared key such as a component configuration.
type Map[K comparable, V component.Component] map[K]*Component[V]
type Map[K comparable, V component.Component] interface {
// LoadOrStore returns the already created instance if exists, otherwise creates a new instance
// and adds it to the map of references.
LoadOrStore(key K, create func() (V, error), telemetrySettings *component.TelemetrySettings) (*Component[V], error)
}

func NewMap[K comparable, V component.Component]() Map[K, V] {
return &mapImpl[K, V]{
components: map[K]*Component[V]{},
}
}

type mapImpl[K comparable, V component.Component] struct {
components map[K]*Component[V]
}

// LoadOrStore returns the already created instance if exists, otherwise creates a new instance
// and adds it to the map of references.
func (m Map[K, V]) LoadOrStore(key K, create func() (V, error), telemetrySettings *component.TelemetrySettings) (*Component[V], error) {
if c, ok := m[key]; ok {
func (m *mapImpl[K, V]) LoadOrStore(key K, create func() (V, error), telemetrySettings *component.TelemetrySettings) (*Component[V], error) {
if c, ok := m.components[key]; ok {
// If we haven't already seen this telemetry settings, this shared component represents
// another instance. Wrap ReportComponentStatus to report for all instances this shared
// component represents.
Expand All @@ -44,14 +56,14 @@ func (m Map[K, V]) LoadOrStore(key K, create func() (V, error), telemetrySetting
newComp := &Component[V]{
component: comp,
removeFunc: func() {
delete(m, key)
delete(m.components, key)
},
telemetry: telemetrySettings,
seenSettings: map[*component.TelemetrySettings]struct{}{
telemetrySettings: {},
},
}
m[key] = newComp
m.components[key] = newComp
return newComp, nil
}

Expand Down
26 changes: 13 additions & 13 deletions internal/sharedcomponent/sharedcomponent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,35 @@ type baseComponent struct {
telemetry *component.TelemetrySettings
}

func TestNewSharedComponents(t *testing.T) {
comps := Map[component.ID, *baseComponent]{}
assert.Len(t, comps, 0)
func TestNewMap(t *testing.T) {
comps := NewMap[component.ID, *baseComponent]()
assert.Len(t, comps.(*mapImpl[component.ID, *baseComponent]).components, 0)
}

func TestNewSharedComponentsCreateError(t *testing.T) {
comps := Map[component.ID, *baseComponent]{}
assert.Len(t, comps, 0)
comps := NewMap[component.ID, *baseComponent]().(*mapImpl[component.ID, *baseComponent])
assert.Len(t, comps.components, 0)
myErr := errors.New("my error")
_, err := comps.LoadOrStore(
id,
func() (*baseComponent, error) { return nil, myErr },
newNopTelemetrySettings(),
)
assert.ErrorIs(t, err, myErr)
assert.Len(t, comps, 0)
assert.Len(t, comps.components, 0)
}

func TestSharedComponentsLoadOrStore(t *testing.T) {
nop := &baseComponent{}

comps := Map[component.ID, *baseComponent]{}
comps := NewMap[component.ID, *baseComponent]()
got, err := comps.LoadOrStore(
id,
func() (*baseComponent, error) { return nop, nil },
newNopTelemetrySettings(),
)
require.NoError(t, err)
assert.Len(t, comps, 1)
assert.Len(t, comps.(*mapImpl[component.ID, *baseComponent]).components, 1)
assert.Same(t, nop, got.Unwrap())
gotSecond, err := comps.LoadOrStore(
id,
Expand All @@ -64,7 +64,7 @@ func TestSharedComponentsLoadOrStore(t *testing.T) {

// Shutdown nop will remove
assert.NoError(t, got.Shutdown(context.Background()))
assert.Len(t, comps, 0)
assert.Len(t, comps.(*mapImpl[component.ID, *baseComponent]).components, 0)
gotThird, err := comps.LoadOrStore(
id,
func() (*baseComponent, error) { return nop, nil },
Expand All @@ -88,7 +88,7 @@ func TestSharedComponent(t *testing.T) {
return wantErr
}}

comps := Map[component.ID, *baseComponent]{}
comps := NewMap[component.ID, *baseComponent]()
got, err := comps.LoadOrStore(
id,
func() (*baseComponent, error) { return comp, nil },
Expand Down Expand Up @@ -122,7 +122,7 @@ func TestSharedComponentsReportStatus(t *testing.T) {
}

comp := &baseComponent{}
comps := Map[component.ID, *baseComponent]{}
comps := NewMap[component.ID, *baseComponent]()
var telemetrySettings *component.TelemetrySettings

// make a shared component that represents three instances
Expand All @@ -141,7 +141,7 @@ func TestSharedComponentsReportStatus(t *testing.T) {
telemetrySettings,
)
require.NoError(t, err)
assert.Len(t, comps, 1)
assert.Len(t, comps.(*mapImpl[component.ID, *baseComponent]).components, 1)
assert.Same(t, comp, got.Unwrap())
}

Expand Down Expand Up @@ -245,7 +245,7 @@ func TestReportStatusOnStartShutdown(t *testing.T) {
return tc.shutdownErr
}
}
comps := Map[component.ID, *baseComponent]{}
comps := NewMap[component.ID, *baseComponent]()
var comp *Component[*baseComponent]
var err error
for i := 0; i < 3; i++ {
Expand Down
2 changes: 1 addition & 1 deletion receiver/otlpreceiver/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,4 @@ func createLog(
// create separate objects, they must use one otlpReceiver object per configuration.
// When the receiver is shutdown it should be removed from this map so the same configuration
// can be recreated successfully.
var receivers = sharedcomponent.Map[*Config, *otlpReceiver]{}
var receivers = sharedcomponent.NewMap[*Config, *otlpReceiver]()

0 comments on commit eb539b5

Please sign in to comment.