- category sync almost ok.

- refactor tasksch (isContinueWhenError)
This commit is contained in:
gazebo
2018-09-22 10:26:31 +08:00
parent 0623d31c71
commit 81089fb85c
13 changed files with 283 additions and 114 deletions

View File

@@ -47,6 +47,16 @@ func AddCategory(cat *model.SkuCategory, userName string) (outCat *model.SkuCate
dao.WrapAddIDCULDEntity(cat, userName) dao.WrapAddIDCULDEntity(cat, userName)
cat.JdSyncStatus = model.SyncFlagNewMask cat.JdSyncStatus = model.SyncFlagNewMask
cat.JdID = genTmpID() cat.JdID = genTmpID()
db := dao.GetDB()
if cat.Seq <= 0 {
var maxSeq struct {
MaxSeq int
}
if err = dao.GetRow(db, &maxSeq, "SELECT MAX(seq) max_seq FROM sku_category t1 WHERE level = ?", cat.Level); err != nil {
return nil, err
}
cat.Seq = maxSeq.MaxSeq + 1
}
if err = dao.CreateEntity(nil, cat); err == nil { if err = dao.CreateEntity(nil, cat); err == nil {
outCat = cat outCat = cat
err = CurVendorSync.SyncCategory(nil, cat.ID, false, userName) err = CurVendorSync.SyncCategory(nil, cat.ID, false, userName)
@@ -89,13 +99,12 @@ func ReorderCategories(parentID int, categoryIDs []int, userName string) (err er
catsMap[cat.ID] = cat catsMap[cat.ID] = cat
} }
for k, v := range categoryIDs { for k, v := range categoryIDs {
catsMap[v].Seq = (k + 1) * 5 catsMap[v].Seq = k
// catsMap[v].JdSyncStatus = model.SyncFlagModifiedMask catsMap[v].JdSyncStatus = model.SyncFlagModifiedMask
if _, err = dao.UpdateEntity(db, catsMap[v], "Seq"); err != nil { if _, err = dao.UpdateEntity(db, catsMap[v], "Seq"); err != nil {
break break
} }
} }
// todo 这里应该也需要先置标记
if err == nil { if err == nil {
err = CurVendorSync.SyncReorderCategories(db, parentID, false, userName) err = CurVendorSync.SyncReorderCategories(db, parentID, false, userName)
} }

View File

@@ -47,23 +47,28 @@ func (v *VendorSync) SyncCategory(db *dao.DaoDB, categoryID int, isForce bool, u
} }
err := dao.GetEntitiesByKV(db, &cats, cond, true) err := dao.GetEntitiesByKV(db, &cats, cond, true)
if err == nil { if err == nil {
tasksch.RunTask("", func(batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.RunTask("", false, nil, len(cats), 1, userName, func(batchItemList []interface{}, params ...interface{}) (interface{}, error) {
cat := batchItemList[0].(*model.SkuCategory) for _, v := range batchItemList {
updateFields := []string{model.FieldJdSyncStatus} cat := v.(*model.SkuCategory)
if (cat.JdSyncStatus & model.SyncFlagDeletedMask) != 0 { //删除 updateFields := []string{multiStoresHandler.GetFieldSyncStatusName()}
err = multiStoresHandler.DeleteCategory(db, cat, userName) if (cat.JdSyncStatus & model.SyncFlagDeletedMask) != 0 { //删除
} else if (cat.JdSyncStatus&model.SyncFlagNewMask) != 0 || isForce { // 新增 err = multiStoresHandler.DeleteCategory(db, cat, userName)
err = multiStoresHandler.CreateCategory(db, cat, userName) } else if (cat.JdSyncStatus&model.SyncFlagNewMask) != 0 || isForce { // 新增
updateFields = append(updateFields, model.FieldJdID) err = multiStoresHandler.CreateCategory(db, cat, userName)
} else if (cat.JdSyncStatus & model.SyncFlagModifiedMask) != 0 { // 修改 updateFields = append(updateFields, multiStoresHandler.GetFieldIDName())
err = multiStoresHandler.UpdateCategory(db, cat, userName) } else if (cat.JdSyncStatus & model.SyncFlagModifiedMask) != 0 { // 修改
} err = multiStoresHandler.UpdateCategory(db, cat, userName)
if err == nil { }
cat.JdSyncStatus = 0 if err == nil {
_, err = dao.UpdateEntity(db, cat, model.FieldJdSyncStatus) cat.JdSyncStatus = 0
_, err = dao.UpdateEntity(db, cat, updateFields...)
} else {
break
}
} }
return nil, err return nil, err
}, nil, len(cats), 1, "", cats) }, cats)
_, err = task.GetResult(0)
} }
return nil, err return nil, err
}) })
@@ -71,11 +76,17 @@ func (v *VendorSync) SyncCategory(db *dao.DaoDB, categoryID int, isForce bool, u
} }
func (v *VendorSync) SyncReorderCategories(db *dao.DaoDB, categoryID int, isForce bool, userName string) (err error) { func (v *VendorSync) SyncReorderCategories(db *dao.DaoDB, categoryID int, isForce bool, userName string) (err error) {
// todo err = v.LoopMultiStoresVendors(db, func(batchItemList []interface{}, params ...interface{}) (interface{}, error) {
if handler := GetPurchaseHandler(model.VendorIDJD); handler != nil { multiStoresHandler := batchItemList[0].(partner.IMultipleStoresHandler)
err = handler.(partner.IMultipleStoresHandler).ReorderCategories(db, categoryID, userName) err2 := multiStoresHandler.ReorderCategories(db, categoryID, userName)
} if err2 == nil {
return nil cat := &model.SkuCategory{}
_, err2 = dao.UpdateEntityByKV(db, cat, utils.Params2Map(multiStoresHandler.GetFieldSyncStatusName(), 0), utils.Params2Map(model.FieldParentID, categoryID))
return nil, err2
}
return nil, err2
})
return err
} }
func (v *VendorSync) SyncStore(db *dao.DaoDB, vendorID, storeID int, isForce bool, userName string) (err error) { func (v *VendorSync) SyncStore(db *dao.DaoDB, vendorID, storeID int, isForce bool, userName string) (err error) {
@@ -109,26 +120,30 @@ func (v *VendorSync) SyncSku(db *dao.DaoDB, nameID, skuID int, isForce bool, use
} }
err := dao.GetEntitiesByKV(db, &skuList, cond, true) err := dao.GetEntitiesByKV(db, &skuList, cond, true)
if err == nil { if err == nil {
globals.SugarLogger.Debug(utils.Format4Output(skuList, false)) // globals.SugarLogger.Debug(utils.Format4Output(skuList, false))
task := tasksch.RunTask("SyncSku", func(batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.RunTask("SyncSku", false, nil, len(skuList), 1, userName, func(batchItemList []interface{}, params ...interface{}) (interface{}, error) {
sku := batchItemList[0].(*model.Sku) for _, v := range batchItemList {
if (skuID == -1 || skuID == sku.ID) && (isForce || sku.JdSyncStatus != 0) { sku := v.(*model.Sku)
updateFields := []string{model.FieldJdSyncStatus} if (skuID == -1 || skuID == sku.ID) && (isForce || sku.JdSyncStatus != 0) {
if sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 updateFields := []string{multiStoresHandler.GetFieldSyncStatusName()}
err = multiStoresHandler.DeleteSku(db, sku, userName) if sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除
} else if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 新增 err = multiStoresHandler.DeleteSku(db, sku, userName)
err = multiStoresHandler.CreateSku(db, sku, userName) } else if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 新增
updateFields = append(updateFields, model.FieldJdID) err = multiStoresHandler.CreateSku(db, sku, userName)
} else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改 updateFields = append(updateFields, multiStoresHandler.GetFieldIDName())
err = multiStoresHandler.UpdateSku(db, sku, userName) } else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改
} err = multiStoresHandler.UpdateSku(db, sku, userName)
if err == nil { }
sku.JdSyncStatus = 0 if err == nil {
dao.UpdateEntity(db, sku, updateFields...) sku.JdSyncStatus = 0
dao.UpdateEntity(db, sku, updateFields...)
} else {
break
}
} }
} }
return nil, err return nil, err
}, nil, len(skuList), 1, "", skuList) }, skuList)
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
return nil, err return nil, err
@@ -152,14 +167,14 @@ func (v *VendorSync) SyncStoreSku(db *dao.DaoDB, storeID int, skuIDs []int, isFo
func (v *VendorSync) LoopStoreMap(db *dao.DaoDB, storeID int, handler tasksch.WorkFunc) (err error) { func (v *VendorSync) LoopStoreMap(db *dao.DaoDB, storeID int, handler tasksch.WorkFunc) (err error) {
storeMaps, err := GetStoreVendorMaps(db, storeID, -1) storeMaps, err := GetStoreVendorMaps(db, storeID, -1)
if err == nil { if err == nil {
task := tasksch.RunTask("", handler, nil, len(storeMaps), 1, "", storeMaps) task := tasksch.RunTask("LoopStoreMap", false, nil, len(storeMaps), 1, "", handler, storeMaps)
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
return err return err
} }
func (v *VendorSync) LoopMultiStoresVendors(db *dao.DaoDB, handler tasksch.WorkFunc) (err error) { func (v *VendorSync) LoopMultiStoresVendors(db *dao.DaoDB, handler tasksch.WorkFunc) (err error) {
task := tasksch.RunTask("LoopMultiStoresVendors", handler, nil, len(MultiStoresVendorHandlers), 1, "", MultiStoresVendorHandlers) task := tasksch.RunTask("LoopMultiStoresVendors", false, nil, len(MultiStoresVendorHandlers), 1, "", handler, MultiStoresVendorHandlers)
_, err = task.GetResult(0) _, err = task.GetResult(0)
return err return err
} }
@@ -177,7 +192,39 @@ func (v *VendorSync) LoopSingleStoreVendors(db *dao.DaoDB, taskName, userName st
if parellelCount > 20 { if parellelCount > 20 {
parellelCount = 20 parellelCount = 20
} }
tasksch.RunManagedTask(taskName, handler, nil, parellelCount, 1, userName, storeMaps) task := tasksch.RunManagedTask(taskName, false, nil, parellelCount, 1, userName, handler, storeMaps)
_, err = task.GetResult(0)
}
return err
}
func (v *VendorSync) RefreshSkuIDs(nameID, skuID int, isForce bool, userName string) (err error) {
sql := `
SELECT t1.id
FROM sku t1
JOIN sku_name t2 ON t1.name_id = t2.id
WHERE 1 = 1
`
sqlParams := []interface{}{}
if nameID != -1 {
sql += " AND t1.name_id = ?"
sqlParams = append(sqlParams, nameID)
}
if skuID != -1 {
sql += " AND t1.id = ?"
sqlParams = append(sqlParams, skuID)
}
var ids []int
db := dao.GetDB()
if err = dao.GetRows(db, &ids, sql, sqlParams); err == nil {
// globals.SugarLogger.Debug(utils.Format4Output(ids, false))
err = v.LoopMultiStoresVendors(db, func(batchItemList []interface{}, params ...interface{}) (interface{}, error) {
multiStoresHandler := batchItemList[0].(partner.IMultipleStoresHandler)
err := multiStoresHandler.SyncSkusIDMap(db, ids, userName)
globals.SugarLogger.Debug(err)
return nil, err
})
} }
return err return err
} }

