Files
yusing b7250b29e0 fix(idlewatcher): improve container readiness handling in wakeFromHTTP
- Updated the wakeFromHTTP method to send a 100 Continue response to prevent client wait-header timeout.
- Implemented logic for non-HTML requests to wait for the container to become ready, returning an error message if it times out, or redirecting if successful.
- Adjusted the waitForReady method to return true upon receiving a ready notification.
2025-12-17 10:30:06 +08:00

92 lines
2.0 KiB
Go

package idlewatcher
import (
"context"
"time"
idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types"
)
func (w *Watcher) running() bool {
return w.state.Load().status == idlewatcher.ContainerStatusRunning
}
func (w *Watcher) ready() bool {
return w.state.Load().ready
}
func (w *Watcher) error() error {
return w.state.Load().err
}
func (w *Watcher) setReady() {
w.state.Store(&containerState{
status: idlewatcher.ContainerStatusRunning,
ready: true,
})
// Send ready event via SSE
w.sendEvent(WakeEventReady, w.cfg.ContainerName()+" is ready!", nil)
// Notify waiting handlers that container is ready
select {
case w.readyNotifyCh <- struct{}{}:
default: // channel full, notification already pending
}
}
func (w *Watcher) setStarting() {
now := time.Now()
w.state.Store(&containerState{
status: idlewatcher.ContainerStatusRunning,
ready: false,
startedAt: now,
})
w.l.Debug().Time("started_at", now).Msg("container starting")
}
func (w *Watcher) setNapping(status idlewatcher.ContainerStatus) {
w.clearEventHistory() // Clear events on stop/pause
w.state.Store(&containerState{
status: status,
ready: false,
startedAt: time.Time{},
healthTries: 0,
})
}
func (w *Watcher) setError(err error) {
w.sendEvent(WakeEventError, "Container error", err)
w.state.Store(&containerState{
status: idlewatcher.ContainerStatusError,
ready: false,
err: err,
startedAt: time.Time{},
healthTries: 0,
})
}
// waitForReady waits for the container to become ready or context to be canceled.
// Returns true if ready, false if canceled.
func (w *Watcher) waitForReady(ctx context.Context) bool {
// Check if already ready
if w.ready() {
return true
}
// Wait for ready notification or context cancellation
select {
case <-w.readyNotifyCh:
return true
case <-ctx.Done():
return false
}
}
func (w *Watcher) waitStarted(reqCtx context.Context) bool {
select {
case <-reqCtx.Done():
return false
case <-w.route.Started():
return true
}
}