- all db orm use beego orm, don't use gorm anymore.

This commit is contained in:
gazebo
2018-09-08 12:55:39 +08:00
parent 711013fab4
commit 8c130a15a4
28 changed files with 780 additions and 448 deletions

View File

@@ -0,0 +1,168 @@
package dtask
import (
"bytes"
"encoding/base64"
"encoding/gob"
"errors"
"reflect"
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/basesch"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
)
var (
CurMan *DurableTaskMan
)
type DurableTaskMan struct {
objCreator func(objHint string) interface{}
tasks map[string]*DurableTask
}
type DurableTask struct {
cmdChan chan string
data *model.DurableTask
itemCount int
items []*model.DurableTaskItem
}
func Init(objCreator func(objHint string) interface{}, interfaceTypes ...interface{}) {
if CurMan == nil {
if objCreator == nil {
objCreator = defObjCreator
}
CurMan = &DurableTaskMan{
tasks: make(map[string]*DurableTask),
objCreator: objCreator,
}
for _, v := range interfaceTypes {
gob.Register(v)
}
}
}
func (m *DurableTaskMan) LoadPendingTask() (err error) {
db := dao.GetDB()
tasks := make([]*model.DurableTask, 0)
if err = dao.GetRows(db, &tasks, "SELECT * FROM durable_task WHERE status = 0"); err == nil {
for _, task := range tasks {
dTask := &DurableTask{
data: task,
}
m.tasks[task.TaskID] = dTask
return dao.GetRows(db, &dTask.items, "SELECT * FROM durable_task_item WHERE status = 0")
}
}
return err
}
func (m *DurableTaskMan) Start() error {
for _, task := range m.tasks {
m.StartTask(task.data.TaskID)
}
return nil
}
func (m *DurableTaskMan) AddTask(desc, createdBy string) (taskID string, err error) {
task := &DurableTask{}
task.data = &model.DurableTask{
TaskID: utils.GetUUID(),
Description: desc,
CreatedBy: createdBy,
Status: 0,
FinishedAt: utils.DefaultTimeValue,
}
if err = dao.CreateEntity(nil, task.data); err == nil {
m.tasks[task.data.TaskID] = task
return task.data.TaskID, nil
}
return "", err
}
func (m *DurableTaskMan) AddItem(taskID, objHint string, funcName string, params ...interface{}) (err error) {
d := m.tasks[taskID]
d.data.TotalItem++
item := &model.DurableTaskItem{
ObjHint: objHint,
FuncName: funcName,
TaskID: d.data.TaskID,
TaskIndex: d.data.TotalItem,
FinishedAt: utils.DefaultTimeValue,
}
if item.Params, err = SerializeData(params); err == nil {
db := dao.GetDB()
if err = dao.CreateEntity(db, item); err == nil {
err = dao.UpdateEntity(db, d.data, "TotalItem")
d.items = append(d.items, item)
}
}
d.data.TotalItem--
return err
}
func (m *DurableTaskMan) StartTask(taskID string) error {
d := m.tasks[taskID]
if d.cmdChan == nil {
d.cmdChan = make(chan string)
go func() {
failedItemCount := 0
for _, taskItem := range d.items {
if taskItem.Status == 0 {
obj := m.objCreator(taskItem.ObjHint)
objValue := reflect.ValueOf(obj)
func2Call := objValue.MethodByName(taskItem.FuncName)
params := []interface{}{}
DeSerializeData(taskItem.Params, &params)
valueParams := make([]reflect.Value, len(params))
for k, v := range params {
valueParams[k] = reflect.ValueOf(v)
}
if func2Call.Call(valueParams)[0].IsNil() {
taskItem.Status = 1
taskItem.FinishedAt = time.Now()
taskItem.UpdatedAt = taskItem.FinishedAt
dao.UpdateEntity(nil, taskItem, "Status", "FinishedAt", "UpdatedAt")
} else {
failedItemCount++
}
}
}
if failedItemCount == 0 {
d.data.Status = 1
d.data.FinishedAt = time.Now()
d.data.UpdatedAt = d.data.FinishedAt
dao.UpdateEntity(nil, d.data, "Status", "FinishedAt", "UpdatedAt")
}
}()
return nil
}
return errors.New("任务已经启动")
}
func defObjCreator(objHint string) interface{} {
return basesch.FixedBaseScheduler.GetPurchasePlatformFromVendorID(0)
}
func SerializeData(data interface{}) (strValue string, err error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err = enc.Encode(data); err == nil {
strValue = base64.StdEncoding.EncodeToString(buf.Bytes())
return strValue, nil
}
return "", err
}
func DeSerializeData(strValue string, dataPtr interface{}) (err error) {
byteData, err := base64.StdEncoding.DecodeString(strValue)
if err == nil {
dec := gob.NewDecoder(bytes.NewReader(byteData))
return dec.Decode(dataPtr)
}
return err
}

View File