View File

@@ -3,6 +3,7 @@ package jxutils
import ( import (
"fmt" "fmt"
"math" "math"
"reflect"
"strings" "strings"
"time" "time"
@@ -17,8 +18,13 @@ func MergeStoreStatus(status int, vendorStatus int) int {
return vendorStatus return vendorStatus
} }
func SplitSlice(list []interface{}, batchCount int) (listInList [][]interface{}) { func SplitSlice(list interface{}, batchCount int) (listInList [][]interface{}) {
len := len(list) typeInfo := reflect.TypeOf(list)
if typeInfo.Kind() != reflect.Slice {
panic("list must be slice")
}
valueInfo := reflect.ValueOf(list)
len := valueInfo.Len()
if len > 0 { if len > 0 {
listInListLen := (len-1)/batchCount + 1 listInListLen := (len-1)/batchCount + 1
listInList = make([][]interface{}, listInListLen) listInList = make([][]interface{}, listInListLen)
@@ -32,7 +38,7 @@ func SplitSlice(list []interface{}, batchCount int) (listInList [][]interface{})
} }
listInList[index] = make([]interface{}, arrLen) listInList[index] = make([]interface{}, arrLen)
} }
listInList[index][i%batchCount] = list[i] listInList[index][i%batchCount] = valueInfo.Index(i).Interface()
} }
} }
return listInList return listInList
@@ -107,3 +113,7 @@ func CaculateSkuPrice(unitPrice int, specQuality float32, specUnit string) int {
} }
return int(math.Round(float64(float32(unitPrice) * specQuality / 500))) return int(math.Round(float64(float32(unitPrice) * specQuality / 500)))
} }
func GetSliceLen(list interface{}) int {
return reflect.ValueOf(list).Len()
}

