diff --git a/business/jxcallback/orderman/orderman.go b/business/jxcallback/orderman/orderman.go index c6d902311..698b792c0 100644 --- a/business/jxcallback/orderman/orderman.go +++ b/business/jxcallback/orderman/orderman.go @@ -7,7 +7,6 @@ import ( "git.rosy.net.cn/baseapi/utils" "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/model" "git.rosy.net.cn/jx-callback/business/partner" diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index 6d6ebcde3..73e64cd94 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -4,12 +4,14 @@ import ( "errors" "fmt" "math/rand" + "sync" "time" "git.rosy.net.cn/baseapi/utils" "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/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/model" "git.rosy.net.cn/jx-callback/business/model/dao" @@ -21,8 +23,8 @@ import ( ) const ( - time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。 - time2Schedule3rdCarrier = 20 * time.Minute // 京东要求5分钟后才能转自送,保险起见,设置为5分半钟 + time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。 + time2Schedule3rdCarrier = 20 // 京东要求5分钟后才能转自送,保险起见,设置为5分半钟 // time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟,但为了防止没有运单事件,所以就拣货完成事件开始算,添加3分钟 time2AutoPickupMin = 15 * time.Minute time2AutoPickupGap = 5 * 60 //随机5分钟 @@ -35,6 +37,8 @@ const ( maxWaybillRetryCount = 3 orderMapStoreMaxTime = 4 * 24 * time.Hour // cache最长存储时间 + + time2Schedule3rdCarrierKey = "waitminute4mt" ) const ( @@ -73,6 +77,7 @@ type StatusActionConfig struct { // 重要:此调度器要求同一定单的处理逻辑必须是序列化了的,不然会有并发问题 type DefScheduler struct { basesch.BaseScheduler + locker sync.RWMutex defWorkflowConfig []map[int]*StatusActionConfig orderMap jxutils.SyncMapWithTimeout } @@ -237,7 +242,7 @@ func init() { map[int]*StatusActionConfig{ model.WaybillStatusNew: &StatusActionConfig{ TimerType: scheduler.TimerTypeBaseStatusTime, - Timeout: time2Schedule3rdCarrier, + Timeout: time2Schedule3rdCarrier * time.Minute, TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) { if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore { // 非自配置商家使用 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) { 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) { vendorTimeout := partner.GetPurchasePlatformFromVendorID(purchaseVendorID).GetStatusActionTimeout(statusType, status) + s.locker.RLock() + defer func() { + s.locker.RUnlock() + }() defConfig := s.defWorkflowConfig[statusType][status] if defConfig == 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) 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) + } + } +} diff --git a/business/jxutils/configindb/configindb.go b/business/jxutils/configindb/configindb.go new file mode 100644 index 000000000..34243cd65 --- /dev/null +++ b/business/jxutils/configindb/configindb.go @@ -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) +} diff --git a/business/model/legacymodel/config.go b/business/model/legacymodel/config.go index 8137ac40d..b0ab1ef26 100644 --- a/business/model/legacymodel/config.go +++ b/business/model/legacymodel/config.go @@ -1,8 +1,9 @@ package legacymodel type Config struct { - Id int - Thirdparty string `orm:"size(20);unique"` - Token string `orm:"size(300)"` - Date string `orm:"size(30)"` + Id int + Thirdparty string `orm:"size(20);unique" json:"key"` + Token string `orm:"size(300)" json:"value"` + Date string `orm:"size(30)" json:"date"` + LastOperator string `orm:"size(32)" json:"lastOperator"` // 最后操作员 } diff --git a/controllers/cms.go b/controllers/cms.go index 8a831009f..328750b5d 100644 --- a/controllers/cms.go +++ b/controllers/cms.go @@ -3,6 +3,7 @@ package controllers import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/jx-callback/business/jxutils/configindb" "github.com/astaxie/beego" ) @@ -103,3 +104,32 @@ func (c *CmsController) GetCoordinateDistrictCode() { 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 + }) +} diff --git a/main.go b/main.go index 1ee6089d8..96a1f5555 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "os" "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/promotion" "git.rosy.net.cn/jx-callback/business/jxutils/tasks" @@ -28,6 +29,7 @@ var ( func Init() { // globals.Init() beegodb.Init() + defsch.Init() api.Init() cms.InitServiceInfo(Version, BuildDate, GitCommit) if globals.EnableStore { diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index ed0c76bb8..877729dcf 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -55,6 +55,14 @@ func init() { 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.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.ControllerComments{ Method: "GetCoordinateDistrictCode", @@ -87,6 +95,14 @@ func init() { 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.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.ControllerComments{ Method: "UpdatePlace",