mirror of
https://github.com/yusing/godoxy.git
synced 2025-07-21 20:04:03 +02:00
feat: enhance idlewaker loading page design and add favicon handling in waker_http, removed unnecessary checkings
This commit is contained in:
parent
1c001ed9df
commit
d105f866ff
8 changed files with 201 additions and 132 deletions
|
@ -37,12 +37,14 @@ var (
|
||||||
clientMapMu sync.RWMutex
|
clientMapMu sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var initClientCleanerOnce sync.Once
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cleanInterval = 10 * time.Second
|
cleanInterval = 10 * time.Second
|
||||||
clientTTLSecs = int64(10)
|
clientTTLSecs = int64(10)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func initClientCleaner() {
|
||||||
cleaner := task.RootTask("docker_clients_cleaner")
|
cleaner := task.RootTask("docker_clients_cleaner")
|
||||||
go func() {
|
go func() {
|
||||||
ticker := time.NewTicker(cleanInterval)
|
ticker := time.NewTicker(cleanInterval)
|
||||||
|
@ -115,6 +117,8 @@ func (c *SharedClient) Close() {
|
||||||
// - Client: the Docker client connection.
|
// - Client: the Docker client connection.
|
||||||
// - error: an error if the connection failed.
|
// - error: an error if the connection failed.
|
||||||
func NewClient(host string) (*SharedClient, error) {
|
func NewClient(host string) (*SharedClient, error) {
|
||||||
|
initClientCleanerOnce.Do(initClientCleaner)
|
||||||
|
|
||||||
clientMapMu.Lock()
|
clientMapMu.Lock()
|
||||||
defer clientMapMu.Unlock()
|
defer clientMapMu.Unlock()
|
||||||
|
|
||||||
|
|
|
@ -18,33 +18,41 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (w *Watcher) ContainerID() string {
|
||||||
|
return w.route.ContainerInfo().ContainerID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Watcher) ContainerName() string {
|
||||||
|
return w.route.ContainerInfo().ContainerName
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerStop(ctx context.Context) error {
|
func (w *Watcher) containerStop(ctx context.Context) error {
|
||||||
return w.client.ContainerStop(ctx, w.ContainerID, container.StopOptions{
|
return w.client.ContainerStop(ctx, w.ContainerID(), container.StopOptions{
|
||||||
Signal: string(w.StopSignal),
|
Signal: string(w.Config().StopSignal),
|
||||||
Timeout: &w.StopTimeout,
|
Timeout: &w.Config().StopTimeout,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerPause(ctx context.Context) error {
|
func (w *Watcher) containerPause(ctx context.Context) error {
|
||||||
return w.client.ContainerPause(ctx, w.ContainerID)
|
return w.client.ContainerPause(ctx, w.ContainerID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerKill(ctx context.Context) error {
|
func (w *Watcher) containerKill(ctx context.Context) error {
|
||||||
return w.client.ContainerKill(ctx, w.ContainerID, string(w.StopSignal))
|
return w.client.ContainerKill(ctx, w.ContainerID(), string(w.Config().StopSignal))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerUnpause(ctx context.Context) error {
|
func (w *Watcher) containerUnpause(ctx context.Context) error {
|
||||||
return w.client.ContainerUnpause(ctx, w.ContainerID)
|
return w.client.ContainerUnpause(ctx, w.ContainerID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerStart(ctx context.Context) error {
|
func (w *Watcher) containerStart(ctx context.Context) error {
|
||||||
return w.client.ContainerStart(ctx, w.ContainerID, container.StartOptions{})
|
return w.client.ContainerStart(ctx, w.ContainerID(), container.StartOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) containerStatus() (string, error) {
|
func (w *Watcher) containerStatus() (string, error) {
|
||||||
ctx, cancel := context.WithTimeoutCause(w.task.Context(), dockerReqTimeout, errors.New("docker request timeout"))
|
ctx, cancel := context.WithTimeoutCause(w.task.Context(), dockerReqTimeout, errors.New("docker request timeout"))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
json, err := w.client.ContainerInspect(ctx, w.ContainerID)
|
json, err := w.client.ContainerInspect(ctx, w.ContainerID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{{.Title}}</title>
|
<title>{{.Title}}</title>
|
||||||
<style>
|
<style>
|
||||||
|
/* size variables */
|
||||||
|
:root {
|
||||||
|
--dot-size: 12px;
|
||||||
|
--logo-size: 100px;
|
||||||
|
}
|
||||||
/* Global Styles */
|
/* Global Styles */
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -12,58 +17,109 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
font-family: Inter, Arial, sans-serif;
|
font-family:
|
||||||
|
"Inter",
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"Segoe UI",
|
||||||
|
Roboto,
|
||||||
|
Oxygen,
|
||||||
|
Ubuntu,
|
||||||
|
Cantarell,
|
||||||
|
"Open Sans",
|
||||||
|
"Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #fff;
|
color: #f8f9fa;
|
||||||
background-color: #212121;
|
background-color: #121212;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
gap: 32px;
|
||||||
|
background: linear-gradient(135deg, #121212 0%, #1e1e1e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 48px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background-color: rgba(30, 30, 30, 0.6);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
max-width: 90%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spinner Styles */
|
/* Spinner Styles */
|
||||||
.spinner {
|
.loading-dots {
|
||||||
width: 120px;
|
display: flex;
|
||||||
height: 120px;
|
|
||||||
border: 16px solid #333;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top: 16px solid #66d9ef;
|
|
||||||
animation: spin 2s linear infinite;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error Styles */
|
|
||||||
.error {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
.dot {
|
||||||
|
width: var(--dot-size);
|
||||||
|
height: var(--dot-size);
|
||||||
|
background-color: #66d9ef;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: bounce 1.3s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
.dot:nth-child(1) {
|
||||||
|
animation-delay: -0.32s;
|
||||||
|
}
|
||||||
|
.dot:nth-child(2) {
|
||||||
|
animation-delay: -0.16s;
|
||||||
|
}
|
||||||
|
@keyframes bounce {
|
||||||
|
0%,
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
.error::before {
|
|
||||||
content: "\26A0"; /* Unicode for warning symbol */
|
|
||||||
font-size: 40px;
|
|
||||||
color: #ff9900;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Message Styles */
|
/* Message Styles */
|
||||||
.message {
|
.message {
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
font-weight: bold;
|
font-weight: 500;
|
||||||
padding-left: 32px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
color: #f8f9fa;
|
||||||
|
max-width: 500px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo */
|
||||||
|
.logo {
|
||||||
|
width: var(--logo-size);
|
||||||
|
height: var(--logo-size);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<!-- icon handled by waker_http -->
|
||||||
|
<img class="logo" src="/favicon.ico" />
|
||||||
|
<div id="loading-dots" class="loading-dots">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<div class="dot"></div>
|
||||||
|
<div class="dot"></div>
|
||||||
|
</div>
|
||||||
|
<div id="message" class="message">{{.Message}}</div>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
window.onload = async function () {
|
window.onload = async function () {
|
||||||
let resp = await fetch(window.location.href, {
|
let resp = await fetch(window.location.href, {
|
||||||
|
@ -74,15 +130,10 @@
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
window.location.href = resp.url;
|
window.location.href = resp.url;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("message").innerText =
|
document.getElementById("message").innerText = await resp.text();
|
||||||
await resp.text();
|
document.getElementById("loading-dots").remove();
|
||||||
document
|
|
||||||
.getElementById("spinner")
|
|
||||||
.classList.replace("spinner", "error");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<div id="spinner" class="spinner"></div>
|
|
||||||
<div id="message" class="message">{{.Message}}</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,7 +3,6 @@ package idlewatcher
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
||||||
|
@ -20,12 +19,12 @@ var loadingPage []byte
|
||||||
var loadingPageTmpl = template.Must(template.New("loading_page").Parse(string(loadingPage)))
|
var loadingPageTmpl = template.Must(template.New("loading_page").Parse(string(loadingPage)))
|
||||||
|
|
||||||
func (w *Watcher) makeLoadingPageBody() []byte {
|
func (w *Watcher) makeLoadingPageBody() []byte {
|
||||||
msg := w.ContainerName + " is starting..."
|
msg := w.ContainerName() + " is starting..."
|
||||||
|
|
||||||
data := new(templateData)
|
data := new(templateData)
|
||||||
data.CheckRedirectHeader = httpheaders.HeaderGoDoxyCheckRedirect
|
data.CheckRedirectHeader = httpheaders.HeaderGoDoxyCheckRedirect
|
||||||
data.Title = w.ContainerName
|
data.Title = w.route.HomepageItem().Name
|
||||||
data.Message = strings.ReplaceAll(msg, " ", " ")
|
data.Message = msg
|
||||||
|
|
||||||
buf := bytes.NewBuffer(make([]byte, len(loadingPage)+len(data.Title)+len(data.Message)+len(httpheaders.HeaderGoDoxyCheckRedirect)))
|
buf := bytes.NewBuffer(make([]byte, len(loadingPage)+len(data.Title)+len(data.Message)+len(httpheaders.HeaderGoDoxyCheckRedirect)))
|
||||||
err := loadingPageTmpl.Execute(buf, data)
|
err := loadingPageTmpl.Execute(buf, data)
|
||||||
|
|
|
@ -100,7 +100,7 @@ func (w *Watcher) Name() string {
|
||||||
|
|
||||||
// String implements health.HealthMonitor.
|
// String implements health.HealthMonitor.
|
||||||
func (w *Watcher) String() string {
|
func (w *Watcher) String() string {
|
||||||
return w.ContainerName
|
return w.ContainerName()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uptime implements health.HealthMonitor.
|
// Uptime implements health.HealthMonitor.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/yusing/go-proxy/internal/api/v1/favicon"
|
||||||
gphttp "github.com/yusing/go-proxy/internal/net/gphttp"
|
gphttp "github.com/yusing/go-proxy/internal/net/gphttp"
|
||||||
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
||||||
)
|
)
|
||||||
|
@ -55,6 +56,10 @@ func (w *Watcher) cancelled(reqCtx context.Context, rw http.ResponseWriter) bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isFaviconPath(path string) bool {
|
||||||
|
return path == "/favicon.ico"
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Watcher) wakeFromHTTP(rw http.ResponseWriter, r *http.Request) (shouldNext bool) {
|
func (w *Watcher) wakeFromHTTP(rw http.ResponseWriter, r *http.Request) (shouldNext bool) {
|
||||||
w.resetIdleTimer()
|
w.resetIdleTimer()
|
||||||
|
|
||||||
|
@ -63,8 +68,15 @@ func (w *Watcher) wakeFromHTTP(rw http.ResponseWriter, r *http.Request) (shouldN
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle favicon request
|
||||||
|
if isFaviconPath(r.URL.Path) {
|
||||||
|
r.URL.RawQuery = "alias=" + w.route.TargetName()
|
||||||
|
favicon.GetFavIcon(rw, r)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Check if start endpoint is configured and request path matches
|
// Check if start endpoint is configured and request path matches
|
||||||
if w.StartEndpoint != "" && r.URL.Path != w.StartEndpoint {
|
if w.Config().StartEndpoint != "" && r.URL.Path != w.Config().StartEndpoint {
|
||||||
http.Error(rw, "Forbidden: Container can only be started via configured start endpoint", http.StatusForbidden)
|
http.Error(rw, "Forbidden: Container can only be started via configured start endpoint", http.StatusForbidden)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -88,7 +100,7 @@ func (w *Watcher) wakeFromHTTP(rw http.ResponseWriter, r *http.Request) (shouldN
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeoutCause(r.Context(), w.WakeTimeout, errors.New("wake timeout"))
|
ctx, cancel := context.WithTimeoutCause(r.Context(), w.Config().WakeTimeout, errors.New("wake timeout"))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if w.cancelled(ctx, rw) {
|
if w.cancelled(ctx, rw) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (w *Watcher) wakeFromStream() error {
|
||||||
return wakeErr
|
return wakeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeoutCause(w.task.Context(), w.WakeTimeout, errors.New("wake timeout"))
|
ctx, cancel := context.WithTimeoutCause(w.task.Context(), w.Config().WakeTimeout, errors.New("wake timeout"))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -26,8 +26,8 @@ type (
|
||||||
zerolog.Logger
|
zerolog.Logger
|
||||||
|
|
||||||
*waker
|
*waker
|
||||||
*containerMeta
|
|
||||||
*idlewatcher.Config
|
route route.Route
|
||||||
|
|
||||||
client *docker.SharedClient
|
client *docker.SharedClient
|
||||||
state atomic.Value[*containerState]
|
state atomic.Value[*containerState]
|
||||||
|
@ -52,11 +52,6 @@ const dockerReqTimeout = 3 * time.Second
|
||||||
|
|
||||||
func registerWatcher(parent task.Parent, route route.Route, waker *waker) (*Watcher, error) {
|
func registerWatcher(parent task.Parent, route route.Route, waker *waker) (*Watcher, error) {
|
||||||
cfg := route.IdlewatcherConfig()
|
cfg := route.IdlewatcherConfig()
|
||||||
|
|
||||||
if cfg.IdleTimeout == 0 {
|
|
||||||
panic(errShouldNotReachHere)
|
|
||||||
}
|
|
||||||
|
|
||||||
cont := route.ContainerInfo()
|
cont := route.ContainerInfo()
|
||||||
key := cont.ContainerID
|
key := cont.ContainerID
|
||||||
|
|
||||||
|
@ -79,11 +74,7 @@ func registerWatcher(parent task.Parent, route route.Route, waker *waker) (*Watc
|
||||||
|
|
||||||
// FIXME: possible race condition here
|
// FIXME: possible race condition here
|
||||||
w.waker = waker
|
w.waker = waker
|
||||||
w.containerMeta = &containerMeta{
|
w.route = route
|
||||||
ContainerID: cont.ContainerID,
|
|
||||||
ContainerName: cont.ContainerName,
|
|
||||||
}
|
|
||||||
w.Config = cfg
|
|
||||||
w.ticker.Reset(cfg.IdleTimeout)
|
w.ticker.Reset(cfg.IdleTimeout)
|
||||||
|
|
||||||
if cont.Running {
|
if cont.Running {
|
||||||
|
@ -112,6 +103,10 @@ func registerWatcher(parent task.Parent, route route.Route, waker *waker) (*Watc
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Watcher) Config() *idlewatcher.Config {
|
||||||
|
return w.route.IdlewatcherConfig()
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Watcher) Wake() error {
|
func (w *Watcher) Wake() error {
|
||||||
return w.wakeIfStopped()
|
return w.wakeIfStopped()
|
||||||
}
|
}
|
||||||
|
@ -141,7 +136,7 @@ func (w *Watcher) wakeIfStopped() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(w.task.Context(), w.WakeTimeout)
|
ctx, cancel := context.WithTimeout(w.task.Context(), w.Config().WakeTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// !Hard coded here since theres no constants from Docker API
|
// !Hard coded here since theres no constants from Docker API
|
||||||
|
@ -159,7 +154,7 @@ func (w *Watcher) wakeIfStopped() error {
|
||||||
|
|
||||||
func (w *Watcher) getStopCallback() StopCallback {
|
func (w *Watcher) getStopCallback() StopCallback {
|
||||||
var cb func(context.Context) error
|
var cb func(context.Context) error
|
||||||
switch w.StopMethod {
|
switch w.Config().StopMethod {
|
||||||
case idlewatcher.StopMethodPause:
|
case idlewatcher.StopMethodPause:
|
||||||
cb = w.containerPause
|
cb = w.containerPause
|
||||||
case idlewatcher.StopMethodStop:
|
case idlewatcher.StopMethodStop:
|
||||||
|
@ -170,7 +165,7 @@ func (w *Watcher) getStopCallback() StopCallback {
|
||||||
panic(errShouldNotReachHere)
|
panic(errShouldNotReachHere)
|
||||||
}
|
}
|
||||||
return func() error {
|
return func() error {
|
||||||
ctx, cancel := context.WithTimeout(w.task.Context(), time.Duration(w.StopTimeout)*time.Second)
|
ctx, cancel := context.WithTimeout(w.task.Context(), time.Duration(w.Config().StopTimeout)*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return cb(ctx)
|
return cb(ctx)
|
||||||
}
|
}
|
||||||
|
@ -178,19 +173,19 @@ func (w *Watcher) getStopCallback() StopCallback {
|
||||||
|
|
||||||
func (w *Watcher) resetIdleTimer() {
|
func (w *Watcher) resetIdleTimer() {
|
||||||
w.Trace().Msg("reset idle timer")
|
w.Trace().Msg("reset idle timer")
|
||||||
w.ticker.Reset(w.IdleTimeout)
|
w.ticker.Reset(w.Config().IdleTimeout)
|
||||||
w.lastReset = time.Now()
|
w.lastReset = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) expires() time.Time {
|
func (w *Watcher) expires() time.Time {
|
||||||
return w.lastReset.Add(w.IdleTimeout)
|
return w.lastReset.Add(w.Config().IdleTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Watcher) getEventCh(ctx context.Context, dockerWatcher *watcher.DockerWatcher) (eventCh <-chan events.Event, errCh <-chan gperr.Error) {
|
func (w *Watcher) getEventCh(ctx context.Context, dockerWatcher *watcher.DockerWatcher) (eventCh <-chan events.Event, errCh <-chan gperr.Error) {
|
||||||
eventCh, errCh = dockerWatcher.EventsWithOptions(ctx, watcher.DockerListOptions{
|
eventCh, errCh = dockerWatcher.EventsWithOptions(ctx, watcher.DockerListOptions{
|
||||||
Filters: watcher.NewDockerFilter(
|
Filters: watcher.NewDockerFilter(
|
||||||
watcher.DockerFilterContainer,
|
watcher.DockerFilterContainer,
|
||||||
watcher.DockerFilterContainerNameID(w.ContainerID),
|
watcher.DockerFilterContainerNameID(w.route.ContainerInfo().ContainerID),
|
||||||
watcher.DockerFilterStart,
|
watcher.DockerFilterStart,
|
||||||
watcher.DockerFilterStop,
|
watcher.DockerFilterStop,
|
||||||
watcher.DockerFilterDie,
|
watcher.DockerFilterDie,
|
||||||
|
@ -249,20 +244,20 @@ func (w *Watcher) watchUntilDestroy() (returnCause error) {
|
||||||
w.Error().Msg("unexpected docker event: " + e.String())
|
w.Error().Msg("unexpected docker event: " + e.String())
|
||||||
}
|
}
|
||||||
// container name changed should also change the container id
|
// container name changed should also change the container id
|
||||||
if w.ContainerName != e.ActorName {
|
// if w.ContainerName != e.ActorName {
|
||||||
w.Debug().Msgf("renamed %s -> %s", w.ContainerName, e.ActorName)
|
// w.Debug().Msgf("renamed %s -> %s", w.ContainerName, e.ActorName)
|
||||||
w.ContainerName = e.ActorName
|
// w.ContainerName = e.ActorName
|
||||||
}
|
// }
|
||||||
if w.ContainerID != e.ActorID {
|
// if w.ContainerID != e.ActorID {
|
||||||
w.Debug().Msgf("id changed %s -> %s", w.ContainerID, e.ActorID)
|
// w.Debug().Msgf("id changed %s -> %s", w.ContainerID, e.ActorID)
|
||||||
w.ContainerID = e.ActorID
|
// w.ContainerID = e.ActorID
|
||||||
// recreate event stream
|
// // recreate event stream
|
||||||
eventCancel()
|
// eventCancel()
|
||||||
|
|
||||||
eventCtx, eventCancel = context.WithCancel(w.task.Context())
|
// eventCtx, eventCancel = context.WithCancel(w.task.Context())
|
||||||
defer eventCancel()
|
// defer eventCancel()
|
||||||
dockerEventCh, dockerEventErrCh = w.getEventCh(eventCtx, dockerWatcher)
|
// dockerEventCh, dockerEventErrCh = w.getEventCh(eventCtx, dockerWatcher)
|
||||||
}
|
// }
|
||||||
case <-w.ticker.C:
|
case <-w.ticker.C:
|
||||||
w.ticker.Stop()
|
w.ticker.Stop()
|
||||||
if w.running() {
|
if w.running() {
|
||||||
|
@ -274,7 +269,7 @@ func (w *Watcher) watchUntilDestroy() (returnCause error) {
|
||||||
if errors.Is(err, context.DeadlineExceeded) {
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
err = errors.New("timeout waiting for container to stop, please set a higher value for `stop_timeout`")
|
err = errors.New("timeout waiting for container to stop, please set a higher value for `stop_timeout`")
|
||||||
}
|
}
|
||||||
w.Err(err).Msgf("container stop with method %q failed", w.StopMethod)
|
w.Err(err).Msgf("container stop with method %q failed", w.Config().StopMethod)
|
||||||
default:
|
default:
|
||||||
w.Info().Str("reason", "idle timeout").Msg("container stopped")
|
w.Info().Str("reason", "idle timeout").Msg("container stopped")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue