go-common/app/job/main/aegis/service/handler.go
2019-04-22 18:49:16 +08:00

374 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}
}