GoDoxy/internal/route/provider/event_handler.go

133 lines
3.6 KiB
Go

package provider
import (
"github.com/yusing/go-proxy/internal/common"
E "github.com/yusing/go-proxy/internal/error"
"github.com/yusing/go-proxy/internal/proxy/entry"
"github.com/yusing/go-proxy/internal/route"
"github.com/yusing/go-proxy/internal/task"
"github.com/yusing/go-proxy/internal/watcher"
)
type EventHandler struct {
provider *Provider
added []string
removed []string
paused []string
updated []string
errs E.Builder
}
func (provider *Provider) newEventHandler() *EventHandler {
return &EventHandler{
provider: provider,
errs: E.NewBuilder("event errors"),
}
}
func (handler *EventHandler) Handle(parent task.Task, events []watcher.Event) {
oldRoutes := handler.provider.routes
newRoutes, err := handler.provider.LoadRoutesImpl()
if err != nil {
handler.errs.Add(err.Subject("load routes"))
return
}
if common.IsDebug {
eventsLog := E.NewBuilder("events")
for _, event := range events {
eventsLog.Addf("event %s, actor: name=%s, id=%s", event.Action, event.ActorName, event.ActorID)
}
handler.provider.l.Debug(eventsLog.String())
oldRoutesLog := E.NewBuilder("old routes")
oldRoutes.RangeAll(func(k string, r *route.Route) {
oldRoutesLog.Addf(k)
})
handler.provider.l.Debug(oldRoutesLog.String())
newRoutesLog := E.NewBuilder("new routes")
newRoutes.RangeAll(func(k string, r *route.Route) {
newRoutesLog.Addf(k)
})
handler.provider.l.Debug(newRoutesLog.String())
}
oldRoutes.RangeAll(func(k string, oldr *route.Route) {
newr, ok := newRoutes.Load(k)
if !ok {
handler.Remove(oldr)
} else if handler.matchAny(events, newr) {
handler.Update(parent, oldr, newr)
} else if entry.ShouldNotServe(newr) {
handler.Remove(oldr)
}
})
newRoutes.RangeAll(func(k string, newr *route.Route) {
if !(oldRoutes.Has(k) || entry.ShouldNotServe(newr)) {
handler.Add(parent, newr)
}
})
}
func (handler *EventHandler) matchAny(events []watcher.Event, route *route.Route) bool {
for _, event := range events {
if handler.match(event, route) {
return true
}
}
return false
}
func (handler *EventHandler) match(event watcher.Event, route *route.Route) bool {
switch handler.provider.GetType() {
case ProviderTypeDocker:
return route.Entry.Container.ContainerID == event.ActorID ||
route.Entry.Container.ContainerName == event.ActorName
case ProviderTypeFile:
return true
}
// should never happen
return false
}
func (handler *EventHandler) Add(parent task.Task, route *route.Route) {
err := handler.provider.startRoute(parent, route)
if err != nil {
handler.errs.Add(E.FailWith("add "+route.Entry.Alias, err))
} else {
handler.added = append(handler.added, route.Entry.Alias)
}
}
func (handler *EventHandler) Remove(route *route.Route) {
route.Finish("route removed")
handler.provider.routes.Delete(route.Entry.Alias)
handler.removed = append(handler.removed, route.Entry.Alias)
}
func (handler *EventHandler) Update(parent task.Task, oldRoute *route.Route, newRoute *route.Route) {
oldRoute.Finish("route update")
err := handler.provider.startRoute(parent, newRoute)
if err != nil {
handler.errs.Add(E.FailWith("update "+newRoute.Entry.Alias, err))
} else {
handler.updated = append(handler.updated, newRoute.Entry.Alias)
}
}
func (handler *EventHandler) Log() {
results := E.NewBuilder("event occured")
for _, alias := range handler.added {
results.Addf("added %s", alias)
}
for _, alias := range handler.removed {
results.Addf("removed %s", alias)
}
for _, alias := range handler.updated {
results.Addf("updated %s", alias)
}
results.Add(handler.errs.Build())
if result := results.Build(); result != nil {
handler.provider.l.Info(result)
}
}