Skip to content

Commit 90b2dec

Browse files
authored
Adding Watchable and Closeable to ParserProvider interface (#2954)
* Adding Watchable and Closeable to ParserProvider interface * PR Feedback
1 parent 7b5b893 commit 90b2dec

File tree

3 files changed

+54
-6
lines changed

3 files changed

+54
-6
lines changed

service/application.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package service
1818

1919
import (
2020
"context"
21+
"errors"
2122
"flag"
2223
"fmt"
2324
"os"
@@ -32,6 +33,7 @@ import (
3233
"go.opentelemetry.io/collector/config/configcheck"
3334
"go.opentelemetry.io/collector/config/configloader"
3435
"go.opentelemetry.io/collector/config/configtelemetry"
36+
"go.opentelemetry.io/collector/config/experimental/configsource"
3537
"go.opentelemetry.io/collector/consumer/consumererror"
3638
"go.opentelemetry.io/collector/internal/collector/telemetry"
3739
"go.opentelemetry.io/collector/service/internal/builder"
@@ -254,6 +256,24 @@ func (app *Application) setupConfigurationComponents(ctx context.Context) error
254256
}
255257

256258
app.service = service
259+
260+
// If provider is watchable start a goroutine watching for updates.
261+
if watchable, ok := app.parserProvider.(parserprovider.Watchable); ok {
262+
go func() {
263+
err := watchable.WatchForUpdate()
264+
switch {
265+
// TODO: Move configsource.ErrSessionClosed to providerparser package to avoid depending on configsource.
266+
case errors.Is(err, configsource.ErrSessionClosed):
267+
// This is the case of shutdown of the whole application, nothing to do.
268+
app.logger.Info("Config WatchForUpdate closed", zap.Error(err))
269+
return
270+
default:
271+
app.logger.Warn("Config WatchForUpdated exited", zap.Error(err))
272+
app.reloadService(context.Background())
273+
}
274+
}()
275+
}
276+
257277
return nil
258278
}
259279

@@ -291,6 +311,12 @@ func (app *Application) execute(ctx context.Context) error {
291311
runtime.KeepAlive(ballast)
292312
app.logger.Info("Starting shutdown...")
293313

314+
if closable, ok := app.parserProvider.(parserprovider.Closeable); ok {
315+
if err := closable.Close(ctx); err != nil {
316+
errs = append(errs, fmt.Errorf("failed to close config: %w", err))
317+
}
318+
}
319+
294320
if app.service != nil {
295321
if err := app.service.Shutdown(ctx); err != nil {
296322
errs = append(errs, fmt.Errorf("failed to shutdown service: %w", err))
@@ -319,10 +345,16 @@ func (app *Application) createMemoryBallast() ([]byte, uint64) {
319345
return nil, 0
320346
}
321347

322-
// updateService shutdowns the current app.service and setups a new one according
348+
// reloadService shutdowns the current app.service and setups a new one according
323349
// to the latest configuration. It requires that app.parserProvider and app.factories
324350
// are properly populated to finish successfully.
325-
func (app *Application) updateService(ctx context.Context) error {
351+
func (app *Application) reloadService(ctx context.Context) error {
352+
if closeable, ok := app.parserProvider.(parserprovider.Closeable); ok {
353+
if err := closeable.Close(ctx); err != nil {
354+
return fmt.Errorf("failed close current config provider: %w", err)
355+
}
356+
}
357+
326358
if app.service != nil {
327359
retiringService := app.service
328360
app.service = nil

service/application_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func TestApplication_Start(t *testing.T) {
8989
assertMetrics(t, testPrefix, metricsPort, mandatoryLabels)
9090

9191
// Trigger another configuration load.
92-
require.NoError(t, app.updateService(context.Background()))
92+
require.NoError(t, app.reloadService(context.Background()))
9393
require.True(t, isAppAvailable(t, "http://"+healthCheckEndpoint))
9494

9595
app.signalsChannel <- syscall.SIGTERM
@@ -250,7 +250,7 @@ func (epl *errParserLoader) Get() (*config.Parser, error) {
250250
return nil, epl.err
251251
}
252252

253-
func TestApplication_updateService(t *testing.T) {
253+
func TestApplication_reloadService(t *testing.T) {
254254
factories, err := defaultcomponents.Components()
255255
require.NoError(t, err)
256256
ctx := context.Background()
@@ -304,7 +304,7 @@ func TestApplication_updateService(t *testing.T) {
304304
service: tt.service,
305305
}
306306

307-
err := app.updateService(ctx)
307+
err := app.reloadService(ctx)
308308

309309
if err != nil {
310310
assert.ErrorIs(t, err, sentinelError)

service/parserprovider/provider.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,27 @@
1414

1515
package parserprovider
1616

17-
import "go.opentelemetry.io/collector/config"
17+
import (
18+
"context"
19+
20+
"go.opentelemetry.io/collector/config"
21+
)
1822

1923
// ParserProvider is an interface that helps providing configuration's parser.
2024
// Implementations may load the parser from a file, a database or any other source.
2125
type ParserProvider interface {
2226
// Get returns the config.Parser if succeed or error otherwise.
2327
Get() (*config.Parser, error)
2428
}
29+
30+
// Watchable is an extension for ParserProvider that is implemented if the given provider
31+
// supports monitoring for configuration updates.
32+
type Watchable interface {
33+
// WatchForUpdate is used to monitor for updates on the retrieved value.
34+
WatchForUpdate() error
35+
}
36+
37+
// Closeable is an extension interface for ParserProvider that should be added if they need to be closed.
38+
type Closeable interface {
39+
Close(ctx context.Context) error
40+
}

0 commit comments

Comments
 (0)