View File

@@ -22,22 +22,29 @@ const (
TaskStatusEnd = 4 TaskStatusEnd = 4
) )
const (
MaxParallelCount = 10
)
type WorkFunc func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) type WorkFunc func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error)
type ResultHandlerFunc func(taskName string, result []interface{}, err error) type ResultHandlerFunc func(taskName string, result []interface{}, err error)
type Task struct { type Task struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
CreatedBy string `json:"createdBy"` CreatedBy string `json:"createdBy"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
TerminatedAt time.Time `json:"terminatedAt"` TerminatedAt time.Time `json:"terminatedAt"`
ParallelCount int `json:"parallelCount"` ParallelCount int `json:"parallelCount"`
TotalItemCount int `json:"totalItemCount"` TotalItemCount int `json:"totalItemCount"`
TotalJobCount int `json:"totalJobCount"` TotalJobCount int `json:"totalJobCount"`
FinishedItemCount int `json:"finishedItemCount"` FinishedItemCount int `json:"finishedItemCount"`
FinishedJobCount int `json:"finishedJobCount"` FinishedJobCount int `json:"finishedJobCount"`
Status int `json:"status"` FailedItemCount int `json:"failedItemCount"`
FailedJobCount int `json:"failedJobCount"`
IsContinueWhenError bool `json:"isContinueWhenError"`
Status int `json:"status"`
C <-chan int `json:"-"` C <-chan int `json:"-"`
@@ -72,23 +79,31 @@ var (
ErrTaskIsCanceled = errors.New("任务被取消了") ErrTaskIsCanceled = errors.New("任务被取消了")
) )
func RunTask(taskName string, worker WorkFunc, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, itemList interface{}, params ...interface{}) *Task { func RunTask(taskName string, isContinueWhenError bool, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, worker WorkFunc, itemList interface{}, params ...interface{}) *Task {
if parallelCount > MaxParallelCount {
parallelCount = MaxParallelCount
}
listLen := jxutils.GetSliceLen(itemList)
if parallelCount > listLen {
parallelCount = listLen
}
realItemList := utils.Interface2Slice(itemList) realItemList := utils.Interface2Slice(itemList)
jobList := jxutils.SplitSlice(realItemList, batchSize) jobList := jxutils.SplitSlice(realItemList, batchSize)
task := &Task{ task := &Task{
ID: utils.GetUUID(), ID: utils.GetUUID(),
Name: taskName, Name: taskName,
CreatedAt: time.Now(), CreatedAt: time.Now(),
CreatedBy: userName, CreatedBy: userName,
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
TotalJobCount: len(jobList), TotalJobCount: len(jobList),
TotalItemCount: len(realItemList), TotalItemCount: len(realItemList),
ParallelCount: parallelCount, ParallelCount: parallelCount,
taskChan: make(chan []interface{}, parallelCount*100), taskChan: make(chan []interface{}, len(realItemList)+parallelCount), // 确保能装下所有taskitem加结束标记
quitChan: make(chan int, parallelCount), quitChan: make(chan int, parallelCount),
subFinishChan: make(chan interface{}, parallelCount), subFinishChan: make(chan interface{}, parallelCount),
finishChan: make(chan int, 2), finishChan: make(chan int, 2),
Status: TaskStatusWorking, Status: TaskStatusWorking,
IsContinueWhenError: isContinueWhenError,
} }
task.C = task.finishChan task.C = task.finishChan
go func() { go func() {
@@ -99,35 +114,34 @@ func RunTask(taskName string, worker WorkFunc, resultHandler ResultHandlerFunc,
retVal := make([]interface{}, 0) retVal := make([]interface{}, 0)
for { for {
select { select {
case <-task.quitChan: case <-task.quitChan: // 取消
goto end goto end
case job := <-task.taskChan: case job := <-task.taskChan:
if job == nil { if job == nil { // 任务完成
chanRetVal = retVal chanRetVal = retVal
goto end goto end
} else { } else {
result, err := worker(job, params...) result, err := worker(job, params...)
globals.SugarLogger.Debugf("RunTask %s, after call worker result:%v, err:%v", taskName, result, err) globals.SugarLogger.Debugf("RunTask %s, after call worker result:%v, err:%v", taskName, result, err)
task.finishedOneJob(len(job), err)
if err == nil { if err == nil {
task.finishedOneJob(len(job))
if result != nil { if result != nil {
retVal = append(retVal, utils.Interface2Slice(result)...) retVal = append(retVal, utils.Interface2Slice(result)...)
} }
} else { } else if !isContinueWhenError { // 出错
chanRetVal = err chanRetVal = err
go func() {
task.Cancel()
}()
goto end goto end
} }
} }
} }
} }
end: end:
// globals.SugarLogger.Debugf("RunTask %s, put to chann chanRetVal:%v", taskName, chanRetVal) globals.SugarLogger.Debugf("RunTask %s, put to chann chanRetVal:%v", taskName, chanRetVal)
if task.GetStatus() < TaskStatusEndBegin { task.locker.RLock()
if task.Status < TaskStatusEndBegin {
task.subFinishChan <- chanRetVal task.subFinishChan <- chanRetVal
} }
task.locker.RUnlock()
}() }()
} }
for _, job := range jobList { for _, job := range jobList {
@@ -141,10 +155,12 @@ func RunTask(taskName string, worker WorkFunc, resultHandler ResultHandlerFunc,
var taskErr error var taskErr error
for i := 0; i < parallelCount; i++ { for i := 0; i < parallelCount; i++ {
result := <-task.subFinishChan result := <-task.subFinishChan
// globals.SugarLogger.Debugf("RunTask %s, received from chann result:%v", taskName, result)
if err2, ok := result.(error); ok { if err2, ok := result.(error); ok {
task.Cancel()
taskResult = nil taskResult = nil
taskErr = err2 taskErr = err2
break break // 出错情况下是否需要直接跳出?
} else if result != nil { } else if result != nil {
resultList := result.([]interface{}) resultList := result.([]interface{})
taskResult = append(taskResult, resultList...) taskResult = append(taskResult, resultList...)
@@ -201,11 +217,13 @@ func (t *Task) GetResult(duration time.Duration) (retVal []interface{}, err erro
} }
func (t *Task) Cancel() { func (t *Task) Cancel() {
if t.GetStatus() < TaskStatusEndBegin { t.locker.Lock()
defer t.locker.Unlock()
if t.Status < TaskStatusEndBegin && t.Status != TaskStatusCanceling {
t.Status = TaskStatusCanceling
for i := 0; i < t.ParallelCount; i++ { for i := 0; i < t.ParallelCount; i++ {
t.quitChan <- 0 t.quitChan <- 0
} }
t.setStatus(TaskStatusCanceling)
} }
} }
@@ -240,13 +258,18 @@ func (t *Task) GetStatus() int {
///////// /////////
func (t *Task) finishedOneJob(itemCount int) { func (t *Task) finishedOneJob(itemCount int, err error) {
t.locker.Lock() t.locker.Lock()
defer t.locker.Unlock() defer t.locker.Unlock()
t.UpdatedAt = time.Now() t.UpdatedAt = time.Now()
t.FinishedItemCount += itemCount if err == nil {
t.FinishedJobCount++ t.FinishedItemCount += itemCount
t.FinishedJobCount++
} else {
t.FailedItemCount += itemCount
t.FailedJobCount++
}
} }
func (t *Task) setStatus(status int) { func (t *Task) setStatus(status int) {

View File

@@ -17,8 +17,8 @@ func init() {
defTaskMan.taskList = make(map[string]*Task) defTaskMan.taskList = make(map[string]*Task)
} }
func (m *TaskMan) RunTask(taskName string, worker WorkFunc, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, itemList interface{}, params ...interface{}) *Task { func (m *TaskMan) RunTask(taskName string, isContinueWhenError bool, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, worker WorkFunc, itemList interface{}, params ...interface{}) *Task {
task := RunTask(taskName, worker, resultHandler, parallelCount, batchSize, userName, itemList, params...) task := RunTask(taskName, isContinueWhenError, resultHandler, parallelCount, batchSize, userName, worker, itemList, params...)
m.taskList[task.ID] = task m.taskList[task.ID] = task
return task return task
} }
@@ -34,8 +34,8 @@ func (m *TaskMan) GetTasks(taskID string, fromStatus, toStatus int, lastHours in
return taskList return taskList
} }
func RunManagedTask(taskName string, worker WorkFunc, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, itemList interface{}, params ...interface{}) *Task { func RunManagedTask(taskName string, isContinueWhenError bool, resultHandler ResultHandlerFunc, parallelCount, batchSize int, userName string, worker WorkFunc, itemList interface{}, params ...interface{}) *Task {
return defTaskMan.RunTask(taskName, worker, resultHandler, parallelCount, batchSize, userName, itemList, params...) return defTaskMan.RunTask(taskName, isContinueWhenError, resultHandler, parallelCount, batchSize, userName, worker, itemList, params...)
} }
func GetTasks(taskID string, fromStatus, toStatus int, lastHours int) (taskList []*Task) { func GetTasks(taskID string, fromStatus, toStatus int, lastHours int) (taskList []*Task) {

View File

@@ -13,7 +13,10 @@ func TestTaskMan(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task1 := RunManagedTask("test", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task1 := RunManagedTask("test", false, func(taskName string, result []interface{}, err error) {
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
sleepSecond := rand.Intn(5) sleepSecond := rand.Intn(5)
t.Logf("sleep %d seconds", sleepSecond) t.Logf("sleep %d seconds", sleepSecond)
time.Sleep(time.Duration(sleepSecond) * time.Second) time.Sleep(time.Duration(sleepSecond) * time.Second)
@@ -22,12 +25,12 @@ func TestTaskMan(t *testing.T) {
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
} }
return retSlice, nil return retSlice, nil
}, func(taskName string, result []interface{}, err error) { }, itemList, "a", "b", 1, 2)
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", itemList, "a", "b", 1, 2)
task2 := RunManagedTask("test", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task2 := RunManagedTask("test", false, func(taskName string, result []interface{}, err error) {
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
sleepSecond := rand.Intn(5) sleepSecond := rand.Intn(5)
t.Logf("sleep %d seconds", sleepSecond) t.Logf("sleep %d seconds", sleepSecond)
time.Sleep(time.Duration(sleepSecond) * time.Second) time.Sleep(time.Duration(sleepSecond) * time.Second)
@@ -36,10 +39,7 @@ func TestTaskMan(t *testing.T) {
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
} }
return retSlice, nil return retSlice, nil
}, func(taskName string, result []interface{}, err error) { }, itemList, "a", "b", 1, 2)
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", itemList, "a", "b", 1, 2)
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
task2.Cancel() task2.Cancel()
if task1.GetStatus() == task2.GetStatus() { if task1.GetStatus() == task2.GetStatus() {

View File

@@ -13,7 +13,10 @@ func TestRunTask(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task := RunTask("test", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := RunTask("test", false, func(taskName string, result []interface{}, err error) {
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
sleepSecond := rand.Intn(5) sleepSecond := rand.Intn(5)
t.Logf("sleep %d seconds", sleepSecond) t.Logf("sleep %d seconds", sleepSecond)
time.Sleep(time.Duration(sleepSecond) * time.Second) time.Sleep(time.Duration(sleepSecond) * time.Second)
@@ -22,10 +25,7 @@ func TestRunTask(t *testing.T) {
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
} }
return retSlice, nil return retSlice, nil
}, func(taskName string, result []interface{}, err error) { }, itemList, "a", "b", 1, 2)
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", itemList, "a", "b", 1, 2)
result, err := task.GetResult(1 * time.Microsecond) result, err := task.GetResult(1 * time.Microsecond)
if err == nil || task.GetStatus() != TaskStatusWorking { if err == nil || task.GetStatus() != TaskStatusWorking {
t.Fatal("task can not be done in 1 microsecond") t.Fatal("task can not be done in 1 microsecond")
@@ -46,7 +46,10 @@ func TestCancelTask(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task := RunTask("test", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := RunTask("test", false, func(taskName string, result []interface{}, err error) {
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
sleepSecond := rand.Intn(5) sleepSecond := rand.Intn(5)
t.Logf("sleep %d seconds", sleepSecond) t.Logf("sleep %d seconds", sleepSecond)
time.Sleep(time.Duration(sleepSecond) * time.Second) time.Sleep(time.Duration(sleepSecond) * time.Second)
@@ -55,10 +58,7 @@ func TestCancelTask(t *testing.T) {
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
} }
return retSlice, nil return retSlice, nil
}, func(taskName string, result []interface{}, err error) { }, itemList, "a", "b", 1, 2)
// t.Log("finished here")
// t.Log(utils.Format4Output(result, false))
}, 100, 7, "autotest", itemList, "a", "b", 1, 2)
// time.Sleep(time.Second * 6) // time.Sleep(time.Second * 6)
t.Logf("finishedItemCount:%d, finishedJobCount:%d", task.GetFinishedItemCount(), task.GetFinishedJobCount()) t.Logf("finishedItemCount:%d, finishedJobCount:%d", task.GetFinishedItemCount(), task.GetFinishedJobCount())
task.Cancel() task.Cancel()

View File

@@ -78,6 +78,9 @@ type IPurchasePlatformHandler interface {
// db *dao.DaoDB, // db *dao.DaoDB,
type IMultipleStoresHandler interface { type IMultipleStoresHandler interface {
GetFieldIDName() string
GetFieldSyncStatusName() string
ReadCategories() (cats []*model.SkuCategory, err error) ReadCategories() (cats []*model.SkuCategory, err error)
CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error)
@@ -90,6 +93,8 @@ type IMultipleStoresHandler interface {
ReadSku(vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) ReadSku(vendorSkuID string) (skuNameExt *model.SkuNameExt, err error)
UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
SyncSkusIDMap(db *dao.DaoDB, skuIDs []int, userName string) (err error)
} }
type ISingleStoreHandler interface { type ISingleStoreHandler interface {

View File

@@ -3,8 +3,10 @@ package jd
// 这里函数取得的信息除了与自身实体相关的ID比如PARENT ID都已经转换成了本地ID了 // 这里函数取得的信息除了与自身实体相关的ID比如PARENT ID都已经转换成了本地ID了
import ( import (
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner"
@@ -137,7 +139,6 @@ func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuE
} }
if err == nil { if err == nil {
skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, skuInfoExt.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, 0) skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, skuInfoExt.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, 0)
globals.SugarLogger.Debug(utils.Format4Output(skuInfoExt, false), utils.Format4Output(sku, false))
skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit) skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit)
result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams) result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams)
if err = err2; err == nil { if err = err2; err == nil {
@@ -252,6 +253,48 @@ func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName stri
return err return err
} }
func (p *PurchaseHandler) SyncSkusIDMap(db *dao.DaoDB, skuIDs []int, userName string) (err error) {
sql := `
SELECT t1.id out_sku_id, t1.jd_id sku_id
FROM sku t1
WHERE t1.jd_sync_status <> 0
`
// AND t1.jd_sync_status <> 0
sqlParams := []interface{}{}
if skuIDs != nil && len(skuIDs) > 0 {
sql += " AND t1.id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuIDs)
}
var skuPairs []*jdapi.SkuIDPair
if err = dao.GetRows(db, &skuPairs, sql, sqlParams); err == nil {
// globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
globals.SugarLogger.Debug(len(skuPairs))
task := tasksch.RunTask("SyncSkusIDMap", true, nil, 10, 1, userName, func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList))
for k, v := range batchItemList {
pair := v.(*jdapi.SkuIDPair)
skuPairs[k] = &jdapi.SkuIDPair{
SkuId: pair.SkuId,
OutSkuId: pair.OutSkuId, //utils.GetUUID(),
}
}
if _, err = api.JdAPI.BatchUpdateOutSkuId(skuPairs); err == nil {
// for k, v := range batchItemList {
// pair := v.(*jdapi.SkuIDPair)
// skuPairs[k].OutSkuId = pair.OutSkuId
// }
// _, err = api.JdAPI.BatchUpdateOutSkuId(skuPairs)
}
if err != nil {
globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
}
return nil, err
}, skuPairs)
_, err = task.GetResult(0)
}
return err
}
func jdStatus2jxStatus(jdStatus int) (jxStatus int) { func jdStatus2jxStatus(jdStatus int) (jxStatus int) {
switch jdStatus { switch jdStatus {
case 1: case 1:

View File

@@ -26,6 +26,14 @@ type tJdStoreInfo struct {
SyncStatus int SyncStatus int
} }
func (p *PurchaseHandler) GetFieldIDName() string {
return model.FieldJdID
}
func (p *PurchaseHandler) GetFieldSyncStatusName() string {
return model.FieldJdSyncStatus
}
func (p *PurchaseHandler) ReadStore(vendorStoreID string) (*model.Store, error) { func (p *PurchaseHandler) ReadStore(vendorStoreID string) (*model.Store, error) {
result, err := api.JdAPI.GetStoreInfoByStationNo(vendorStoreID) result, err := api.JdAPI.GetStoreInfoByStationNo(vendorStoreID)
if err == nil { if err == nil {

View File

@@ -29,7 +29,7 @@ func (p *PurchaseHandler) SyncStoreSkus(db *dao.DaoDB, storeIDs []int, skuIDs []
globals.SugarLogger.Debug(sql, sqlParams) globals.SugarLogger.Debug(sql, sqlParams)
if err = dao.GetRows(db, &storeSkus, sql, sqlParams); err == nil { if err = dao.GetRows(db, &storeSkus, sql, sqlParams); err == nil {
outStationNo := utils.Int2Str(storeID) outStationNo := utils.Int2Str(storeID)
task := tasksch.RunTask("", func(batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.RunTask("", false, nil, 10, 50, userName, func(batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var skuPriceInfoList []*jdapi.SkuPriceInfo var skuPriceInfoList []*jdapi.SkuPriceInfo
var skuVendibilityList []*jdapi.StockVendibility var skuVendibilityList []*jdapi.StockVendibility
var skuStockList []*jdapi.SkuStock var skuStockList []*jdapi.SkuStock
@@ -77,7 +77,7 @@ func (p *PurchaseHandler) SyncStoreSkus(db *dao.DaoDB, storeIDs []int, skuIDs []
} }
} }
return nil, err return nil, err
}, nil, 10, 50, userName, storeSkus) }, storeSkus)
if _, err = task.GetResult(0); err == nil { if _, err = task.GetResult(0); err == nil {
sql := ` sql := `
UPDATE store_sku_bind UPDATE store_sku_bind

View File

@@ -299,3 +299,19 @@ func (c *SkuController) SyncSkus() {
return retVal, "", err return retVal, "", err
}) })
} }
// @Title 重新刷新商家ID
// @Description 重新刷新商家ID
// @Param token header string true "认证token"
// @Param nameID query int true "name ID, -1表示所有"
// @Param skuID query int true "sku ID, -1表示所有"
// @Param isForce query bool false "是否强制刷新,缺省为否"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /RefreshSkuIDs [put]
func (c *SkuController) RefreshSkuIDs() {
c.callRefreshSkuIDs(func(params *tSkuRefreshSkuIDsParams) (retVal interface{}, errCode string, err error) {
err = cms.CurVendorSync.RefreshSkuIDs(params.NameID, params.SkuID, false, GetUserNameFromToken(params.Token))
return retVal, "", err
})
}

View File

@@ -263,6 +263,14 @@ func init() {
MethodParams: param.Make(), MethodParams: param.Make(),
Params: nil}) Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "RefreshSkuIDs",
Router: `/RefreshSkuIDs`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{ beego.ControllerComments{
Method: "ReorderCategories", Method: "ReorderCategories",