-
Notifications
You must be signed in to change notification settings - Fork 11
/
event_entity.go
107 lines (94 loc) · 2.44 KB
/
event_entity.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
99
100
101
102
103
104
105
106
107
package easyfsm
import "context"
type (
// EventEntity is the core that wraps the basic Event methods.
EventEntity struct {
hook EventHook
eventName EventName
observers []EventObserver
eventFunc EventFunc
// issue:https://github.com/wuqinqiang/easyfsm/issues/16
forkCtxFunc func(ctx context.Context) context.Context
}
EventEntityOpt func(entity *EventEntity)
// EventFunc is the function that will be called when the event is triggered.
EventFunc func(opt *Param) (State, error)
// EventObserver is the interface.When the event is processed,
// it can notify the observers asynchronously and execute their own business.
EventObserver interface {
Receive(opt *Param)
}
// EventHook is the interface that user can implement to hook the event func.
EventHook interface {
Before(opt *Param)
After(opt Param, state State, err error)
}
)
// NewEventEntity creates a new EventEntity.
func NewEventEntity(event EventName, handler EventFunc,
opts ...EventEntityOpt) *EventEntity {
entity := &EventEntity{
eventName: event,
eventFunc: handler,
observers: make([]EventObserver, 0),
forkCtxFunc: func(ctx context.Context) context.Context {
return context.Background()
},
}
for _, opt := range opts {
opt(entity)
}
return entity
}
// WithObservers adds observers to the event.
func WithObservers(observers ...EventObserver) EventEntityOpt {
return func(entity *EventEntity) {
if len(observers) == 0 {
return
}
entity.observers = append(entity.observers, observers...)
}
}
// WithHook adds hook to the event
func WithHook(hook EventHook) EventEntityOpt {
return func(entity *EventEntity) {
if hook == nil {
return
}
entity.hook = hook
}
}
func WithForkCtxFunc(fn func(ctx context.Context) context.Context) EventEntityOpt {
return func(entity *EventEntity) {
entity.forkCtxFunc = fn
}
}
// execute executes the event.
func (e *EventEntity) execute(param *Param) (State, error) {
if e.hook != nil {
e.hook.Before(param)
}
state, err := e.eventFunc(param)
if e.hook != nil {
// post operation Not allowed to modify the Data
forkParam := *param
e.hook.After(forkParam, state, err)
}
if err != nil {
return state, err
}
// Asynchronous notify observers
GoSafe(func() {
param.Ctx = e.forkCtxFunc(param.Ctx)
e.notify(param)
})
return state, nil
}
func (e *EventEntity) notify(opt *Param) {
for _, observer := range e.observers {
if observer == nil {
continue
}
observer.Receive(opt)
}
}