Skip to content

Commit

Permalink
support OVERMIND_AUTO_RESTART_INTERVAL
Browse files Browse the repository at this point in the history
  • Loading branch information
jackie-pc committed Dec 15, 2023
1 parent 7f78ffd commit 8696ada
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 34 deletions.
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func setupStartCmd() cli.Command {
cli.StringFlag{Name: "can-die, c", EnvVar: "OVERMIND_CAN_DIE", Usage: "Specify names of process which can die without interrupting the other processes. Divide names with comma", Destination: &c.CanDie},
cli.BoolFlag{Name: "any-can-die", EnvVar: "OVERMIND_ANY_CAN_DIE", Usage: "No dead processes should stop Overmind. Overrides can-die", Destination: &c.AnyCanDie},
cli.StringFlag{Name: "auto-restart, r", EnvVar: "OVERMIND_AUTO_RESTART", Usage: "Specify names of process which will be auto restarted on death. Divide names with comma. Use 'all' as a process name to auto restart all processes on death.", Destination: &c.AutoRestart},
cli.DurationFlag{Name: "auto-restart-interval, ri", EnvVar: "OVERMIND_AUTO_RESTART_INTERVAL", Usage: "Wait this many seconds before restarting any process", Destination: &c.AutoRestartInterval},
cli.StringFlag{Name: "colors, b", EnvVar: "OVERMIND_COLORS", Usage: "Specify the xterm color codes that will be used to colorize process names. Divide codes with comma"},
cli.BoolFlag{Name: "show-timestamps, T", EnvVar: "OVERMIND_SHOW_TIMESTAMPS", Usage: "Add timestamps to the output", Destination: &c.ShowTimestamps},
cli.StringFlag{Name: "formation, m", EnvVar: "OVERMIND_FORMATION", Usage: "Specify the number of each process type to run. The value passed in should be in the format process=num,process=num. Use 'all' as a process name to set value for all processes"},
Expand Down
2 changes: 2 additions & 0 deletions start/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func newCommand(h *Handler) (*command, error) {

canDie := utils.SplitAndTrim(h.CanDie)
autoRestart := utils.SplitAndTrim(h.AutoRestart)
autoRestartInterval := h.AutoRestartInterval

c.scriptDir = filepath.Join(os.TempDir(), instanceID)
os.MkdirAll(c.scriptDir, 0700)
Expand All @@ -95,6 +96,7 @@ func newCommand(h *Handler) (*command, error) {
c.output,
(h.AnyCanDie || utils.StringsContain(canDie, e.OrigName)),
(utils.StringsContain(autoRestart, e.OrigName) || utils.StringsContain(autoRestart, "all")),
autoRestartInterval,
e.StopSignal,
))
}
Expand Down
44 changes: 23 additions & 21 deletions start/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"syscall"
"time"

"github.com/DarthSim/overmind/v2/utils"

Expand All @@ -27,27 +28,28 @@ var signalMap = map[string]syscall.Signal{

// Handler handles args and flags for the start command
type Handler struct {
Title string
Procfile string
Root string
Timeout int
NoPort bool
PortBase, PortStep int
ProcNames string
IgnoredProcNames string
SocketPath string
Network string
CanDie string
AnyCanDie bool
AutoRestart string
Colors []int
ShowTimestamps bool
Formation map[string]int
FormationPortStep int
StopSignals map[string]syscall.Signal
Daemonize bool
TmuxConfigPath string
Shell string
Title string
Procfile string
Root string
Timeout int
NoPort bool
PortBase, PortStep int
ProcNames string
IgnoredProcNames string
SocketPath string
Network string
CanDie string
AnyCanDie bool
AutoRestart string
AutoRestartInterval time.Duration
Colors []int
ShowTimestamps bool
Formation map[string]int
FormationPortStep int
StopSignals map[string]syscall.Signal
Daemonize bool
TmuxConfigPath string
Shell string
}

// AbsRoot returns absolute path to the working directory
Expand Down
57 changes: 44 additions & 13 deletions start/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package start
import (
"fmt"
"io"
"math"
"syscall"
"time"

Expand All @@ -11,21 +12,24 @@ import (

const runningCheckInterval = 100 * time.Millisecond

const interruptableSleepCheckInterval = 50 * time.Millisecond

const SIGINFO syscall.Signal = 29

type process struct {
output *multiOutput

pid int

stopSignal syscall.Signal
canDie bool
canDieNow bool
autoRestart bool
keepingAlive bool
dead bool
interrupted bool
restart bool
stopSignal syscall.Signal
canDie bool
canDieNow bool
autoRestart bool
autoRestartInterval time.Duration
keepingAlive bool
dead bool
interrupted bool
restart bool

tmux *tmuxClient

Expand All @@ -37,17 +41,18 @@ type process struct {
Command string
}

func newProcess(tmux *tmuxClient, name string, color int, command string, output *multiOutput, canDie bool, autoRestart bool, stopSignal syscall.Signal) *process {
func newProcess(tmux *tmuxClient, name string, color int, command string, output *multiOutput, canDie bool, autoRestart bool, autoRestartInterval time.Duration, stopSignal syscall.Signal) *process {
out, in := io.Pipe()

proc := &process{
output: output,
tmux: tmux,

stopSignal: stopSignal,
canDie: canDie,
canDieNow: canDie,
autoRestart: autoRestart,
stopSignal: stopSignal,
canDie: canDie,
canDieNow: canDie,
autoRestart: autoRestart,
autoRestartInterval: autoRestartInterval,

in: in,
out: out,
Expand Down Expand Up @@ -167,6 +172,24 @@ func (p *process) scanOuput() {
}
}

func (p *process) interruptableSleep(sleepDuration time.Duration) bool {
ticker2 := time.NewTicker(interruptableSleepCheckInterval)
totalTicks := int(math.Ceil(sleepDuration.Seconds() / interruptableSleepCheckInterval.Seconds()))
defer ticker2.Stop()
ticksPassed := 0
for range ticker2.C {
ticksPassed += 1
if p.interrupted {
p.output.WriteBoldLinef(p, "Interrupted while waiting for process restart")
return true
}
if ticksPassed >= totalTicks {
return false
}
}
return false
}

func (p *process) observe() {
ticker := time.NewTicker(runningCheckInterval)
defer ticker.Stop()
Expand All @@ -184,6 +207,14 @@ func (p *process) observe() {
p.pid = 0

if p.restart || (!p.interrupted && p.autoRestart) {
if p.autoRestartInterval > 0 {
p.output.WriteBoldLinef(p, "Restarting in %v seconds...", p.autoRestartInterval.Seconds())
interrupted := p.interruptableSleep(p.autoRestartInterval)
if interrupted {
p.dead = true
break
}
}
p.respawn()
} else {
p.dead = true
Expand Down

0 comments on commit 8696ada

Please sign in to comment.