This commit is contained in:
yusing
2026-02-16 08:59:01 +08:00
parent 15b9635ee1
commit e4e6f6b3e8
242 changed files with 3953 additions and 3502 deletions

View File

@@ -3,6 +3,7 @@ package watcher
import (
"context"
"errors"
"fmt"
"time"
dockerEvents "github.com/docker/docker/api/types/events"
@@ -11,8 +12,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/yusing/godoxy/internal/docker"
"github.com/yusing/godoxy/internal/types"
"github.com/yusing/godoxy/internal/watcher/events"
gperr "github.com/yusing/goutils/errs"
watcherEvents "github.com/yusing/godoxy/internal/watcher/events"
)
type (
@@ -46,8 +46,8 @@ var (
dockerWatcherRetryInterval = 3 * time.Second
reloadTrigger = Event{
Type: events.EventTypeDocker,
Action: events.ActionForceReload,
Type: watcherEvents.EventTypeDocker,
Action: watcherEvents.ActionForceReload,
ActorAttributes: map[string]string{},
ActorName: "",
ActorID: "",
@@ -64,18 +64,21 @@ func NewDockerWatcher(dockerCfg types.DockerProviderConfig) DockerWatcher {
}
}
func (w DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan gperr.Error) {
var _ Watcher = (*DockerWatcher)(nil)
// Events implements the Watcher interface.
func (w DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan error) {
return w.EventsWithOptions(ctx, optionsDefault)
}
func (w DockerWatcher) EventsWithOptions(ctx context.Context, options DockerListOptions) (<-chan Event, <-chan gperr.Error) {
func (w DockerWatcher) EventsWithOptions(ctx context.Context, options DockerListOptions) (<-chan Event, <-chan error) {
eventCh := make(chan Event)
errCh := make(chan gperr.Error)
errCh := make(chan error)
go func() {
client, err := docker.NewClient(w.cfg)
if err != nil {
errCh <- gperr.Wrap(err, "docker watcher: failed to initialize client")
errCh <- fmt.Errorf("docker watcher: failed to initialize client: %w", err)
return
}
@@ -105,20 +108,19 @@ func (w DockerWatcher) EventsWithOptions(ctx context.Context, options DockerList
eventCh <- reloadTrigger
retry := time.NewTicker(dockerWatcherRetryInterval)
defer retry.Stop()
ok := false
outer:
for !ok {
for {
select {
case <-ctx.Done():
retry.Stop()
return
case <-retry.C:
if checkConnection(ctx, client) {
ok = true
break outer
}
}
}
retry.Stop()
// connection successful, trigger reload (reload routes)
eventCh <- reloadTrigger
// reopen event channel
@@ -130,23 +132,23 @@ func (w DockerWatcher) EventsWithOptions(ctx context.Context, options DockerList
return eventCh, errCh
}
func (w DockerWatcher) parseError(err error) gperr.Error {
func (w DockerWatcher) parseError(err error) error {
if errors.Is(err, context.DeadlineExceeded) {
return gperr.New("docker client connection timeout")
return errors.New("docker client connection timeout")
}
if client.IsErrConnectionFailed(err) {
return gperr.New("docker client connection failure")
return errors.New("docker client connection failure")
}
return gperr.Wrap(err)
return err
}
func (w DockerWatcher) handleEvent(event dockerEvents.Message, ch chan<- Event) {
action, ok := events.DockerEventMap[event.Action]
action, ok := watcherEvents.DockerEventMap[event.Action]
if !ok {
return
}
ch <- Event{
Type: events.EventTypeDocker,
Type: watcherEvents.EventTypeDocker,
ActorID: event.Actor.ID,
ActorAttributes: event.Actor.Attributes, // labels
ActorName: event.Actor.Attributes["name"],