fix retry wait can't start error

master
codeskyblue 8 years ago
parent ec0f64c789
commit 2965cf0b85

@ -145,7 +145,7 @@ func (p *Process) waitNextRetry() {
p.retryLeft -= 1
select {
case <-time.After(2 * time.Second): // TODO: need put it into Program
go p.Operate(StartEvent)
p.startCommand()
case <-p.stopC:
p.stopCommand()
}
@ -162,42 +162,51 @@ func (p *Process) IsRunning() bool {
return p.State() == Running || p.State() == RetryWait
}
func (p *Process) startCommand() {
p.cmd = kexec.CommandString("echo hello world && sleep 4 && echo end")
p.cmd.Stdout = os.Stdout
p.SetState(Running)
go func() {
errC := GoFunc(p.cmd.Run)
startTime := time.Now()
select {
case err := <-errC: //<-GoTimeoutFunc(time.Duration(p.StartSeconds)*time.Second, p.cmd.Run):
log.Println(err, time.Since(startTime))
if time.Since(startTime) < time.Duration(p.StartSeconds)*time.Second {
if p.retryLeft == p.StartRetries { // If first time quit so fast, just set to fatal
p.SetState(Fatal)
log.Println("Start change to fatal")
return
}
}
p.waitNextRetry()
case <-p.stopC:
p.stopCommand()
}
}()
}
func NewProcess(pg Program) *Process {
pr := &Process{
FSM: NewFSM(Stopped),
Program: pg,
stopC: make(chan int),
retryLeft: pg.StartRetries,
Status: string(Stopped),
}
pr.StateChange = func(_, newStatus FSMState) {
pr.Status = string(newStatus)
}
startFunc := func() {
pr.retryLeft = pr.StartRetries
pr.cmd = kexec.CommandString("echo hello world && sleep 10 && echo end")
pr.cmd.Stdout = os.Stdout
pr.SetState(Running)
go func() {
errC := GoFunc(pr.cmd.Run)
startTime := time.Now()
select {
case err := <-errC: //<-GoTimeoutFunc(time.Duration(pr.StartSeconds)*time.Second, pr.cmd.Run):
log.Println(err)
if time.Since(startTime) < time.Duration(pr.StartSeconds) {
pr.SetState(Fatal)
return
}
pr.waitNextRetry()
case <-pr.stopC:
pr.stopCommand()
}
}()
if pr.StartSeconds <= 0 {
pr.StartSeconds = 3
}
pr.AddHandler(Stopped, StartEvent, startFunc)
pr.AddHandler(Fatal, StartEvent, startFunc)
pr.AddHandler(Stopped, StartEvent, func() {
pr.retryLeft = pr.StartRetries
pr.startCommand()
})
pr.AddHandler(Fatal, StartEvent, pr.startCommand)
pr.AddHandler(Running, StopEvent, func() {
pr.cmd.Terminate(syscall.SIGKILL)

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>gosuv</title>
<link rel="shortcut icon" type="image/png" href="/res/favicon.png" />
<link rel="shortcut icon" type="image/png" href="/res/images/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/res/bootstrap-3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/res/font-awesome-4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="/res/css/style.css">
@ -43,6 +43,9 @@
<button class="btn btn-default btn-sm" id="launchNewProgram">
<span class="glyphicon glyphicon-plus"></span> New Program
</button>
<button class="btn btn-default btn-sm" v-on:click="refresh">
<span class="glyphicon glyphicon-refresh"></span> Refresh
</button>
</div>
<div class="col-md-12">
<table class="table table-hover">
@ -58,15 +61,18 @@
<td v-text="p.program.name"></td>
<td v-text="p.status"></td>
<td>
<button class="btn btn-default btn-xs">
<button v-on:click="cmdStart(p.program.name)" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-play"></span> Start
</button>
<button class="btn btn-default btn-xs">
<button class="btn btn-default btn-xs" :disabled="p.status=='stopped'">
<span class="glyphicon glyphicon-stop"></span> Stop
</button>
<button class="btn btn-default btn-xs" disabled="true">
<span class="glyphicon glyphicon-minus"></span> Tailf
</button>
<button class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-cog"></span> Setting
</button>
</td>
</tr>
<tr class="success">
@ -82,6 +88,9 @@
<button class="btn btn-default btn-xs" disabled="true">
<span class="glyphicon glyphicon-minus"></span> Tailf
</button>
<button class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-cog"></span> Setting
</button>
</td>
</tr>
</tbody>
@ -144,12 +153,12 @@
// keyboard: false,
backdrop: 'static',
})
})
$("#newProgram").modal({
show: true,
// keyboard: false,
backdrop: 'static',
})
});
// $("#newProgram").modal({
// show: true,
// // keyboard: false,
// backdrop: 'static',
// })
});
</script>
</body>

@ -56,6 +56,25 @@ var vm = new Vue({
}
return this.breadcrumb;
},
refresh: function() {
console.log("RR");
$.ajax({
url: "/api/programs",
success: function(data) {
vm.programs = data;
}
});
},
cmdStart: function(name) {
console.log(name);
$.ajax({
url: "/api/programs/" + name + "/start",
method: 'post',
success: function(data) {
console.log(data);
}
})
},
}
})
@ -72,18 +91,12 @@ Vue.filter('formatBytes', function(value) {
else return (bytes / 1073741824).toFixed(1) + " GB";
})
var refreshPrograms = function() {
$.ajax({
url: "/api/programs",
success: function(data) {
console.log(data)
vm.programs = data;
}
});
}
Vue.directive('disable', function(value) {
this.el.disabled = !!value
})
$(function() {
refreshPrograms();
vm.refresh();
$("#formNewProgram").submit(function(e) {
var url = "/api/programs",

@ -31,7 +31,6 @@ func (s *Supervisor) programPath() string {
func (s *Supervisor) addOrUpdateProgram(pg Program) error {
origPg, ok := s.pgMap[pg.Name]
if ok {
// log.Println("Orig:", origPg, "Curr:", pg)
if !reflect.DeepEqual(origPg, &pg) {
log.Println("Update:", pg.Name)
origProc := s.procMap[pg.Name]
@ -181,6 +180,26 @@ func (s *Supervisor) hAddProgram(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}
func (s *Supervisor) hStartProgram(w http.ResponseWriter, r *http.Request) {
log.Println("Hello")
name := mux.Vars(r)["name"]
proc, ok := s.procMap[name]
var data []byte
if !ok {
data, _ = json.Marshal(map[string]interface{}{
"status": 1,
"error": fmt.Sprintf("Process %s not exists", strconv.Quote(name)),
})
} else {
proc.Operate(StartEvent)
data, _ = json.Marshal(map[string]interface{}{
"status": 0,
"name": name,
})
}
w.Write(data)
}
func init() {
suv := &Supervisor{
ConfigDir: filepath.Join(UserHomeDir(), ".gosuv"),
@ -194,6 +213,7 @@ func init() {
r.HandleFunc("/", suv.hIndex)
r.HandleFunc("/api/programs", suv.hGetProgram).Methods("GET")
r.HandleFunc("/api/programs", suv.hAddProgram).Methods("POST")
r.HandleFunc("/api/programs/{name}/start", suv.hStartProgram).Methods("POST")
fs := http.FileServer(http.Dir("res"))
http.Handle("/", r)

Loading…
Cancel
Save