fileboy/taskman.go

136 lines
2.8 KiB
Go
Raw Normal View History

2018-12-29 09:49:38 +00:00
package main
import (
"os"
"os/exec"
"sync"
"time"
)
2018-12-30 07:14:14 +00:00
type TaskMan struct {
2018-12-29 09:49:38 +00:00
lastTaskId int64
delay int
cmd *exec.Cmd
2019-01-02 11:07:52 +00:00
notifier *NetNotifier
2018-12-29 09:49:38 +00:00
putLock sync.Mutex
runLock sync.Mutex
2020-01-02 08:38:26 +00:00
waitChan chan bool
waitQueue []*changedFile
2018-12-29 09:49:38 +00:00
}
2019-01-02 11:07:52 +00:00
func newTaskMan(delay int, callUrl string) *TaskMan {
2020-01-02 08:38:26 +00:00
t := &TaskMan{
delay: delay,
notifier: newNetNotifier(callUrl),
waitChan: make(chan bool, 1),
waitQueue: []*changedFile{},
}
if keyInInstruction(InstShouldFinish) {
go func() {
for {
<-t.waitChan
if len(t.waitQueue) > 0 {
cf := t.waitQueue[len(t.waitQueue)-1]
if len(t.waitQueue) > 1 {
2020-03-03 03:12:08 +00:00
logInfo("redundant tasks dropped:", len(t.waitQueue)-1)
2020-01-02 08:38:26 +00:00
}
t.waitQueue = []*changedFile{}
go t.preRun(cf)
}
}
}()
2018-12-29 09:49:38 +00:00
}
2020-01-02 08:38:26 +00:00
return t
2018-12-29 09:49:38 +00:00
}
2019-01-03 01:56:26 +00:00
func (t *TaskMan) Put(cf *changedFile) {
2018-12-29 09:49:38 +00:00
if t.delay < 1 {
2020-01-02 10:32:16 +00:00
t.dispatcher(cf)
2018-12-29 09:49:38 +00:00
return
}
t.putLock.Lock()
defer t.putLock.Unlock()
t.lastTaskId = cf.Changed
go func() {
2019-01-23 02:27:26 +00:00
<-time.After(time.Millisecond * time.Duration(t.delay))
2018-12-29 09:49:38 +00:00
if t.lastTaskId > cf.Changed {
return
}
2020-01-02 10:32:16 +00:00
t.dispatcher(cf)
2018-12-29 09:49:38 +00:00
}()
}
2020-01-02 10:32:16 +00:00
func (t *TaskMan) dispatcher(cf *changedFile) {
if keyInInstruction(InstShouldFinish) {
t.waitQueue = append(t.waitQueue, cf)
if t.cmd == nil {
t.waitChan <- true
return
}
2020-03-03 03:12:08 +00:00
logInfo("waitting for the last task to finish")
logInfo("waiting tasks:", len(t.waitQueue))
2020-01-02 10:32:16 +00:00
} else {
t.preRun(cf)
}
}
2019-01-03 01:56:26 +00:00
func (t *TaskMan) preRun(cf *changedFile) {
2019-06-04 02:52:58 +00:00
if t.cmd != nil && t.cmd.Process != nil {
2019-01-19 09:17:55 +00:00
if err := t.cmd.Process.Kill(); err != nil {
2020-01-02 09:25:02 +00:00
logInfo("stop old process ")
logWarn("stopped err, reason:", err)
2018-12-29 09:49:38 +00:00
}
}
go t.run(cf)
2019-06-04 02:58:42 +00:00
go t.notifier.Put(cf)
2018-12-29 09:49:38 +00:00
}
2019-01-03 01:56:26 +00:00
func (t *TaskMan) run(cf *changedFile) {
2018-12-29 09:49:38 +00:00
t.runLock.Lock()
defer t.runLock.Unlock()
for i := 0; i < len(cfg.Command.Exec); i++ {
carr := cmdParse2Array(cfg.Command.Exec[i], cf)
2020-01-02 09:25:02 +00:00
logInfo("EXEC", carr)
2018-12-29 09:49:38 +00:00
t.cmd = exec.Command(carr[0], carr[1:]...)
//cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT}
t.cmd.Stdin = os.Stdin
2019-12-27 10:09:56 +00:00
t.cmd.Stdout = os.Stdout
2020-01-02 09:38:52 +00:00
if keyInInstruction(InstIgnoreStdout) {
t.cmd.Stdout = nil
}
2018-12-29 09:49:38 +00:00
t.cmd.Stderr = os.Stderr
t.cmd.Dir = projectFolder
t.cmd.Env = os.Environ()
2019-12-27 10:09:56 +00:00
err := t.cmd.Start()
2019-01-03 02:41:23 +00:00
if err != nil {
2020-01-02 09:25:02 +00:00
logError("run command", carr, "error. ", err)
2020-01-02 09:38:52 +00:00
if keyInInstruction(InstIgnoreExecError) {
continue
}
2019-12-27 10:09:56 +00:00
break
2018-12-29 09:49:38 +00:00
}
err = t.cmd.Wait()
if err != nil {
2020-01-02 09:25:02 +00:00
logWarn("command exec failed:", carr, err)
2020-01-02 09:38:52 +00:00
if keyInInstruction(InstIgnoreExecError) {
continue
}
2018-12-29 09:49:38 +00:00
break
}
2019-06-04 03:12:41 +00:00
if t.cmd.Process != nil {
2019-12-27 10:09:56 +00:00
err := t.cmd.Process.Kill()
2020-01-02 09:25:02 +00:00
logInfo(t.cmd.ProcessState)
2019-12-27 10:09:56 +00:00
if t.cmd.ProcessState != nil && !t.cmd.ProcessState.Exited() {
2020-01-02 09:25:02 +00:00
logError("command cannot stop!", carr, err)
2019-01-03 02:41:23 +00:00
}
2018-12-29 09:49:38 +00:00
}
}
2020-01-02 08:38:26 +00:00
if keyInInstruction(InstShouldFinish) {
t.cmd = nil
t.waitChan <- true
}
2020-01-02 09:25:02 +00:00
logInfo("EXEC end")
2018-12-29 09:49:38 +00:00
}