/
fsm.go
98 lines (87 loc) · 2.12 KB
/
fsm.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
97
98
package database
import (
"context"
"fmt"
"time"
"github.com/dumacp/go-logs/pkg/logs"
"github.com/looplab/fsm"
"go.etcd.io/bbolt"
)
const (
sInit = "sInit"
sOpen = "sOpen"
sClose = "sClose"
sRestart = "sRestart"
sWaitEvent = "sWait"
)
const (
eOpenCmd = "eOpenCmd"
eOpened = "eOpened"
eClosed = "eClosed"
eError = "eError"
eStart = "eStart"
)
// func beforeEvent(event string) string {
// return fmt.Sprintf("before_%s", event)
// }
func enterState(state string) string {
return fmt.Sprintf("enter_%s", state)
}
// func leaveState(state string) string {
// return fmt.Sprintf("leave_%s", state)
// }
func (a *dbActor) initFSM() *fsm.FSM {
f := fsm.NewFSM(
sInit,
fsm.Events{
{Name: eOpenCmd, Src: []string{sInit, sClose, sRestart}, Dst: sOpen},
{Name: eOpened, Src: []string{sOpen}, Dst: sWaitEvent},
{Name: eClosed, Src: []string{sOpen, sWaitEvent}, Dst: sClose},
{Name: eError, Src: []string{sOpen, sWaitEvent}, Dst: sRestart},
},
fsm.Callbacks{
"enter_state": func(_ context.Context, e *fsm.Event) {
logs.LogBuild.Printf("FSM DB state Src: %v, state Dst: %v", e.Src, e.Dst)
},
"leave_state": func(_ context.Context, e *fsm.Event) {
if e.Err != nil {
e.Cancel(e.Err)
}
},
"before_event": func(_ context.Context, e *fsm.Event) {
if e.Err != nil {
e.Cancel(e.Err)
}
},
enterState(sOpen): func(_ context.Context, e *fsm.Event) {
if a.db != nil {
a.db.Close()
}
db, err := bbolt.Open(a.pathDB, 0666, nil)
if err != nil {
logs.LogError.Println(err)
a.ctx.Send(a.ctx.Self(), &MsgErrorDB{})
e.Err = err
return
}
a.db = db
a.ctx.Send(a.ctx.Self(), &MsgOpenedDB{})
},
enterState(sClose): func(_ context.Context, e *fsm.Event) {
if a.db != nil {
a.db.Close()
a.db = nil
}
a.behavior.Become(a.CloseState)
},
enterState(sRestart): func(contxt context.Context, e *fsm.Event) {
select {
case <-time.After(3 * time.Second):
a.behavior.Become(a.CloseState)
a.ctx.Send(a.ctx.Self(), &MsgOpenDB{})
case <-contxt.Done():
}
},
})
return f
}