Skip to content

Commit

Permalink
Add --maxrestart argument to change max deamon restart delay
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Aug 8, 2020
1 parent 8983974 commit 5e3f6c6
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 26 deletions.
11 changes: 10 additions & 1 deletion cmd/modd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"strings"
"time"

"github.com/cortesi/modd"
"github.com/cortesi/modd/notify"
Expand Down Expand Up @@ -45,6 +46,10 @@ var prep = kingpin.Flag("prep", "Run prep commands and exit").
Short('p').
Bool()

var maxRestartDelay = kingpin.Flag("maxrestart", "Max deamon restart delay").
Default("8").
Int()

var debug = kingpin.Flag("debug", "Debugging for modd development").
Default("false").
Bool()
Expand Down Expand Up @@ -110,7 +115,11 @@ func main() {
notifiers = append(notifiers, &notify.BeepNotifier{})
}

mr, err := modd.NewModRunner(*file, log, notifiers, !(*noconf))
mr, err := modd.NewModRunner(log, notifiers, modd.ModRunnerArgs{
ConfPath: *file,
ConfReload: !(*noconf),
MaxRestartDelay: time.Duration(*maxRestartDelay) * time.Second,
})
if err != nil {
log.Shout("%s", err)
return
Expand Down
28 changes: 14 additions & 14 deletions daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ const (
MinRestart = 500 * time.Millisecond
// MulRestart is the exponential backoff multiplier applied when the daemon exits uncleanly
MulRestart = 2
// MaxRestart is the maximum amount of time between daemon restarts
MaxRestart = 8 * time.Second
)

// A single daemon
type daemon struct {
conf conf.Daemon
indir string
conf conf.Daemon
indir string
maxRestartDelay time.Duration

ex *shell.Executor
log termlog.Stream
Expand Down Expand Up @@ -61,12 +60,12 @@ func (d *daemon) Run() {

// If we exited cleanly, or the process ran for > MaxRestart, we reset
// the delay timer
if time.Now().Sub(lastStart) > MaxRestart {
if time.Now().Sub(lastStart) > d.maxRestartDelay {
delay = MinRestart
} else {
delay *= MulRestart
if delay > MaxRestart {
delay = MaxRestart
if delay > d.maxRestartDelay {
delay = d.maxRestartDelay
}
}
}
Expand Down Expand Up @@ -110,7 +109,7 @@ type DaemonPen struct {
}

// NewDaemonPen creates a new DaemonPen
func NewDaemonPen(block conf.Block, vars map[string]string, log termlog.TermLog) (*DaemonPen, error) {
func NewDaemonPen(block conf.Block, vars map[string]string, log termlog.TermLog, maxRestartDelay time.Duration) (*DaemonPen, error) {
d := make([]*daemon, len(block.Daemons))
for i, dmn := range block.Daemons {
vcmd := varcmd.VarCmd{Block: nil, Modified: nil, Vars: vars}
Expand All @@ -134,10 +133,11 @@ func NewDaemonPen(block conf.Block, vars map[string]string, log termlog.TermLog)
}

d[i] = &daemon{
conf: dmn,
log: log.Stream(niceHeader("daemon: ", dmn.Command)),
shell: sh,
indir: indir,
conf: dmn,
log: log.Stream(niceHeader("daemon: ", dmn.Command)),
shell: sh,
indir: indir,
maxRestartDelay: maxRestartDelay,
}
}
return &DaemonPen{daemons: d}, nil
Expand Down Expand Up @@ -171,10 +171,10 @@ type DaemonWorld struct {
}

// NewDaemonWorld creates a DaemonWorld
func NewDaemonWorld(cnf *conf.Config, log termlog.TermLog) (*DaemonWorld, error) {
func NewDaemonWorld(cnf *conf.Config, log termlog.TermLog, maxRestartDelay time.Duration) (*DaemonWorld, error) {
daemonPens := make([]*DaemonPen, len(cnf.Blocks))
for i, b := range cnf.Blocks {
d, err := NewDaemonPen(b, cnf.GetVariables(), log)
d, err := NewDaemonPen(b, cnf.GetVariables(), log, maxRestartDelay)
if err != nil {
return nil, err
}
Expand Down
31 changes: 20 additions & 11 deletions modd.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,31 @@ var CommonExcludes = []string{
"**/node_modules/**",
}

// ModRunnerArgs arguments for modd command
type ModRunnerArgs struct {
ConfPath string
ConfReload bool
MaxRestartDelay time.Duration
}

// ModRunner coordinates running the modd command
type ModRunner struct {
Log termlog.TermLog
Config *conf.Config
ConfPath string
ConfReload bool
Notifiers []notify.Notifier
Log termlog.TermLog
Config *conf.Config
ConfPath string
ConfReload bool
MaxRestartDelay time.Duration
Notifiers []notify.Notifier
}

// NewModRunner constructs a new ModRunner
func NewModRunner(confPath string, log termlog.TermLog, notifiers []notify.Notifier, confreload bool) (*ModRunner, error) {
func NewModRunner(log termlog.TermLog, notifiers []notify.Notifier, ma ModRunnerArgs) (*ModRunner, error) {
mr := &ModRunner{
Log: log,
ConfPath: confPath,
ConfReload: confreload,
Notifiers: notifiers,
Log: log,
ConfPath: ma.ConfPath,
ConfReload: ma.ConfReload,
MaxRestartDelay: ma.MaxRestartDelay,
Notifiers: notifiers,
}
err := mr.ReadConfig()
if err != nil {
Expand Down Expand Up @@ -166,7 +175,7 @@ func (mr *ModRunner) trigger(root string, mod *moddwatch.Mod, dworld *DaemonWorl

// Gives control of chan to caller
func (mr *ModRunner) runOnChan(modchan chan *moddwatch.Mod, readyCallback func()) error {
dworld, err := NewDaemonWorld(mr.Config, mr.Log)
dworld, err := NewDaemonWorld(mr.Config, mr.Log, mr.MaxRestartDelay)
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions test/maxrestartdelay.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# used to test max restart delay
# run and in another shell do echo test > changeme etc
changeme {
daemon: echo starting; exec sleep 1000000
}

0 comments on commit 5e3f6c6

Please sign in to comment.