-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand.go
96 lines (84 loc) · 1.7 KB
/
command.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package clipper
import (
"time"
)
type status int
const (
finishOk status = 0
finishWithErr status = 1
finishWithTimeout status = 2
)
type command struct {
cb *Clipper
start int64
runFunction func() error
fallbackFunction func() error
end chan bool
status chan status
cmdType string
}
// Do will perform the command operation, return a status with
// 0 == no error
// 1 == error (app)
// 2 == timeout
// everything != 0 is counted as error
// you can provide the config
func Do(cfg *Configs, fn func() error, fallbackFn func() error) chan status {
cb := getClipper(cfg)
cmd := &command{
cb: cb,
start: time.Now().Unix(),
runFunction: fn,
fallbackFunction: fallbackFn,
cmdType: "async",
status: make(chan status, 1),
end: make(chan bool, 1),
}
return run(cmd)
}
func run(cmd *command) chan status {
cb := cmd.cb
cb.mutex.Lock()
defer cb.mutex.Unlock()
if cb.isOpen() {
cmd.status <- 1
return cmd.status
}
go func() {
defer func() {
cmd.end <- true
}()
err := cmd.runFunction()
cb.statistics.numOfRuns++
if err != nil {
cb.update(err)
if cmd.fallbackFunction != nil {
err = cmd.fallbackFunction()
if err != nil {
cmd.status <- finishWithErr
return
} else {
cmd.status <- finishOk
return
}
} else {
cmd.status <- finishWithErr
return
}
}
cmd.status <- finishOk
return
}()
go func() {
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case <-cmd.end:
return
case <-timer.C:
cmd.status <- finishWithTimeout
return
}
}()
return cmd.status
}