- timer task shceuled to order goroutine to avoid concurrent problem.
This commit is contained in:
@@ -5,7 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/baseapi/utils/routinepool"
|
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
"git.rosy.net.cn/jx-callback/business/scheduler"
|
"git.rosy.net.cn/jx-callback/business/scheduler"
|
||||||
_ "git.rosy.net.cn/jx-callback/business/scheduler/defsch" // 导入缺省订单调度器
|
_ "git.rosy.net.cn/jx-callback/business/scheduler/defsch" // 导入缺省订单调度器
|
||||||
@@ -20,11 +20,9 @@ const (
|
|||||||
var (
|
var (
|
||||||
OrderManager *OrderController
|
OrderManager *OrderController
|
||||||
WaybillManager *WaybillController
|
WaybillManager *WaybillController
|
||||||
routinePool *routinepool.Pool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
routinePool = routinepool.New(1000, 1000)
|
|
||||||
OrderManager = NewOrderManager()
|
OrderManager = NewOrderManager()
|
||||||
WaybillManager = NewWaybillManager()
|
WaybillManager = NewWaybillManager()
|
||||||
scheduler.CurrentScheduler.RegisterOrderManager(OrderManager)
|
scheduler.CurrentScheduler.RegisterOrderManager(OrderManager)
|
||||||
@@ -51,13 +49,6 @@ func addOrderOrWaybillStatus(status *model.OrderStatus, db orm.Ormer) (isDuplica
|
|||||||
return isDuplicated, err
|
return isDuplicated, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func CallMsgHandler(handler func(), primaryID string) {
|
|
||||||
// handler()
|
|
||||||
routinePool.CallFun(func() {
|
|
||||||
handler()
|
|
||||||
}, primaryID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDataCityCodeFromOrder(order *model.GoodsOrder) (retVal string, err error) {
|
func GetDataCityCodeFromOrder(order *model.GoodsOrder) (retVal string, err error) {
|
||||||
var sql string
|
var sql string
|
||||||
if order.VendorID == model.VendorIDJD {
|
if order.VendorID == model.VendorIDJD {
|
||||||
@@ -110,47 +101,47 @@ func LoadPendingOrders() {
|
|||||||
orderNew := *order
|
orderNew := *order
|
||||||
orderNew.Status = model.OrderStatusNew
|
orderNew.Status = model.OrderStatusNew
|
||||||
orderNew.StatusTime = order.OrderCreatedAt
|
orderNew.StatusTime = order.OrderCreatedAt
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnOrderNew(&orderNew)
|
scheduler.CurrentScheduler.OnOrderNew(&orderNew)
|
||||||
}, order.VendorOrderID)
|
}, order.VendorOrderID)
|
||||||
for _, bill := range billsMap[order.VendorOrderID] {
|
for _, bill := range billsMap[order.VendorOrderID] {
|
||||||
if order.Status > model.OrderStatusNew && !isNoNewSent && order.StatusTime.Sub(bill.WaybillCreatedAt) < 0 {
|
if order.Status > model.OrderStatusNew && !isNoNewSent && order.StatusTime.Sub(bill.WaybillCreatedAt) < 0 {
|
||||||
isNoNewSent = true
|
isNoNewSent = true
|
||||||
order2 := *order
|
order2 := *order
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
||||||
}, order.VendorOrderID)
|
}, order.VendorOrderID)
|
||||||
}
|
}
|
||||||
billNew := *bill
|
billNew := *bill
|
||||||
billNew.Status = model.OrderStatusNew
|
billNew.Status = model.OrderStatusNew
|
||||||
billNew.StatusTime = order.OrderCreatedAt
|
billNew.StatusTime = order.OrderCreatedAt
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnWaybillStatusChanged(&billNew)
|
scheduler.CurrentScheduler.OnWaybillStatusChanged(&billNew)
|
||||||
}, bill.VendorOrderID)
|
}, bill.VendorOrderID)
|
||||||
if order.Status > model.OrderStatusNew && !isNoNewSent && order.StatusTime.Sub(bill.StatusTime) < 0 {
|
if order.Status > model.OrderStatusNew && !isNoNewSent && order.StatusTime.Sub(bill.StatusTime) < 0 {
|
||||||
isNoNewSent = true
|
isNoNewSent = true
|
||||||
order2 := *order
|
order2 := *order
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
||||||
}, order.VendorOrderID)
|
}, order.VendorOrderID)
|
||||||
}
|
}
|
||||||
if bill.Status > model.WaybillStatusNew {
|
if bill.Status > model.WaybillStatusNew {
|
||||||
bill2 := *bill
|
bill2 := *bill
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnWaybillStatusChanged(&bill2)
|
scheduler.CurrentScheduler.OnWaybillStatusChanged(&bill2)
|
||||||
}, bill.VendorOrderID)
|
}, bill.VendorOrderID)
|
||||||
}
|
}
|
||||||
if order.Status > model.OrderStatusNew && !isNoNewSent {
|
if order.Status > model.OrderStatusNew && !isNoNewSent {
|
||||||
isNoNewSent = true
|
isNoNewSent = true
|
||||||
order2 := *order
|
order2 := *order
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
||||||
}, order.VendorOrderID)
|
}, order.VendorOrderID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if order.Status > model.OrderStatusNew && !isNoNewSent {
|
if order.Status > model.OrderStatusNew && !isNoNewSent {
|
||||||
order2 := *order
|
order2 := *order
|
||||||
routinePool.CallFunAsync(func() {
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(&order2))
|
||||||
}, order.VendorOrderID)
|
}, order.VendorOrderID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *WaybillController) OnWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaapi.CallbackResponse) {
|
func (c *WaybillController) OnWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onWaybillMsg(msg)
|
retVal = c.onWaybillMsg(msg)
|
||||||
}, msg.OrderID)
|
}, msg.OrderID)
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package elm
|
|||||||
import (
|
import (
|
||||||
"git.rosy.net.cn/baseapi/platformapi/elmapi"
|
"git.rosy.net.cn/baseapi/platformapi/elmapi"
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/jx-callback/business/controller"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
)
|
)
|
||||||
@@ -46,7 +45,7 @@ func (c *Controller) OnCallbackMsg(msg *elmapi.CallbackMsg) (retVal *elmapi.Call
|
|||||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||||
} else {
|
} else {
|
||||||
innerMsg.MsgType = msg.Type
|
innerMsg.MsgType = msg.Type
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = new(OrderController).onOrderUserUrgeOrder(&innerMsg)
|
retVal = new(OrderController).onOrderUserUrgeOrder(&innerMsg)
|
||||||
}, jxutils.ComposeUniversalOrderID(innerMsg.OrderID, model.VendorIDELM))
|
}, jxutils.ComposeUniversalOrderID(innerMsg.OrderID, model.VendorIDELM))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *OrderController) OnOrderStatusMsg(msg *elmapi.CallbackOrderStatusMsg) (retVal *elmapi.CallbackResponse) {
|
func (c *OrderController) OnOrderStatusMsg(msg *elmapi.CallbackOrderStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onOrderStatusMsg(msg)
|
retVal = c.onOrderStatusMsg(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||||
return retVal
|
return retVal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OrderController) OnOrderNewMsg(msg map[string]interface{}) (retVal *elmapi.CallbackResponse) {
|
func (c *OrderController) OnOrderNewMsg(msg map[string]interface{}) (retVal *elmapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onOrderNew(msg)
|
retVal = c.onOrderNew(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg["orderId"].(string), model.VendorIDELM))
|
}, jxutils.ComposeUniversalOrderID(msg["orderId"].(string), model.VendorIDELM))
|
||||||
return retVal
|
return retVal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OrderController) OnOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancelRefundMsg) (retVal *elmapi.CallbackResponse) {
|
func (c *OrderController) OnOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancelRefundMsg) (retVal *elmapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onOrderCancelRefundMsg(msg)
|
retVal = c.onOrderCancelRefundMsg(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type WaybillController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *WaybillController) OnWaybillStatusMsg(msg *elmapi.CallbackWaybillStatusMsg) (retVal *elmapi.CallbackResponse) {
|
func (c *WaybillController) OnWaybillStatusMsg(msg *elmapi.CallbackWaybillStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onWaybillStatusMsg(msg)
|
retVal = c.onWaybillStatusMsg(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *OrderController) OnOrderMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
func (c *OrderController) OnOrderMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onOrderMsg(msg)
|
retVal = c.onOrderMsg(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type WaybillController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *WaybillController) OnWaybillMsg(msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
|
func (c *WaybillController) OnWaybillMsg(msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onWaybillMsg(msg)
|
retVal = c.onWaybillMsg(msg)
|
||||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDJD))
|
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDJD))
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *WaybillController) OnWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *mtpsapi.CallbackResponse) {
|
func (c *WaybillController) OnWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *mtpsapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
retVal = c.onWaybillMsg(msg)
|
retVal = c.onWaybillMsg(msg)
|
||||||
}, msg.OrderID)
|
}, msg.OrderID)
|
||||||
return retVal
|
return retVal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WaybillController) OnWaybillExcept(msg *mtpsapi.CallbackOrderExceptionMsg) (retVal *mtpsapi.CallbackResponse) {
|
func (c *WaybillController) OnWaybillExcept(msg *mtpsapi.CallbackOrderExceptionMsg) (retVal *mtpsapi.CallbackResponse) {
|
||||||
controller.CallMsgHandler(func() {
|
jxutils.CallMsgHandler(func() {
|
||||||
order := &model.Waybill{
|
order := &model.Waybill{
|
||||||
VendorWaybillID: msg.MtPeisongID,
|
VendorWaybillID: msg.MtPeisongID,
|
||||||
VendorWaybillID2: utils.Int64ToStr(msg.DeliveryID),
|
VendorWaybillID2: utils.Int64ToStr(msg.DeliveryID),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"git.rosy.net.cn/baseapi/platformapi/autonavi"
|
"git.rosy.net.cn/baseapi/platformapi/autonavi"
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"git.rosy.net.cn/baseapi/utils/routinepool"
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
"git.rosy.net.cn/jx-callback/globals/api"
|
"git.rosy.net.cn/jx-callback/globals/api"
|
||||||
)
|
)
|
||||||
@@ -18,12 +19,17 @@ const (
|
|||||||
DefaultOrderCacheTimeout = 24 * time.Hour
|
DefaultOrderCacheTimeout = 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
routinePool *routinepool.Pool
|
||||||
|
)
|
||||||
|
|
||||||
type SyncMapWithTimeout struct {
|
type SyncMapWithTimeout struct {
|
||||||
sync.Map
|
sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
|
routinePool = routinepool.New(1000, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SyncMapWithTimeout) StoreWithTimeout(key, value interface{}, timeout time.Duration) {
|
func (m *SyncMapWithTimeout) StoreWithTimeout(key, value interface{}, timeout time.Duration) {
|
||||||
@@ -142,3 +148,15 @@ func StandardPrice2Int(value float64) int64 {
|
|||||||
func IntPrice2StandardString(value int64) string {
|
func IntPrice2StandardString(value int64) string {
|
||||||
return fmt.Sprintf("%.2f", IntPrice2Standard(value))
|
return fmt.Sprintf("%.2f", IntPrice2Standard(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CallMsgHandler(handler func(), primaryID string) {
|
||||||
|
routinePool.CallFun(func() {
|
||||||
|
handler()
|
||||||
|
}, primaryID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallMsgHandlerAsync(handler func(), primaryID string) {
|
||||||
|
routinePool.CallFunAsync(func() {
|
||||||
|
handler()
|
||||||
|
}, primaryID)
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,7 +48,18 @@ func init() {
|
|||||||
Timeout: 1 * time.Second,
|
Timeout: 1 * time.Second,
|
||||||
TimeoutAction: func(order *model.GoodsOrder) (err error) {
|
TimeoutAction: func(order *model.GoodsOrder) (err error) {
|
||||||
_ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, order.ConsigneeMobile, jxutils.GetJxStoreIDFromOrder(order), nil, func(isAcceptIt bool) error {
|
_ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, order.ConsigneeMobile, jxutils.GetJxStoreIDFromOrder(order), nil, func(isAcceptIt bool) error {
|
||||||
return sch.AcceptOrRefuseOrder(order, isAcceptIt)
|
if err = sch.AcceptOrRefuseOrder(order, isAcceptIt); err != nil {
|
||||||
|
// 为了解决京东新消息与接单消息乱序的问题
|
||||||
|
if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 && errWithCode.IntCode() == -1 {
|
||||||
|
if order2, err2 := sch.CurOrderManager.LoadOrder(order.VendorOrderID, order.VendorID); err2 == nil && order2.Status > order.Status {
|
||||||
|
sch.OnOrderStatusChanged(model.Order2Status(order2))
|
||||||
|
err = nil
|
||||||
|
} else {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@@ -75,7 +86,7 @@ func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder) (err error) {
|
|||||||
order: order,
|
order: order,
|
||||||
}
|
}
|
||||||
s.orderMap.Store(jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), watchInfo)
|
s.orderMap.Store(jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), watchInfo)
|
||||||
s.resetTimer(watchInfo, model.OrderStatusNew, order.OrderCreatedAt, 0)
|
s.resetTimer(watchInfo, watchInfo.order.Status, order.OrderCreatedAt, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,9 +312,13 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, status int, be
|
|||||||
timeout := jxutils.GetRealTimeout(beginTime, config.Timeout, minTimeout) + gap
|
timeout := jxutils.GetRealTimeout(beginTime, config.Timeout, minTimeout) + gap
|
||||||
globals.SugarLogger.Debugf("resetTimer timeout:%v, orderID:%s", timeout, savedOrderInfo.order.VendorOrderID)
|
globals.SugarLogger.Debugf("resetTimer timeout:%v, orderID:%s", timeout, savedOrderInfo.order.VendorOrderID)
|
||||||
savedOrderInfo.timerStatus = status
|
savedOrderInfo.timerStatus = status
|
||||||
|
order := savedOrderInfo.order
|
||||||
savedOrderInfo.timer = time.AfterFunc(timeout, func() {
|
savedOrderInfo.timer = time.AfterFunc(timeout, func() {
|
||||||
config.TimeoutAction(savedOrderInfo.order)
|
// order 事件序列化
|
||||||
savedOrderInfo.timerStatus = 0 // todo 可能有线程安全问题,考虑加入订单队列
|
jxutils.CallMsgHandlerAsync(func() {
|
||||||
|
config.TimeoutAction(order)
|
||||||
|
savedOrderInfo.timerStatus = 0
|
||||||
|
}, order.VendorOrderID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user