利用管道、反射实现业务代码和非业务代码分离,涉及监听其设计、管道设计、反射应用等知识点 事件监听结构
const chanBuff = 100
type Event struct {
// param list, FIFO
Data []interface{} `json:"data"`
Func interface{} `json:"func"`
Method string `json:"method"`
}
type ListenEvent struct {
Event
}
type CallBackEvent struct {
Event
}
var sm sync.Mutex
var pe ProcessListener
type ProcessListener struct {
ProcListenerCh chan *ListenEvent
ProcCallBackCh chan *CallBackEvent
}
func GetProcessListener() *ProcessListener {
sm.Lock()
defer func() { sm.Unlock() }()
if pe != (ProcessListener{}) {
return &pe
}
pe = ProcessListener{
ProcListenerCh: make(chan *ListenEvent, chanBuff),
ProcCallBackCh: make(chan *CallBackEvent, chanBuff),
}
return &pe
}
//AddEvent 添加事件
func (pe *ProcessListener) AddEvent(event interface{}) error {
if e, ok := event.(*ListenEvent); ok {
pe.ProcListenerCh <- e
}
if e, ok := event.(*CallBackEvent); ok {
pe.ProcCallBackCh <- e
}
return nil
}
//Execute 执行事件
func (pe *ProcessListener) Execute() {
for {
select {
case e := <-pe.ProcListenerCh:
GetProcessEventHandler().ListenerHandle(e)
case e := <-pe.ProcCallBackCh:
GetProcessEventHandler().CallBackHandle(e)
}
}
}
事件处理器
//流程事件处理器
type ProcessEventHandler struct {
}
func GetProcessEventHandler() *ProcessEventHandler {
return &ProcessEventHandler{}
}
//监听流程逻辑
func (h *ProcessEventHandler) ListenerHandle(event *ListenEvent) {
handle(event)
}
//流程回调处理逻辑
func (h *ProcessEventHandler) CallBackHandle(event *CallBackEvent) {
handle(event)
}
func handle() {
ctx, cancel := context.WithTimeout(context.Background(), common.TimeOut5Seco)
defer cancel()
handler := reflect.New(reflect.ValueOf(event.Func).Type())
var params []reflect.Value
vars := event.Data
if vars != nil {
params = make([]reflect.Value, len(vars))
for i, v := range vars {
params[i] = reflect.ValueOf(v)
}
}
rets := handler.MethodByName(event.Method).Call(params)
val := rets[0]
if err, ok := val.Interface().(error); ok {
if err != nil {
log.Errorf(log.FormatFields(ctx, utils.LogTag, map[string]interface{}{
"action": "the ProcessEventHandler CallBackHandle is error",
"err": err.Error(),
}))
}
}
}
使用
// 流程结束更新配置状态
if u.Status == model.Completed {
configUpdate := &app_config.CallBackInfo{
ProcInsID: param.ProcInsID,
Status: u.Status,
OpUser: model.BpmUser,
OpType: param.OpType,
}
params := make([]interface{}, 1)
params[0] = configUpdate
event := &domain.CallBackEvent{}
event.Data = params
event.Func = *app_config.GetConfigApp()
event.Method = "CallBack"
err = domain.GetProcessListener().AddEvent(event)
}