修复发货提交卡死恢复
This commit is contained in:
@@ -34,6 +34,8 @@ const (
|
||||
deliveryStageCreateQueue = "create_queue" // 创建上游 queue 失败
|
||||
deliveryStagePatchQueue = "patch_queue" // 补充 queue 账号信息失败
|
||||
deliveryStageCreateOrder = "create_upstream" // 创建上游正式订单失败
|
||||
|
||||
deliverySubmissionStaleTimeout = 10 * time.Minute
|
||||
)
|
||||
|
||||
// deliverySubmittedUpstream 判断订单是否已成功提交到上游正式订单。
|
||||
@@ -315,16 +317,10 @@ func (s *DeliveryService) submit(orderNo, gameAccount, bindUUID string, apiClien
|
||||
s.markDeliverySubmissionFailed(claimed, apiClientID, deliveryStageCreateQueue, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
// 建 queue 后立即持久化,缩小崩溃窗口:即使后续崩溃,也能识别到已建 queue 的阶段。
|
||||
if _, err := s.fulfillment.UpdateFulfillment(FulfillmentUpdateInput{
|
||||
MerchantID: order.MerchantID,
|
||||
APIClientID: apiClientID,
|
||||
OrderNo: order.OrderNo,
|
||||
Status: model.OrderStatusDelivering,
|
||||
ResultData: mergeResultData(claimed.ResultData, map[string]interface{}{
|
||||
"provider_order_stage": deliveryStageQueueCreated,
|
||||
"queue_order_id": queueOrderID,
|
||||
}),
|
||||
// 建 queue 后只持久化阶段信息,不提前改成 delivering。
|
||||
// 上游创建正式订单前会回查开放接口,此时订单必须仍然 can_ship=true。
|
||||
if err := s.recordDeliverySubmissionStage(claimed, deliveryStageQueueCreated, map[string]interface{}{
|
||||
"queue_order_id": queueOrderID,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -401,14 +397,19 @@ func (s *DeliveryService) claimDeliverySubmission(merchantID, apiClientID uint,
|
||||
if err := validateOrderStatusTransition(&order, model.OrderStatusDelivering, fulfillmentTransitionUpdate); err != nil {
|
||||
return newDeliveryHTTPError(http.StatusConflict, "订单暂不可发货")
|
||||
}
|
||||
now := time.Now()
|
||||
stage := resultDataString(order.ResultData, "provider_order_stage")
|
||||
if deliverySubmissionInProgress(stage) && !deliverySubmissionStale(&order, now) {
|
||||
updated = order
|
||||
return nil
|
||||
}
|
||||
patch := map[string]interface{}{
|
||||
"source": "delivery_proxy",
|
||||
"submit_started_at": timeutil.FormatAPITime(time.Now()),
|
||||
"submit_started_at": timeutil.FormatAPITime(now),
|
||||
"provider_order_stage": deliveryStageClaimed,
|
||||
"ship_attempts": resultDataNumber(order.ResultData, "ship_attempts") + 1,
|
||||
}
|
||||
if err := tx.Model(&order).Updates(map[string]interface{}{
|
||||
"order_status": model.OrderStatusDelivering,
|
||||
"result_data": mergeResultData(order.ResultData, patch),
|
||||
"failure_reason": "",
|
||||
}).Error; err != nil {
|
||||
@@ -422,11 +423,6 @@ func (s *DeliveryService) claimDeliverySubmission(merchantID, apiClientID uint,
|
||||
if err := writeAudit(tx, &merchantID, nil, apiClientIDPtr, "delivery.submit.claim", "fulfillment_order", order.OrderNo, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if s.fulfillment.callbacks != nil {
|
||||
if err := s.fulfillment.callbacks.Enqueue(tx, merchantID, "order.shipping.updated", orderCallbackData(&updated)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -435,6 +431,24 @@ func (s *DeliveryService) claimDeliverySubmission(merchantID, apiClientID uint,
|
||||
return &updated, claimedNow, nil
|
||||
}
|
||||
|
||||
func (s *DeliveryService) recordDeliverySubmissionStage(order *model.FulfillmentOrder, stage string, patch map[string]interface{}) error {
|
||||
if order == nil {
|
||||
return errors.New("订单不存在")
|
||||
}
|
||||
if patch == nil {
|
||||
patch = map[string]interface{}{}
|
||||
}
|
||||
patch["provider_order_stage"] = stage
|
||||
resultData := mergeResultData(order.ResultData, patch)
|
||||
if err := s.fulfillment.db.Model(&model.FulfillmentOrder{}).
|
||||
Where("id = ?", order.ID).
|
||||
Update("result_data", resultData).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
order.ResultData = resultData
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *DeliveryService) markDeliverySubmissionFailed(order *model.FulfillmentOrder, apiClientID uint, stage, reason string) {
|
||||
if order == nil {
|
||||
return
|
||||
@@ -585,6 +599,23 @@ func upstreamDeliverySucceeded(order map[string]interface{}) bool {
|
||||
strings.EqualFold(stringFromMap(order, "send_status"), "SUCCESS")
|
||||
}
|
||||
|
||||
func deliverySubmissionInProgress(stage string) bool {
|
||||
return stage == deliveryStageClaimed || stage == deliveryStageQueueCreated
|
||||
}
|
||||
|
||||
func deliverySubmissionStale(order *model.FulfillmentOrder, now time.Time) bool {
|
||||
if order == nil {
|
||||
return false
|
||||
}
|
||||
startedAtRaw := resultDataString(order.ResultData, "submit_started_at")
|
||||
if startedAtRaw != "" {
|
||||
if startedAt, err := time.Parse(timeutil.APITimeLayout, startedAtRaw); err == nil {
|
||||
return now.Sub(startedAt) >= deliverySubmissionStaleTimeout
|
||||
}
|
||||
}
|
||||
return !order.UpdatedAt.IsZero() && now.Sub(order.UpdatedAt) >= deliverySubmissionStaleTimeout
|
||||
}
|
||||
|
||||
func optionalUint(value uint) *uint {
|
||||
if value == 0 {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user