diff --git a/app/app.go b/app/app.go index 21f2f52c..5aeda7f3 100644 --- a/app/app.go +++ b/app/app.go @@ -262,6 +262,15 @@ func (app *App) Start(ctx context.Context) (err error) { return } +// IterateComponents iterates over all registered components. It's safe for concurrent use. +func (app *App) IterateComponents(fn func(Component)) { + app.mu.RLock() + defer app.mu.RUnlock() + for _, s := range app.components { + fn(s) + } +} + func stackAllGoroutines() []byte { buf := make([]byte, 1024) for { diff --git a/app/app_test.go b/app/app_test.go index 0c122b24..5882feab 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -55,6 +55,21 @@ func TestAppServiceRegistry(t *testing.T) { }) } +func TestApp_IterateComponents(t *testing.T) { + app := new(App) + + app.Register(newTestService(testTypeRunnable, "c1", nil, nil)) + app.Register(newTestService(testTypeRunnable, "r1", nil, nil)) + app.Register(newTestService(testTypeComponent, "s1", nil, nil)) + + var got []string + app.IterateComponents(func(s Component) { + got = append(got, s.Name()) + }) + + assert.ElementsMatch(t, []string{"c1", "r1", "s1"}, got) +} + func TestAppStart(t *testing.T) { t.Run("SuccessStartStop", func(t *testing.T) { app := new(App)