@@ -0,0 +1,100 @@
package dtask
import (
"bytes"
"encoding/gob"
"testing"
"time"
"git.rosy.net.cn/baseapi/utils"
_ "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch"
"git.rosy.net.cn/jx-callback/business/model"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/jx-callback/globals/beegodb"
"github.com/astaxie/beego"
)
func init() {
beego.InitBeegoBeforeTest("/Users/xujianhua/go/src/git.rosy.net.cn/jx-callback/conf/app.conf")
// beego.BConfig.RunMode = "dev" // InitBeegoBeforeTest会将runmode设置为test
globals.Init()
beegodb.Init()
api.Init()
}
func TestScope(t *testing.T) {
}
func TestIt(t *testing.T) {
Init(myObjCreator, []*model.Store{})
var err error
// taskID, err := CurMan.AddTask("testtask", "xjh")
// if err != nil {
// t.Fatal(err)
// }
// tt := []*model.Store{
// &model.Store{
// Name: "storename",
// },
// }
// pp := "asdfsafs"
// err = CurMan.AddItem(taskID, "0", "DurableTaskTestFunc", 1, "str", map[string]interface{}{
// "key1": "value1",
// "key2": 100,
// "key3": &pp,
// }, []interface{}{1, "hello"}, tt)
// err = CurMan.AddItem(taskID, "0", "DurableTaskTestFunc", 1, "str", map[string]interface{}{
// "key1": "value1",
// "key2": 100,
// "key3": &pp,
// }, []interface{}{1, "hello"}, tt)
// if err != nil {
// t.Fatal(err)
// }
// err = CurMan.StartTask(taskID)
err = CurMan.LoadPendingTask()
if err != nil {
t.Fatal(err)
}
err = CurMan.Start()
if err != nil {
t.Fatal(err)
}
// CurMan.LoadPendingTask()
// CurMan.Start()
time.Sleep(3 * time.Second)
}
func TestEncode(t *testing.T) {
data := []interface{}{
3,
"abc",
float32(3.4),
}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
enc.Encode(data)
// t.Log(string(buf.Bytes()))
var kk []interface{}
dec.Decode(&kk)
t.Log(kk)
}
type tTest struct {
}
func (p *tTest) DurableTaskTestFunc(intParam int, strParam string, mapParam map[string]interface{}, sliceParam []interface{}, tt []*model.Store) error {
globals.SugarLogger.Debug(intParam, strParam, mapParam, sliceParam)
globals.SugarLogger.Debug(utils.Format4Output(tt, false))
time.Sleep(1 * time.Second)
return nil // errors.New("hello")
}
func myObjCreator(objHint string) interface{} {
return new(tTest)
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"math"
"math/rand"
"reflect"
"regexp"
"strings"
"sync"
@@ -271,12 +272,41 @@ func SplitSkuName(skuName string) (prefix, name, comment, specUnit, unit string,
return prefix, name, comment, specUnit, unit, specQuality
}
func FilterMapByStructObject(mapData map[string]interface{}, obj interface{}) (valid map[string]interface{}, invalid map[string]interface{}) {
func FlatMap(in map[string]interface{}) map[string]interface{} {
keys := []string{}
maps := []map[string]interface{}{}
for k, v := range in {
if vMap, ok := v.(map[string]interface{}); ok {
maps = append(maps, vMap)
keys = append(keys, k)
}
}
if len(maps) > 0 {
retVal := utils.MergeMaps(in, maps...)
for _, v := range keys {
delete(retVal, v)
}
return retVal
}
return in
}
func Struct2FlatMap(obj interface{}) map[string]interface{} {
m := structs.Map(obj)
return FlatMap(m)
}
func FilterMapByStructObject(mapData map[string]interface{}, obj interface{}, excludedFields []string) (valid map[string]interface{}, invalid map[string]interface{}) {
excludedMap := make(map[string]int)
for _, v := range excludedFields {
excludedMap[v] = 1
}
m := Struct2FlatMap(obj)
valid = make(map[string]interface{})
invalid = make(map[string]interface{})
for k, v := range mapData {
if m[k] != nil {
if m[k] != nil && excludedMap[k] == 0 {
valid[k] = v
} else {
invalid[k] = v
@@ -284,3 +314,24 @@ func FilterMapByStructObject(mapData map[string]interface{}, obj interface{}) (v
}
return valid, invalid
}
func NormalFilterMapByStructObject(mapData map[string]interface{}, obj interface{}) (valid map[string]interface{}, invalid map[string]interface{}) {
return FilterMapByStructObject(mapData, obj, []string{"id", "createdAt"})
}
func FilterMapByFieldList(mapData map[string]interface{}, fields []string) (valid map[string]interface{}, invalid map[string]interface{}) {
valid = make(map[string]interface{})
invalid = make(map[string]interface{})
for _, field := range fields {
if mapData[field] != nil {
valid[field] = mapData[field]
} else {
invalid[field] = mapData[field]
}
}
return valid, invalid
}
func GetObjFieldByName(obj interface{}, fieldName string) interface{} {
return reflect.Indirect(reflect.ValueOf(obj)).FieldByName(fieldName).Interface()
}