fixed idlewatcher panic, dashboard app name, route not removing on container destroy

This commit is contained in:
yusing
2024-10-16 00:57:10 +08:00
parent 56b778f19c
commit c0c61709ca
10 changed files with 53 additions and 56 deletions

View File

@@ -7,6 +7,7 @@ import (
"time"
"github.com/sirupsen/logrus"
E "github.com/yusing/go-proxy/internal/error"
gphttp "github.com/yusing/go-proxy/internal/net/http"
"github.com/yusing/go-proxy/internal/net/types"
"github.com/yusing/go-proxy/internal/watcher/health"
@@ -125,7 +126,7 @@ func (w *Waker) wake(rw http.ResponseWriter, r *http.Request) (shouldNext bool)
select {
case <-w.task.Context().Done():
http.Error(rw, "Waking timed out", http.StatusGatewayTimeout)
http.Error(rw, "Service unavailable", http.StatusServiceUnavailable)
return
case <-ctx.Done():
http.Error(rw, "Waking timed out", http.StatusGatewayTimeout)
@@ -133,12 +134,11 @@ func (w *Waker) wake(rw http.ResponseWriter, r *http.Request) (shouldNext bool)
default:
}
// wake the container and reset idle timer
// also wait for another wake request
w.wakeCh <- struct{}{}
if <-w.wakeDone != nil {
http.Error(rw, "Error sending wake request", http.StatusInternalServerError)
w.l.Debug("wake signal received")
err := w.wakeIfStopped()
if err != nil {
w.l.Error(E.FailWith("wake", err))
http.Error(rw, "Error waking container", http.StatusInternalServerError)
return
}
@@ -153,6 +153,9 @@ func (w *Waker) wake(rw http.ResponseWriter, r *http.Request) (shouldNext bool)
for {
select {
case <-w.task.Context().Done():
http.Error(rw, "Service unavailable", http.StatusServiceUnavailable)
return
case <-ctx.Done():
http.Error(rw, "Waking timed out", http.StatusGatewayTimeout)
return

View File

@@ -27,9 +27,7 @@ type (
ready atomic.Bool // whether the site is ready to accept connection
stopByMethod StopCallback // send a docker command w.r.t. `stop_method`
wakeCh chan struct{}
wakeDone chan E.NestedError
ticker *time.Ticker
ticker *time.Ticker
task common.Task
cancel context.CancelFunc
@@ -84,8 +82,6 @@ func Register(entry *P.ReverseProxyEntry) (*Watcher, E.NestedError) {
ReverseProxyEntry: entry,
client: client,
refCount: U.NewRefCounter(),
wakeCh: make(chan struct{}, 1),
wakeDone: make(chan E.NestedError),
ticker: time.NewTicker(entry.IdleTimeout),
l: logger.WithField("container", entry.ContainerName),
}
@@ -127,6 +123,9 @@ func (w *Watcher) containerStart() error {
}
func (w *Watcher) containerStatus() (string, E.NestedError) {
if !w.client.Connected() {
return "", E.Failure("docker client closed")
}
json, err := w.client.ContainerInspect(w.task.Context(), w.ContainerID)
if err != nil {
return "", E.FailWith("inspect container", err)
@@ -201,10 +200,9 @@ func (w *Watcher) watchUntilCancel() {
})
defer func() {
w.cancel()
w.ticker.Stop()
w.client.Close()
close(w.wakeDone)
close(w.wakeCh)
watcherMap.Delete(w.ContainerID)
w.task.Finished()
}()
@@ -220,6 +218,7 @@ func (w *Watcher) watchUntilCancel() {
case err := <-dockerEventErrCh:
if err != nil && err.IsNot(context.Canceled) {
w.l.Error(E.FailWith("docker watcher", err))
return
}
case e := <-dockerEventCh:
switch {
@@ -227,27 +226,22 @@ func (w *Watcher) watchUntilCancel() {
case e.Action.IsContainerWake():
w.ContainerRunning = true
w.resetIdleTimer()
w.l.Info(e)
default: // stop / pause / kil
w.l.Info("container awaken")
case e.Action.IsContainerSleep(): // stop / pause / kil
w.ContainerRunning = false
w.ticker.Stop()
w.ready.Store(false)
w.l.Info(e)
default:
w.l.Errorf("unexpected docker event: %s", e)
}
case <-w.ticker.C:
w.l.Debug("idle timeout")
w.ticker.Stop()
if err := w.stopByMethod(); err != nil && err.IsNot(context.Canceled) {
w.l.Error(E.FailWith("stop", err).Extraf("stop method: %s", w.StopMethod))
} else {
w.l.Info("stopped by idle timeout")
}
case <-w.wakeCh:
w.l.Debug("wake signal received")
w.resetIdleTimer()
err := w.wakeIfStopped()
if err != nil {
w.l.Error(E.FailWith("wake", err))
}
w.wakeDone <- err
}
}
}