feat: exit listener after successful switch for automatic restart
After a successful switch deployment, the listener now exits gracefully so systemd can restart it with the new binary. This works together with stopIfChanged/restartIfChanged to ensure deployments complete before the service restarts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "0.1.4"
|
const version = "0.1.5"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := &cli.Command{
|
app := &cli.Command{
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ type Listener struct {
|
|||||||
|
|
||||||
// Expanded subjects for discovery responses
|
// Expanded subjects for discovery responses
|
||||||
expandedSubjects []string
|
expandedSubjects []string
|
||||||
|
|
||||||
|
// restartCh signals that the listener should exit for restart
|
||||||
|
// (e.g., after a successful switch deployment)
|
||||||
|
restartCh chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new listener with the given configuration.
|
// New creates a new listener with the given configuration.
|
||||||
@@ -43,10 +47,11 @@ func New(cfg Config, logger *slog.Logger) *Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Listener{
|
return &Listener{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
executor: deploy.NewExecutor(cfg.FlakeURL, cfg.Hostname, cfg.Timeout),
|
executor: deploy.NewExecutor(cfg.FlakeURL, cfg.Hostname, cfg.Timeout),
|
||||||
lock: deploy.NewLock(),
|
lock: deploy.NewLock(),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
restartCh: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +98,13 @@ func (l *Listener) Run(ctx context.Context) error {
|
|||||||
|
|
||||||
l.logger.Info("listener started", "deploy_subjects", l.expandedSubjects, "discover_subject", discoverSubject)
|
l.logger.Info("listener started", "deploy_subjects", l.expandedSubjects, "discover_subject", discoverSubject)
|
||||||
|
|
||||||
// Wait for context cancellation
|
// Wait for context cancellation or restart signal
|
||||||
<-ctx.Done()
|
select {
|
||||||
l.logger.Info("shutting down listener")
|
case <-ctx.Done():
|
||||||
|
l.logger.Info("shutting down listener")
|
||||||
|
case <-l.restartCh:
|
||||||
|
l.logger.Info("exiting for restart after successful switch deployment")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -185,6 +194,15 @@ func (l *Listener) handleDeployRequest(subject string, data []byte) {
|
|||||||
messages.StatusCompleted,
|
messages.StatusCompleted,
|
||||||
"deployment completed successfully",
|
"deployment completed successfully",
|
||||||
))
|
))
|
||||||
|
|
||||||
|
// After a successful switch, signal restart so we pick up any new version
|
||||||
|
if req.Action == messages.ActionSwitch {
|
||||||
|
select {
|
||||||
|
case l.restartCh <- struct{}{}:
|
||||||
|
default:
|
||||||
|
// Channel already has a signal pending
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
l.logger.Error("deployment failed",
|
l.logger.Error("deployment failed",
|
||||||
"exit_code", result.ExitCode,
|
"exit_code", result.ExitCode,
|
||||||
|
|||||||
Reference in New Issue
Block a user