diff --git a/pkg/provider/registry.go b/pkg/provider/registry.go index 3df69ba..fdd40c2 100644 --- a/pkg/provider/registry.go +++ b/pkg/provider/registry.go @@ -88,6 +88,24 @@ func (r *Registry) Streamable() []Streamable { return result } +// StreamableIter returns an iterator over all registered providers that +// implement the Streamable interface. +func (r *Registry) StreamableIter() iter.Seq[Streamable] { + r.mu.RLock() + providers := slices.Clone(r.providers) + r.mu.RUnlock() + + return func(yield func(Streamable) bool) { + for _, p := range providers { + if s, ok := p.(Streamable); ok { + if !yield(s) { + return + } + } + } + } +} + // Describable returns all providers that implement the Describable interface. func (r *Registry) Describable() []Describable { r.mu.RLock() @@ -101,6 +119,24 @@ func (r *Registry) Describable() []Describable { return result } +// DescribableIter returns an iterator over all registered providers that +// implement the Describable interface. +func (r *Registry) DescribableIter() iter.Seq[Describable] { + r.mu.RLock() + providers := slices.Clone(r.providers) + r.mu.RUnlock() + + return func(yield func(Describable) bool) { + for _, p := range providers { + if d, ok := p.(Describable); ok { + if !yield(d) { + return + } + } + } + } +} + // Renderable returns all providers that implement the Renderable interface. func (r *Registry) Renderable() []Renderable { r.mu.RLock() @@ -114,6 +150,24 @@ func (r *Registry) Renderable() []Renderable { return result } +// RenderableIter returns an iterator over all registered providers that +// implement the Renderable interface. +func (r *Registry) RenderableIter() iter.Seq[Renderable] { + r.mu.RLock() + providers := slices.Clone(r.providers) + r.mu.RUnlock() + + return func(yield func(Renderable) bool) { + for _, p := range providers { + if rv, ok := p.(Renderable); ok { + if !yield(rv) { + return + } + } + } + } +} + // ProviderInfo is a serialisable summary of a registered provider. type ProviderInfo struct { Name string `json:"name"` diff --git a/pkg/provider/registry_test.go b/pkg/provider/registry_test.go index dab9fe6..37d2fb2 100644 --- a/pkg/provider/registry_test.go +++ b/pkg/provider/registry_test.go @@ -119,6 +119,36 @@ func TestRegistry_Streamable_Good(t *testing.T) { assert.Equal(t, []string{"stub.event"}, s[0].Channels()) } +func TestRegistry_StreamableIter_Good(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&stubProvider{}) + reg.Add(&streamableProvider{}) + + var streamables []provider.Streamable + for s := range reg.StreamableIter() { + streamables = append(streamables, s) + } + + assert.Len(t, streamables, 1) + assert.Equal(t, []string{"stub.event"}, streamables[0].Channels()) +} + +func TestRegistry_StreamableIter_Good_SnapshotCurrentProviders(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&streamableProvider{}) + + iter := reg.StreamableIter() + reg.Add(&streamableProvider{}) + + var streamables []provider.Streamable + for s := range iter { + streamables = append(streamables, s) + } + + assert.Len(t, streamables, 1) + assert.Equal(t, []string{"stub.event"}, streamables[0].Channels()) +} + func TestRegistry_Describable_Good(t *testing.T) { reg := provider.NewRegistry() reg.Add(&stubProvider{}) // not describable @@ -129,6 +159,36 @@ func TestRegistry_Describable_Good(t *testing.T) { assert.Len(t, d[0].Describe(), 1) } +func TestRegistry_DescribableIter_Good(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&stubProvider{}) + reg.Add(&describableProvider{}) + + var describables []provider.Describable + for d := range reg.DescribableIter() { + describables = append(describables, d) + } + + assert.Len(t, describables, 1) + assert.Len(t, describables[0].Describe(), 1) +} + +func TestRegistry_DescribableIter_Good_SnapshotCurrentProviders(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&describableProvider{}) + + iter := reg.DescribableIter() + reg.Add(&describableProvider{}) + + var describables []provider.Describable + for d := range iter { + describables = append(describables, d) + } + + assert.Len(t, describables, 1) + assert.Len(t, describables[0].Describe(), 1) +} + func TestRegistry_Renderable_Good(t *testing.T) { reg := provider.NewRegistry() reg.Add(&stubProvider{}) // not renderable @@ -139,6 +199,36 @@ func TestRegistry_Renderable_Good(t *testing.T) { assert.Equal(t, "core-stub-panel", r[0].Element().Tag) } +func TestRegistry_RenderableIter_Good(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&stubProvider{}) + reg.Add(&renderableProvider{}) + + var renderables []provider.Renderable + for r := range reg.RenderableIter() { + renderables = append(renderables, r) + } + + assert.Len(t, renderables, 1) + assert.Equal(t, "core-stub-panel", renderables[0].Element().Tag) +} + +func TestRegistry_RenderableIter_Good_SnapshotCurrentProviders(t *testing.T) { + reg := provider.NewRegistry() + reg.Add(&renderableProvider{}) + + iter := reg.RenderableIter() + reg.Add(&renderableProvider{}) + + var renderables []provider.Renderable + for r := range iter { + renderables = append(renderables, r) + } + + assert.Len(t, renderables, 1) + assert.Equal(t, "core-stub-panel", renderables[0].Element().Tag) +} + func TestRegistry_Info_Good(t *testing.T) { reg := provider.NewRegistry() reg.Add(&fullProvider{})