Skip to content

Commit

Permalink
service: imp docs, code
Browse files Browse the repository at this point in the history
  • Loading branch information
ainar-g committed Jan 17, 2025
1 parent 431b202 commit 9a5b97a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 54 deletions.
23 changes: 23 additions & 0 deletions service/errorhandler_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package service_test

import (
"context"
"log/slog"

"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/service"
)

func ExampleSlogErrorHandler() {
logger := slogutil.New(&slogutil.Config{
Format: slogutil.FormatJSON,
})

h := service.NewSlogErrorHandler(logger, slog.LevelError, "test message")

h.Handle(context.Background(), errors.Error("test error"))

// Output:
// {"level":"ERROR","msg":"test message","err":"test error"}
}
42 changes: 0 additions & 42 deletions service/errorhandler_test.go

This file was deleted.

15 changes: 15 additions & 0 deletions service/refresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import (

// Refresher is the interface for entities that can update themselves.
type Refresher interface {
// Refresh is a method that is called to perform some kind of a job on an
// entity. Typically, this means updating some data or sending data
// somewhere else.
//
// See [RefreshWorker] for one of the uses.
Refresh(ctx context.Context) (err error)
}

Expand All @@ -18,3 +23,13 @@ var _ Refresher = RefresherFunc(nil)

// Refresh implements the [Refresher] interface for RefresherFunc.
func (f RefresherFunc) Refresh(ctx context.Context) (err error) { return f(ctx) }

// EmptyRefresher is a [Refresher] that does nothing.
type EmptyRefresher struct{}

// type check
var _ Refresher = EmptyRefresher{}

// Refresh implements the [Refresher] interface for EmptyRefresher. It returns
// nil immediately.
func (EmptyRefresher) Refresh(_ context.Context) (err error) { return nil }
25 changes: 13 additions & 12 deletions service/refreshworker.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ type RefreshWorkerConfig struct {
// [RefreshWorkerConfig.ErrorHandler] is used.
Refresher Refresher

// Schedule defines when a refresher is run. It must not be nil.
// Schedule defines when a refresher is run. Schedule.UntilNext is called
// after each refresh to determine how long the worker sleeps until the next
// refresh. It must not be nil.
Schedule timeutil.Schedule

// RefreshOnShutdown, if true, instructs the worker to refresh before
Expand Down Expand Up @@ -90,20 +92,19 @@ func (w *RefreshWorker) Start(ctx context.Context) (err error) {
func (w *RefreshWorker) refreshInALoop(ctx context.Context) {
defer slogutil.RecoverAndLogDefault(ctx)

sleepTime := w.schedule.UntilNext(w.clock.Now())
waitDur := w.schedule.UntilNext(w.clock.Now())

for {
select {
case <-w.done:

return
case <-w.clock.After(sleepTime):
case <-w.clock.After(waitDur):
err := w.refresh(ctx)
if err != nil {
w.errHdlr.Handle(ctx, err)
}

sleepTime = w.schedule.UntilNext(w.clock.Now())
waitDur = w.schedule.UntilNext(w.clock.Now())
}
}
}
Expand All @@ -119,15 +120,15 @@ func (w *RefreshWorker) refresh(ctx context.Context) (err error) {

// Shutdown implements the [Interface] interface for *RefreshWorker.
func (w *RefreshWorker) Shutdown(ctx context.Context) (err error) {
if w.refrOnShutdown {
err = w.refresh(ctx)
}

close(w.done)

if err != nil {
err = fmt.Errorf("refresh on shutdown: %w", err)
if w.refrOnShutdown {
// TODO(a.garipov): Ensure that a refresh isn't already running.
err = w.refresh(ctx)
if err != nil {
return fmt.Errorf("refresh on shutdown: %w", err)
}
}

return err
return nil
}

0 comments on commit 9a5b97a

Please sign in to comment.