From 8fdfa6e9a1121a7e900651854ba11ca5e9651037 Mon Sep 17 00:00:00 2001 From: codeskyblue Date: Tue, 16 Aug 2016 10:52:28 +0800 Subject: [PATCH] support reload --- fsm.go | 19 +++++++++++++++++++ utils.go | 6 ++++++ web.go | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/fsm.go b/fsm.go index 329fbca..08e5a1d 100644 --- a/fsm.go +++ b/fsm.go @@ -15,6 +15,8 @@ package main import ( + "errors" + "fmt" "log" "os" "sync" @@ -98,6 +100,19 @@ type Program struct { // LogDir string `yaml:"logdir"` } +func (p *Program) Check() error { + if p.Name == "" { + return errors.New("Program name empty") + } + if p.Command == "" { + return errors.New("Program command empty") + } + if p.Dir != "" && !IsDir(p.Dir) { + return fmt.Errorf("Program dir(%s) not exists", p.Dir) + } + return nil +} + type Process struct { *FSM Program @@ -137,6 +152,10 @@ func (p *Process) stopCommand() { p.SetState(Stopped) } +func (p *Process) IsRunning() bool { + return p.State() == Running || p.State() == RetryWait +} + func NewProcess(pg Program) *Process { pr := &Process{ FSM: NewFSM(Stopped), diff --git a/utils.go b/utils.go index c6c3c80..a732b79 100644 --- a/utils.go +++ b/utils.go @@ -2,6 +2,7 @@ package main import ( "errors" + "os" "time" "github.com/qiniu/log" @@ -31,3 +32,8 @@ func GoTimeoutFunc(timeout time.Duration, f func() error) chan error { }() return ch } + +func IsDir(dir string) bool { + fi, err := os.Stat(dir) + return err == nil && fi.IsDir() +} diff --git a/web.go b/web.go index a7f5811..180a198 100644 --- a/web.go +++ b/web.go @@ -8,6 +8,7 @@ import ( "net/http" "path/filepath" "reflect" + "time" "github.com/go-yaml/yaml" "github.com/gorilla/mux" @@ -17,6 +18,7 @@ type Supervisor struct { ConfigDir string pgs []*Program pgMap map[string]*Program + procMap map[string]*Process } func (s *Supervisor) programPath() string { @@ -28,10 +30,25 @@ func (s *Supervisor) addOrUpdateProgram(pg Program) { if ok { if !reflect.DeepEqual(origPg, &pg) { log.Println("Update:", pg.Name) + origProc := s.procMap[pg.Name] + isRunning := origProc.IsRunning() + go func() { + origProc.Operate(StopEvent) + + // TODO: wait state change + time.Sleep(2 * time.Second) + + newProc := NewProcess(pg) + s.procMap[pg.Name] = newProc + if isRunning { + newProc.Operate(StartEvent) + } + }() } } else { s.pgs = append(s.pgs, &pg) s.pgMap[pg.Name] = &pg + s.procMap[pg.Name] = NewProcess(pg) log.Println("Add:", pg.Name) } } @@ -51,6 +68,14 @@ func (s *Supervisor) loadDB() error { return nil } +func (s *Supervisor) saveDB() error { + data, err := yaml.Marshal(s.pgs) + if err != nil { + return err + } + return ioutil.WriteFile(s.programPath(), data, 0644) +} + func (s *Supervisor) Index(w http.ResponseWriter, r *http.Request) { t := template.Must(template.New("t").ParseFiles("./res/index.html")) t.ExecuteTemplate(w, "index.html", nil) @@ -60,9 +85,13 @@ func (s *Supervisor) AddProgram(w http.ResponseWriter, r *http.Request) { pg := Program{ Name: r.FormValue("name"), Command: r.FormValue("command"), + // TODO: missing other values } - // TODO: need check pg - // pg.Check() error + if err := pg.Check(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "application/json") var data []byte if _, ok := s.pgMap[pg.Name]; ok {