go-common/app/job/main/aegis/service/handler.go

374 lines
11 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
"go-common/app/job/main/aegis/model"
"go-common/library/log"
"go-common/library/queue/databus"
pkgerr "github.com/pkg/errors"
)
//RscHandler .
type RscHandler interface {
CheckMessage(json.RawMessage) (interface{}, error)
HandleMessage(context.Context, interface{}) error
}
//TaskHandler .
type TaskHandler interface {
CheckMessage(*databus.Message) (interface{}, error)
HandleMessage(context.Context, interface{}) error
}
var (
_ TaskHandler = baseTaskHandler{}
_ TaskHandler = dynamicTaskHandler{}
_ RscHandler = baseResourceAddHandler{}
_ RscHandler = mangaResourceAddHandler{}
_ RscHandler = baseResourceUpdateHandler{}
_ RscHandler = baseResourceCancelHandler{}
)
//单例
var (
basehandleTask *baseTaskHandler
basehandleRscAdd *baseResourceAddHandler
basehandleRscUpdate *baseResourceUpdateHandler
basehandleRscCancel *baseResourceCancelHandler
dynamicHandleTask *dynamicTaskHandler
mangaHandelRscAdd *mangaResourceAddHandler
once sync.Once
)
//ERROR
var (
ErrTaskDuplicate = errors.New("重复任务")
ErrTaskFlowInvalid = errors.New("流程失效")
ErrTaskResourceInvalid = errors.New("资源失效")
ErrInvalidMsg = errors.New("无效消息")
ErrHandlerMiss = errors.New("handler NotFound")
)
//prefix
var (
_prefixTask = "task_"
_prefixRscAdd = "add_"
_prefixRscUpdate = "update_"
_prefixRscCancel = "cancel_"
)
//业务ID
var (
_bizidDynamic = 1
_bizidManga = 2
)
func (s *Service) registerRscHandler(key string, handler RscHandler) {
s.rschandle[key] = handler
}
func (s *Service) registerTaskHandler(key string, handler TaskHandler) {
s.taskhandle[key] = handler
}
func (s *Service) findTaskHandler(key string) TaskHandler {
if handler, ok := s.taskhandle[key]; ok {
return handler
}
log.Warn("key(%s)没找到任务的处理器根据类型使用默认handler", key)
return s.getdynamicTaskHandler()
}
func (s *Service) findRscHandler(key string) RscHandler {
if handler, ok := s.rschandle[key]; ok {
return handler
}
log.Warn("key(%s)没找到业务的处理器根据类型使用默认handler", key)
switch {
case strings.HasPrefix(key, _prefixRscAdd):
return s.getbaseResourceAddHandler()
case strings.HasPrefix(key, _prefixRscUpdate):
return s.getbaseResourceUpdateHandler()
case strings.HasPrefix(key, _prefixRscCancel):
return s.getbaseResourceCancelHandler()
default:
return nil
}
}
//TODO 先写死吧,之后可以根据配置里面的类名用反射实例化
func initHandler(s *Service) {
var (
dynamicTask = fmt.Sprintf("%s%d", _prefixTask, _bizidDynamic)
dynamicRscAdd = fmt.Sprintf("%s%d", _prefixRscAdd, _bizidDynamic)
dynamicRscUpdate = fmt.Sprintf("%s%d", _prefixRscUpdate, _bizidDynamic)
dynamicRscCancel = fmt.Sprintf("%s%d", _prefixRscCancel, _bizidDynamic)
managaTask = fmt.Sprintf("%s%d", _prefixTask, _bizidManga)
managaRscAdd = fmt.Sprintf("%s%d", _prefixRscAdd, _bizidManga)
managaRscUpdate = fmt.Sprintf("%s%d", _prefixRscUpdate, _bizidManga)
managaRscCancel = fmt.Sprintf("%s%d", _prefixRscCancel, _bizidManga)
)
s.rschandle = make(map[string]RscHandler)
s.taskhandle = make(map[string]TaskHandler)
once.Do(func() {
basehandleTask = &baseTaskHandler{Service: s}
basehandleRscAdd = &baseResourceAddHandler{Service: s}
basehandleRscUpdate = &baseResourceUpdateHandler{Service: s}
basehandleRscCancel = &baseResourceCancelHandler{Service: s}
dynamicHandleTask = &dynamicTaskHandler{baseTaskHandler: baseTaskHandler{Service: s}}
mangaHandelRscAdd = &mangaResourceAddHandler{baseResourceAddHandler: baseResourceAddHandler{Service: s}}
})
s.registerRscHandler(dynamicRscAdd, s.getbaseResourceAddHandler())
s.registerRscHandler(dynamicRscUpdate, s.getbaseResourceUpdateHandler())
s.registerRscHandler(dynamicRscCancel, s.getbaseResourceCancelHandler())
s.registerRscHandler(managaRscAdd, s.getmangaResourceAddHandler())
s.registerRscHandler(managaRscUpdate, s.getbaseResourceUpdateHandler())
s.registerRscHandler(managaRscCancel, s.getbaseResourceCancelHandler())
s.registerTaskHandler(managaTask, s.getbaseTaskHandler())
s.registerTaskHandler(dynamicTask, s.getdynamicTaskHandler())
}
func (s *Service) getbaseTaskHandler() *baseTaskHandler {
return basehandleTask
}
func (s *Service) getbaseResourceAddHandler() *baseResourceAddHandler {
return basehandleRscAdd
}
func (s *Service) getbaseResourceUpdateHandler() *baseResourceUpdateHandler {
return basehandleRscUpdate
}
func (s *Service) getbaseResourceCancelHandler() *baseResourceCancelHandler {
return basehandleRscCancel
}
func (s *Service) getdynamicTaskHandler() *dynamicTaskHandler {
return dynamicHandleTask
}
func (s *Service) getmangaResourceAddHandler() *mangaResourceAddHandler {
return mangaHandelRscAdd
}
//解析验证message
/*
TODO
根据DispatchLimit动态设置分发数量
*/
func (s *Service) checkTaskMsg(msg *databus.Message) (*model.Task, error) {
taskMsg := new(model.CreateTaskMsg)
if err := json.Unmarshal(msg.Value, taskMsg); err != nil {
log.Error("checkTaskMsg key(%s) value(%s)", msg.Key, string(msg.Value))
return nil, err
}
if taskMsg.DispatchLimit == 0 || taskMsg.FlowID == 0 || taskMsg.RID == 0 {
log.Error("checkTaskMsg key(%s) value(%s)", msg.Key, string(msg.Value))
return nil, ErrTaskResourceInvalid
}
if s.dao.CheckTask(context.Background(), taskMsg.FlowID, taskMsg.RID) > 0 {
return nil, ErrTaskDuplicate
}
ok, err := s.dao.CheckFlow(context.TODO(), taskMsg.RID, taskMsg.FlowID)
if !ok || err != nil {
return nil, ErrTaskFlowInvalid
}
//先兼容旧的task消息没有传bizid
if taskMsg.BizID == 0 {
res, err := s.dao.Resource(context.Background(), taskMsg.RID)
if err != nil || res == nil {
return nil, ErrTaskResourceInvalid
}
taskMsg.BizID = res.BusinessID
}
return &model.Task{
BusinessID: taskMsg.BizID,
FlowID: taskMsg.FlowID,
RID: taskMsg.RID,
}, nil
}
func (s *Service) writeTaskToDB(c context.Context, task *model.Task) error {
return s.dao.CreateTask(c, task)
}
func (s *Service) checkRscAddMsg(msg json.RawMessage) (*model.AddOption, error) {
addMsg := new(model.AddOption)
if err := json.Unmarshal(msg, addMsg); err != nil {
return nil, err
}
if addMsg.BusinessID == 0 || len(addMsg.OID) == 0 {
return nil, ErrInvalidMsg
}
return addMsg, nil
}
func (s *Service) writeRscAdd(c context.Context, opt *model.AddOption) error {
//TODO 根据错误号重试
return s.dao.RscAdd(c, opt)
}
func (s *Service) checkRscUpdateMsg(msg json.RawMessage) (*model.UpdateOption, error) {
updateMsg := new(model.UpdateOption)
if err := json.Unmarshal(msg, updateMsg); err != nil {
return nil, err
}
if updateMsg.BusinessID == 0 || len(updateMsg.OID) == 0 || len(updateMsg.Update) == 0 {
return nil, ErrInvalidMsg
}
return updateMsg, nil
}
func (s *Service) writeRscUpdate(c context.Context, opt *model.UpdateOption) error {
return s.dao.RscUpdate(c, opt)
}
func (s *Service) checkRscCancelMsg(msg json.RawMessage) (*model.CancelOption, error) {
cancelMsg := new(model.CancelOption)
if err := json.Unmarshal(msg, cancelMsg); err != nil {
return nil, err
}
if cancelMsg.BusinessID == 0 || len(cancelMsg.Oids) == 0 {
return nil, ErrInvalidMsg
}
return cancelMsg, nil
}
func (s *Service) writeRscCancel(c context.Context, opt *model.CancelOption) error {
return s.dao.RscCancel(c, opt)
}
func (s *Service) newrsc(msg *databus.Message) (interface{}, error) {
log.Info("databusgroup new msg key(%+v) partition(%d) offset(%d) value(%s) ", msg.Key, msg.Partition, msg.Offset, string(msg.Value))
rscmsg := new(model.RscMsg)
if err := json.Unmarshal(msg.Value, rscmsg); err != nil {
log.Error("databusgroup json.Unmarshal for msg(%+v)", string(msg.Value))
return nil, ErrInvalidMsg
}
key := fmt.Sprintf("%s_%d", rscmsg.Action, rscmsg.BizID)
handler := s.findRscHandler(key)
if handler == nil {
log.Error("databusgroup can not find handler for msg key(%+v)", key)
return nil, ErrHandlerMiss
}
data, err := handler.CheckMessage(rscmsg.Raw)
if err != nil {
log.Error("databusgroup new msg key(%+v) partition(%d) offset(%d) value(%s) CheckMessage(%v)", msg.Key, msg.Partition, msg.Offset, string(msg.Value), pkgerr.WithStack(err))
}
return data, err
}
func (s *Service) splitrsc(msg *databus.Message, data interface{}) int {
switch t := data.(type) {
case *model.AddOption:
return int(t.BusinessID)
case *model.UpdateOption:
return int(t.BusinessID)
case *model.CancelOption:
return int(t.BusinessID)
default:
return 0
}
}
func (s *Service) dorsc(bmsgs []interface{}) {
for _, msg := range bmsgs {
log.Info("databusgroup do msg(%+v)", msg)
var key string
switch t := msg.(type) {
case *model.AddOption:
key = fmt.Sprintf("%s%d", _prefixRscAdd, t.BusinessID)
case *model.UpdateOption:
key = fmt.Sprintf("%s%d", _prefixRscUpdate, t.BusinessID)
case *model.CancelOption:
key = fmt.Sprintf("%s%d", _prefixRscCancel, t.BusinessID)
default:
log.Error("databusgroup unknow msg(%+v)", msg)
continue
}
handler := s.findRscHandler(key)
if handler == nil {
log.Error("databusgroup msg(%+v) handler NotFound", msg)
continue
}
if err := handler.HandleMessage(context.Background(), msg); err != nil {
log.Error("databusgroup msg(%+v) handler err(%v)", msg, pkgerr.WithStack(err))
continue
}
}
}
func (s *Service) newtask(msg *databus.Message) (interface{}, error) {
log.Info("databusgroup newtask msg key(%+v) partition(%d) offset(%d) value(%s) ", msg.Key, msg.Partition, msg.Offset, string(msg.Value))
taskmsg := new(model.CreateTaskMsg)
if err := json.Unmarshal(msg.Value, taskmsg); err != nil {
log.Error("databusgroup newtask json.Unmarshal for msg(%+v)", string(msg.Value))
return nil, ErrInvalidMsg
}
key := fmt.Sprintf("%s%d", _prefixTask, taskmsg.BizID)
handler := s.findTaskHandler(key)
if handler == nil {
log.Error("databusgroup can not find handler for msg key(%+v)", key)
return nil, ErrHandlerMiss
}
data, err := handler.CheckMessage(msg)
if err != nil {
errmsg := fmt.Sprintf("databusgroup new msg key(%+v) partition(%d) offset(%d) value(%s) CheckMessage(%v)", msg.Key, msg.Partition, msg.Offset, string(msg.Value), pkgerr.WithStack(err))
if err == ErrTaskDuplicate {
log.Warn(errmsg)
} else {
log.Error(errmsg)
}
}
return data, err
}
func (s *Service) splittask(msg *databus.Message, data interface{}) int {
if t, ok := data.(*model.Task); ok {
return int(t.BusinessID)
}
return 0
}
func (s *Service) dotask(bmsgs []interface{}) {
for _, msg := range bmsgs {
log.Info("databusgroup dotask msg(%+v)", msg)
var key string
if t, ok := msg.(*model.Task); ok {
key = fmt.Sprintf("%s%d", _prefixTask, t.BusinessID)
} else {
log.Error("databusgroup dotask unknow msg(%+v)", msg)
continue
}
handler := s.findTaskHandler(key)
if handler == nil {
log.Error("databusgroup dotask msg(%+v) handler NotFound", msg)
continue
}
if err := handler.HandleMessage(context.Background(), msg); err != nil {
log.Error("databusgroup dotask msg(%+v) handler err(%v)", msg, pkgerr.WithStack(err))
continue
}
}
}