- all db orm use beego orm, don't use gorm anymore.
This commit is contained in:
168
business/jxutils/dtask/dtask.go
Normal file
168
business/jxutils/dtask/dtask.go
Normal 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, ¶ms)
|
||||
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
|
||||
}
|
||||
100
business/jxutils/dtask/dtask_test.go
Normal file
100
business/jxutils/dtask/dtask_test.go
Normal 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)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user