- make defsch.time2Schedule3rdCarrier configable.
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
||||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch" // 导入缺省订单调度器
|
|
||||||
"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"
|
||||||
"git.rosy.net.cn/jx-callback/business/partner"
|
"git.rosy.net.cn/jx-callback/business/partner"
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/basesch"
|
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/basesch"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxutils/configindb"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg"
|
"git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg"
|
||||||
"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"
|
||||||
@@ -22,7 +24,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。
|
time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。
|
||||||
time2Schedule3rdCarrier = 20 * time.Minute // 京东要求5分钟后才能转自送,保险起见,设置为5分半钟
|
time2Schedule3rdCarrier = 20 // 京东要求5分钟后才能转自送,保险起见,设置为5分半钟
|
||||||
// time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟,但为了防止没有运单事件,所以就拣货完成事件开始算,添加3分钟
|
// time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟,但为了防止没有运单事件,所以就拣货完成事件开始算,添加3分钟
|
||||||
time2AutoPickupMin = 15 * time.Minute
|
time2AutoPickupMin = 15 * time.Minute
|
||||||
time2AutoPickupGap = 5 * 60 //随机5分钟
|
time2AutoPickupGap = 5 * 60 //随机5分钟
|
||||||
@@ -35,6 +37,8 @@ const (
|
|||||||
maxWaybillRetryCount = 3
|
maxWaybillRetryCount = 3
|
||||||
|
|
||||||
orderMapStoreMaxTime = 4 * 24 * time.Hour // cache最长存储时间
|
orderMapStoreMaxTime = 4 * 24 * time.Hour // cache最长存储时间
|
||||||
|
|
||||||
|
time2Schedule3rdCarrierKey = "waitminute4mt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -73,6 +77,7 @@ type StatusActionConfig struct {
|
|||||||
// 重要:此调度器要求同一定单的处理逻辑必须是序列化了的,不然会有并发问题
|
// 重要:此调度器要求同一定单的处理逻辑必须是序列化了的,不然会有并发问题
|
||||||
type DefScheduler struct {
|
type DefScheduler struct {
|
||||||
basesch.BaseScheduler
|
basesch.BaseScheduler
|
||||||
|
locker sync.RWMutex
|
||||||
defWorkflowConfig []map[int]*StatusActionConfig
|
defWorkflowConfig []map[int]*StatusActionConfig
|
||||||
orderMap jxutils.SyncMapWithTimeout
|
orderMap jxutils.SyncMapWithTimeout
|
||||||
}
|
}
|
||||||
@@ -237,7 +242,7 @@ func init() {
|
|||||||
map[int]*StatusActionConfig{
|
map[int]*StatusActionConfig{
|
||||||
model.WaybillStatusNew: &StatusActionConfig{
|
model.WaybillStatusNew: &StatusActionConfig{
|
||||||
TimerType: scheduler.TimerTypeBaseStatusTime,
|
TimerType: scheduler.TimerTypeBaseStatusTime,
|
||||||
Timeout: time2Schedule3rdCarrier,
|
Timeout: time2Schedule3rdCarrier * time.Minute,
|
||||||
TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) {
|
TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) {
|
||||||
if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore { // 非自配置商家使用
|
if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore { // 非自配置商家使用
|
||||||
return sch.createWaybillOn3rdProviders(savedOrderInfo, nil)
|
return sch.createWaybillOn3rdProviders(savedOrderInfo, nil)
|
||||||
@@ -249,6 +254,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
configindb.WatchConfigChange(time2Schedule3rdCarrierKey, OnDefSchConfChanged)
|
||||||
|
if configTime, err := configindb.GetConfig(time2Schedule3rdCarrierKey, utils.Int2Str(time2Schedule3rdCarrier)); err == nil {
|
||||||
|
OnDefSchConfChanged(time2Schedule3rdCarrierKey, configTime)
|
||||||
|
} else {
|
||||||
|
globals.SugarLogger.Errorf("defsch Init, error:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 以下是订单
|
// 以下是订单
|
||||||
func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder, isPending bool) (err error) {
|
func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder, isPending bool) (err error) {
|
||||||
globals.SugarLogger.Debugf("OnOrderNew orderID:%s", order.VendorOrderID)
|
globals.SugarLogger.Debugf("OnOrderNew orderID:%s", order.VendorOrderID)
|
||||||
@@ -752,6 +766,10 @@ func (s *DefScheduler) handleAutoAcceptOrder(orderID string, vendorID int, userM
|
|||||||
|
|
||||||
func (s *DefScheduler) mergeOrderStatusConfig(statusType, status int, purchaseVendorID int) (retVal *StatusActionConfig) {
|
func (s *DefScheduler) mergeOrderStatusConfig(statusType, status int, purchaseVendorID int) (retVal *StatusActionConfig) {
|
||||||
vendorTimeout := partner.GetPurchasePlatformFromVendorID(purchaseVendorID).GetStatusActionTimeout(statusType, status)
|
vendorTimeout := partner.GetPurchasePlatformFromVendorID(purchaseVendorID).GetStatusActionTimeout(statusType, status)
|
||||||
|
s.locker.RLock()
|
||||||
|
defer func() {
|
||||||
|
s.locker.RUnlock()
|
||||||
|
}()
|
||||||
defConfig := s.defWorkflowConfig[statusType][status]
|
defConfig := s.defWorkflowConfig[statusType][status]
|
||||||
if defConfig == nil {
|
if defConfig == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -809,3 +827,18 @@ func (s *DefScheduler) ProxyCancelWaybill(order *model.GoodsOrder, bill *model.W
|
|||||||
globals.SugarLogger.Debugf("ProxyCancelWaybill orderID:%s stop schedule, bypass CancelWaybill", order.VendorOrderID)
|
globals.SugarLogger.Debugf("ProxyCancelWaybill orderID:%s stop schedule, bypass CancelWaybill", order.VendorOrderID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OnDefSchConfChanged(key, value string) {
|
||||||
|
if key == time2Schedule3rdCarrierKey {
|
||||||
|
waitMinutes := int(utils.Str2Int64WithDefault(value, time2Schedule3rdCarrier))
|
||||||
|
if waitMinutes >= 0 {
|
||||||
|
FixedScheduler.locker.Lock()
|
||||||
|
defer func() {
|
||||||
|
FixedScheduler.locker.Unlock()
|
||||||
|
}()
|
||||||
|
conf := FixedScheduler.defWorkflowConfig[1][model.WaybillStatusNew]
|
||||||
|
conf.Timeout = time.Duration(waitMinutes) * time.Minute
|
||||||
|
globals.SugarLogger.Debugf("defsch wait miniutes 4 3rd delivery changed to:%d", waitMinutes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
82
business/jxutils/configindb/configindb.go
Normal file
82
business/jxutils/configindb/configindb.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package configindb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigNotifier func(key, value string)
|
||||||
|
|
||||||
|
var (
|
||||||
|
legalUsers = map[string]int{
|
||||||
|
"zhaominfu": 1,
|
||||||
|
"shifeng@2018": 1,
|
||||||
|
"zhouyang_2018": 1,
|
||||||
|
"xujianhua": 1,
|
||||||
|
}
|
||||||
|
configNotifierMap = sync.Map{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListConfig(key string) (configList []*legacymodel.Config, err error) {
|
||||||
|
sql := `
|
||||||
|
SELECT *
|
||||||
|
FROM config
|
||||||
|
`
|
||||||
|
sqlParams := []interface{}{}
|
||||||
|
if key != "" {
|
||||||
|
sql += " WHERE thirdparty = ?"
|
||||||
|
sqlParams = append(sqlParams, key)
|
||||||
|
}
|
||||||
|
db := dao.GetDB()
|
||||||
|
if err = dao.GetRows(db, &configList, sql, sqlParams...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return configList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig(key, defValue string) (value string, err error) {
|
||||||
|
configList, err := ListConfig(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(configList) == 0 {
|
||||||
|
return defValue, nil
|
||||||
|
}
|
||||||
|
return configList[0].Token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetConfig(ctx *jxcontext.Context, key, value string) (num int64, err error) {
|
||||||
|
userName := ctx.GetUserName()
|
||||||
|
if legalUsers[userName] != 1 {
|
||||||
|
return 0, fmt.Errorf("%s不具有此功能操作权限", userName)
|
||||||
|
}
|
||||||
|
sql := `
|
||||||
|
UPDATE config
|
||||||
|
SET token = ?,
|
||||||
|
date = NOW(),
|
||||||
|
last_operator = ?
|
||||||
|
WHERE thirdparty = ?
|
||||||
|
`
|
||||||
|
db := dao.GetDB()
|
||||||
|
num, err = dao.ExecuteSQL(db, sql, value, userName, key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if num == 0 {
|
||||||
|
return 0, fmt.Errorf("没有%s这个配置项", key)
|
||||||
|
}
|
||||||
|
if v, ok := configNotifierMap.Load(key); ok {
|
||||||
|
if notifier, ok := v.(ConfigNotifier); ok {
|
||||||
|
notifier(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WatchConfigChange(key string, configNotifier ConfigNotifier) {
|
||||||
|
configNotifierMap.Store(key, configNotifier)
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@ package legacymodel
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Id int
|
Id int
|
||||||
Thirdparty string `orm:"size(20);unique"`
|
Thirdparty string `orm:"size(20);unique" json:"key"`
|
||||||
Token string `orm:"size(300)"`
|
Token string `orm:"size(300)" json:"value"`
|
||||||
Date string `orm:"size(30)"`
|
Date string `orm:"size(30)" json:"date"`
|
||||||
|
LastOperator string `orm:"size(32)" json:"lastOperator"` // 最后操作员
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxutils/configindb"
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -103,3 +104,32 @@ func (c *CmsController) GetCoordinateDistrictCode() {
|
|||||||
return retVal, "", err
|
return retVal, "", err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Title 得到配置参数
|
||||||
|
// @Description 得到配置参数
|
||||||
|
// @Param token header string true "认证token"
|
||||||
|
// @Param key query string true "参数名"
|
||||||
|
// @Success 200 {object} controllers.CallResult
|
||||||
|
// @Failure 200 {object} controllers.CallResult
|
||||||
|
// @router /GetConfig [get]
|
||||||
|
func (c *CmsController) GetConfig() {
|
||||||
|
c.callGetConfig(func(params *tCmsGetConfigParams) (retVal interface{}, errCode string, err error) {
|
||||||
|
retVal, err = configindb.GetConfig(params.Key, "")
|
||||||
|
return retVal, "", err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title 设置配置参数
|
||||||
|
// @Description 设置配置参数
|
||||||
|
// @Param token header string true "认证token"
|
||||||
|
// @Param key query string true "参数名"
|
||||||
|
// @Param value query string true "参数值"
|
||||||
|
// @Success 200 {object} controllers.CallResult
|
||||||
|
// @Failure 200 {object} controllers.CallResult
|
||||||
|
// @router /SetConfig [put]
|
||||||
|
func (c *CmsController) SetConfig() {
|
||||||
|
c.callSetConfig(func(params *tCmsSetConfigParams) (retVal interface{}, errCode string, err error) {
|
||||||
|
retVal, err = configindb.SetConfig(params.Ctx, params.Key, params.Value)
|
||||||
|
return retVal, "", err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch" // 导入缺省订单调度器
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/promotion"
|
"git.rosy.net.cn/jx-callback/business/jxstore/promotion"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasks"
|
"git.rosy.net.cn/jx-callback/business/jxutils/tasks"
|
||||||
@@ -28,6 +29,7 @@ var (
|
|||||||
func Init() {
|
func Init() {
|
||||||
// globals.Init()
|
// globals.Init()
|
||||||
beegodb.Init()
|
beegodb.Init()
|
||||||
|
defsch.Init()
|
||||||
api.Init()
|
api.Init()
|
||||||
cms.InitServiceInfo(Version, BuildDate, GitCommit)
|
cms.InitServiceInfo(Version, BuildDate, GitCommit)
|
||||||
if globals.EnableStore {
|
if globals.EnableStore {
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ func init() {
|
|||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "GetConfig",
|
||||||
|
Router: `/GetConfig`,
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "GetCoordinateDistrictCode",
|
Method: "GetCoordinateDistrictCode",
|
||||||
@@ -87,6 +95,14 @@ func init() {
|
|||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "SetConfig",
|
||||||
|
Router: `/SetConfig`,
|
||||||
|
AllowHTTPMethods: []string{"put"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "UpdatePlace",
|
Method: "UpdatePlace",
|
||||||
|
|||||||
Reference in New Issue
Block a user