Authored by mali

Merge branch 'master' into test6.9.10

@@ -89,9 +89,10 @@ public interface StorageDepositMapper { @@ -89,9 +89,10 @@ public interface StorageDepositMapper {
89 int updateDelStatusByCode(@Param("uid")Integer uid, @Param("depositCode")String depositCode, @Param("status")Integer status); 89 int updateDelStatusByCode(@Param("uid")Integer uid, @Param("depositCode")String depositCode, @Param("status")Integer status);
90 90
91 91
92 - int updateStorageLockFlagByCAS(@Param("uid")int uid,  
93 - @Param("depositCode")String depositCode, 92 + int updateStorageLockFlagByCAS(@Param("id")int id,
94 @Param("status")int status, 93 @Param("status")int status,
95 @Param("expectStatus")int expectStatus 94 @Param("expectStatus")int expectStatus
96 ); 95 );
  96 +
  97 + int removeStorageLockFlag(int id);
97 } 98 }
@@ -420,10 +420,16 @@ @@ -420,10 +420,16 @@
420 <update id="updateStorageLockFlagByCAS"> 420 <update id="updateStorageLockFlagByCAS">
421 update storage_deposit 421 update storage_deposit
422 set lock_flag = #{status,jdbcType=INTEGER} ,update_time = unix_timestamp(now()) 422 set lock_flag = #{status,jdbcType=INTEGER} ,update_time = unix_timestamp(now())
423 - where owner_uid = #{uid,jdbcType=INTEGER}  
424 - and deposit_code = #{depositCode,jdbcType=VARCHAR} 423 + where id = #{id,jdbcType=INTEGER}
425 AND lock_flag = #{expectStatus,jdbcType=INTEGER} 424 AND lock_flag = #{expectStatus,jdbcType=INTEGER}
426 and order_status = #{expectStatus,jdbcType=INTEGER} 425 and order_status = #{expectStatus,jdbcType=INTEGER}
  426 + AND del_status = 0
427 </update> 427 </update>
428 428
  429 + <update id="removeStorageLockFlag" parameterType="java.lang.Integer">
  430 + update storage_deposit
  431 + set lock_flag = 0 ,update_time = unix_timestamp(now())
  432 + where id = #{id,jdbcType=INTEGER}
  433 + AND lock_flag = 1
  434 + </update>
429 </mapper> 435 </mapper>
1 package com.yohoufo.order.model; 1 package com.yohoufo.order.model;
2 2
3 import com.yohobuy.ufo.model.order.vo.AddressInfo; 3 import com.yohobuy.ufo.model.order.vo.AddressInfo;
  4 +import com.yohoufo.dal.order.model.StorageDeposit;
4 import lombok.Data; 5 import lombok.Data;
5 6
6 import java.util.List; 7 import java.util.List;
@@ -10,9 +11,11 @@ import java.util.Map; @@ -10,9 +11,11 @@ import java.util.Map;
10 public class QuickDeliverOrderContext extends SellerOrderContext { 11 public class QuickDeliverOrderContext extends SellerOrderContext {
11 12
12 13
13 - private List<String> depositCodes;  
14 14
15 15
16 private Map<String, AddressInfo> hiddenBackAddressMap; 16 private Map<String, AddressInfo> hiddenBackAddressMap;
17 private Map<String, AddressInfo> noHiddenBackAddressMap; 17 private Map<String, AddressInfo> noHiddenBackAddressMap;
  18 +
  19 + //
  20 + private Map<String, StorageDeposit> depositCodeSDMap;
18 } 21 }
  1 +package com.yohoufo.order.service.deposit;
  2 +
  3 +import com.yohoufo.dal.order.StorageDepositMapper;
  4 +import com.yohoufo.order.utils.LoggerUtils;
  5 +import org.slf4j.Logger;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +@Component
  10 +public class StorageDepositSupport {
  11 +
  12 + private final Logger LOGGER = LoggerUtils.getSellerOrderLogger();
  13 +
  14 + @Autowired
  15 + private StorageDepositMapper storageDepositMapper;
  16 +
  17 + private class DepositLock{
  18 + private int sellerUid;
  19 + private String depositCode;
  20 + private int unlockStatus = 0, lockStatus = 1;
  21 + DepositLock(int sellerUid, String depositCode){
  22 + this.sellerUid = sellerUid;
  23 + this.depositCode = depositCode;
  24 + }
  25 +
  26 + boolean lock(int id){
  27 + int rows = storageDepositMapper.updateStorageLockFlagByCAS(id, lockStatus, unlockStatus);
  28 + LOGGER.info("in DepositLock.lock id {} sellerUid {} depositCode {} rows {}", id, sellerUid, depositCode, rows);
  29 + return rows > 0;
  30 + }
  31 +
  32 + boolean unlock(int id){
  33 + int rows = storageDepositMapper.removeStorageLockFlag(id);
  34 + LOGGER.info("in DepositLock.unlock id {} sellerUid {} depositCode {} rows {}", id, sellerUid, depositCode, rows);
  35 + return rows > 0;
  36 + }
  37 + }
  38 +
  39 + public boolean lock(int uid, String depositCode, int id){
  40 + return new DepositLock(uid, depositCode).lock(id);
  41 + }
  42 +
  43 +
  44 + public boolean unlock(int uid, String depositCode, int depositId){
  45 + //unlock
  46 + return new DepositLock(uid, depositCode).unlock(depositId);
  47 + }
  48 +}
@@ -30,11 +30,8 @@ import com.yohoufo.order.model.response.AppraiseAddressResp; @@ -30,11 +30,8 @@ import com.yohoufo.order.model.response.AppraiseAddressResp;
30 import com.yohoufo.order.service.DepositService; 30 import com.yohoufo.order.service.DepositService;
31 import com.yohoufo.order.service.proxy.InBoxFacade; 31 import com.yohoufo.order.service.proxy.InBoxFacade;
32 import com.yohoufo.order.service.proxy.ProductProxyService; 32 import com.yohoufo.order.service.proxy.ProductProxyService;
33 -import com.yohoufo.order.service.proxy.SellerNoticeFacade;  
34 import com.yohoufo.order.service.seller.SkupService; 33 import com.yohoufo.order.service.seller.SkupService;
35 import com.yohoufo.order.utils.LoggerUtils; 34 import com.yohoufo.order.utils.LoggerUtils;
36 -import lombok.AllArgsConstructor;  
37 -import lombok.Data;  
38 import org.apache.commons.collections.CollectionUtils; 35 import org.apache.commons.collections.CollectionUtils;
39 import org.slf4j.Logger; 36 import org.slf4j.Logger;
40 import org.springframework.beans.factory.annotation.Autowired; 37 import org.springframework.beans.factory.annotation.Autowired;
@@ -78,8 +75,6 @@ public class DepositServiceImpl implements DepositService { @@ -78,8 +75,6 @@ public class DepositServiceImpl implements DepositService {
78 75
79 @Autowired 76 @Autowired
80 private SkupService skupService; 77 private SkupService skupService;
81 - @Autowired  
82 - private SellerNoticeFacade sellerNoticeFacade;  
83 78
84 @Autowired 79 @Autowired
85 private InBoxFacade inBoxFacade; 80 private InBoxFacade inBoxFacade;
@@ -265,8 +260,6 @@ public class DepositServiceImpl implements DepositService { @@ -265,8 +260,6 @@ public class DepositServiceImpl implements DepositService {
265 boolean result = storageDepositMapper.changeSaleStatusOn(uid, depositCode, skup) == 1; 260 boolean result = storageDepositMapper.changeSaleStatusOn(uid, depositCode, skup) == 1;
266 if (result) { 261 if (result) {
267 cleanCacheWhenOnShelve(uid, depositCode); 262 cleanCacheWhenOnShelve(uid, depositCode);
268 - //unlock  
269 - new DepositLock(uid, depositCode).unlock();  
270 } 263 }
271 return result; 264 return result;
272 } 265 }
@@ -309,27 +302,7 @@ public class DepositServiceImpl implements DepositService { @@ -309,27 +302,7 @@ public class DepositServiceImpl implements DepositService {
309 return null; 302 return null;
310 } 303 }
311 304
312 - private class DepositLock{  
313 - private int sellerUid;  
314 - private String depositCode;  
315 - private int unlockStatus = 0, lockStatus = 1;  
316 - DepositLock(int sellerUid, String depositCode){  
317 - this.sellerUid = sellerUid;  
318 - this.depositCode = depositCode;  
319 - }  
320 -  
321 - boolean lock(){  
322 - int rows = storageDepositMapper.updateStorageLockFlagByCAS(sellerUid, depositCode, lockStatus, unlockStatus);  
323 - LOGGER.info("in DepositLock.lock sellerUid {} depositCode {} rows {}", sellerUid, depositCode, rows);  
324 - return rows > 0;  
325 - }  
326 305
327 - boolean unlock(){  
328 - int rows = storageDepositMapper.updateStorageLockFlagByCAS(sellerUid, depositCode, unlockStatus, lockStatus);  
329 - LOGGER.info("in DepositLock.unlock sellerUid {} depositCode {} rows {}", sellerUid, depositCode, rows);  
330 - return rows > 0;  
331 - }  
332 - }  
333 /** 306 /**
334 * 批量上架-查询 307 * 批量上架-查询
335 * 应当锁定相关记录,加中间状态 308 * 应当锁定相关记录,加中间状态
@@ -343,26 +316,8 @@ public class DepositServiceImpl implements DepositService { @@ -343,26 +316,8 @@ public class DepositServiceImpl implements DepositService {
343 if (CollectionUtils.isEmpty(sdList)){ 316 if (CollectionUtils.isEmpty(sdList)){
344 LOGGER.warn("in getStorageDeposit4Publish StorageDeposit empty, uid {} storageId {} num {}", 317 LOGGER.warn("in getStorageDeposit4Publish StorageDeposit empty, uid {} storageId {} num {}",
345 uid, storageId, num); 318 uid, storageId, num);
346 - return sdList;  
347 - }  
348 - List<StorageDeposit> lockedList = new ArrayList<>(sdList.size());  
349 - for (StorageDeposit sd : sdList) {  
350 - DepositLock lock = new DepositLock(uid, sd.getDepositCode());  
351 - try{  
352 - if (lock.lock()) {  
353 - lockedList.add(sd);  
354 - } else {  
355 - LOGGER.warn("getStorageDeposit4Publish updateStorageShelveStatusByCAS fail ,{}", sd);  
356 - }  
357 - }catch (Exception ex){  
358 - //release lock, give a second chance 2 survivor  
359 - lock.unlock();  
360 - LOGGER.warn("getStorageDeposit4Publish updateStorageShelveStatusByCAS occur exception {} - {}",  
361 - sd, Throwables.getStackTraceAsString(ex));  
362 - continue;  
363 - }  
364 } 319 }
365 - return lockedList; 320 + return sdList;
366 } 321 }
367 322
368 // 批量下架 323 // 批量下架
@@ -16,16 +16,18 @@ import com.yohobuy.ufo.model.order.resp.PageResp; @@ -16,16 +16,18 @@ import com.yohobuy.ufo.model.order.resp.PageResp;
16 import com.yohobuy.ufo.model.order.resp.SellerGoodsPageResp; 16 import com.yohobuy.ufo.model.order.resp.SellerGoodsPageResp;
17 import com.yohoufo.common.alarm.EventBusPublisher; 17 import com.yohoufo.common.alarm.EventBusPublisher;
18 import com.yohoufo.common.alarm.SmsAlarmEvent; 18 import com.yohoufo.common.alarm.SmsAlarmEvent;
  19 +import com.yohoufo.common.exception.UfoServiceException;
19 import com.yohoufo.common.lock.RedisLock; 20 import com.yohoufo.common.lock.RedisLock;
20 import com.yohoufo.common.lock.RedisLockFactory; 21 import com.yohoufo.common.lock.RedisLockFactory;
21 -import com.yohoufo.common.exception.UfoServiceException;  
22 import com.yohoufo.dal.order.SellerOrderGoodsViewMapper; 22 import com.yohoufo.dal.order.SellerOrderGoodsViewMapper;
23 import com.yohoufo.dal.order.model.SellerOrderGoods; 23 import com.yohoufo.dal.order.model.SellerOrderGoods;
  24 +import com.yohoufo.dal.order.model.StorageDeposit;
24 import com.yohoufo.order.model.QuickDeliverOrderContext; 25 import com.yohoufo.order.model.QuickDeliverOrderContext;
25 import com.yohoufo.order.model.request.OrderListRequest; 26 import com.yohoufo.order.model.request.OrderListRequest;
26 import com.yohoufo.order.model.request.SellerGoodsListRequest; 27 import com.yohoufo.order.model.request.SellerGoodsListRequest;
27 import com.yohoufo.order.model.response.DepositPublishResp; 28 import com.yohoufo.order.model.response.DepositPublishResp;
28 import com.yohoufo.order.service.DepositService; 29 import com.yohoufo.order.service.DepositService;
  30 +import com.yohoufo.order.service.deposit.StorageDepositSupport;
29 import com.yohoufo.order.service.handler.SellerOrderSubmitHandler; 31 import com.yohoufo.order.service.handler.SellerOrderSubmitHandler;
30 import com.yohoufo.order.service.impl.SkupListService; 32 import com.yohoufo.order.service.impl.SkupListService;
31 import com.yohoufo.order.service.proxy.ProductProxyService; 33 import com.yohoufo.order.service.proxy.ProductProxyService;
@@ -41,7 +43,7 @@ import org.springframework.stereotype.Service; @@ -41,7 +43,7 @@ import org.springframework.stereotype.Service;
41 import java.math.BigDecimal; 43 import java.math.BigDecimal;
42 import java.util.Arrays; 44 import java.util.Arrays;
43 import java.util.List; 45 import java.util.List;
44 -import java.util.UUID; 46 +import java.util.Map;
45 import java.util.concurrent.TimeUnit; 47 import java.util.concurrent.TimeUnit;
46 48
47 /** 49 /**
@@ -85,6 +87,9 @@ public class QuickDeliverGoodsService { @@ -85,6 +87,9 @@ public class QuickDeliverGoodsService {
85 @Autowired 87 @Autowired
86 private RedisLockFactory redisLockFactory; 88 private RedisLockFactory redisLockFactory;
87 89
  90 + @Autowired
  91 + private StorageDepositSupport storageDepositSupport;
  92 +
88 public DepositPublishResp publish(QuickDeliverOrderSubmitReq req) { 93 public DepositPublishResp publish(QuickDeliverOrderSubmitReq req) {
89 RedisKeyBuilder redisLockKey = RedisKeyBuilder.newInstance() 94 RedisKeyBuilder redisLockKey = RedisKeyBuilder.newInstance()
90 .appendFixed("ufo:order:lock:publishQuickDeliverGoods:") 95 .appendFixed("ufo:order:lock:publishQuickDeliverGoods:")
@@ -94,7 +99,8 @@ public class QuickDeliverGoodsService { @@ -94,7 +99,8 @@ public class QuickDeliverGoodsService {
94 try { 99 try {
95 QuickDeliverOrderContext qdoc = quickDeliverPublishProcessor.buildPublishCtx(req); 100 QuickDeliverOrderContext qdoc = quickDeliverPublishProcessor.buildPublishCtx(req);
96 return doPublish(qdoc); 101 return doPublish(qdoc);
97 - } finally { 102 + }finally {
  103 + //redis unlock
98 lock.unlock(); 104 lock.unlock();
99 } 105 }
100 } else { 106 } else {
@@ -111,7 +117,9 @@ public class QuickDeliverGoodsService { @@ -111,7 +117,9 @@ public class QuickDeliverGoodsService {
111 int successNum = 0; 117 int successNum = 0;
112 //submit all as atomic operation, use transaction of DB 118 //submit all as atomic operation, use transaction of DB
113 //all include : 1. skup, 2. order , 3. 寄回地址 119 //all include : 1. skup, 2. order , 3. 寄回地址
114 - for(String depositCode : context.getDepositCodes()) { 120 + for(Map.Entry<String, StorageDeposit> codeSDEntry: context.getDepositCodeSDMap().entrySet()) {
  121 + String depositCode = codeSDEntry.getKey();
  122 + StorageDeposit sd = codeSDEntry.getValue();
115 // step 2: create order, set status(not pay) 123 // step 2: create order, set status(not pay)
116 // generate a new real code 124 // generate a new real code
117 long orderCode = orderCodeGenerator.generate(OrderCodeType.SELLER_TYPE); 125 long orderCode = orderCodeGenerator.generate(OrderCodeType.SELLER_TYPE);
@@ -129,23 +137,30 @@ public class QuickDeliverGoodsService { @@ -129,23 +137,30 @@ public class QuickDeliverGoodsService {
129 //do submit 137 //do submit
130 int skup; 138 int skup;
131 try { 139 try {
132 - orderSubmitHandler.submit(context);  
133 - SellerOrderGoods psog = context.getSellerOrderGoods();  
134 - skup = psog.getId();  
135 - //record deposit code 4 deposit prd -> quick deliver  
136 - sellerOrderMetaService.saveDepositCode(depositCode, uid, skup);  
137 - logger.info("in QuickDeliverGoodsService.publish finish main local persistent, uid {} storageId {} salePrice {} orderCode {}",  
138 - uid, storageId, salePrice, orderCode); 140 + if(storageDepositSupport.lock(uid, depositCode, sd.getId())) {
  141 + orderSubmitHandler.submit(context);
  142 + SellerOrderGoods psog = context.getSellerOrderGoods();
  143 + skup = psog.getId();
  144 + //record deposit code 4 deposit prd -> quick deliver
  145 + sellerOrderMetaService.saveDepositCode(depositCode, uid, skup);
  146 + syncPrd(context, depositCode);
  147 + successNum++;
  148 + logger.info("in QuickDeliverGoodsService.publish finish main local persistent, uid {} storageId {} salePrice {} depositCode {} orderCode {}",
  149 + uid, storageId, salePrice,depositCode, orderCode);
  150 + }else{
  151 + logger.warn("storageDepositSupport do updateStorageShelveStatusByCAS fail , {}", sd);
  152 + }
139 } catch (Exception ex) { 153 } catch (Exception ex) {
140 String content = "用户" + uid + "发布闪购商品" + depositCode + "失败"; 154 String content = "用户" + uid + "发布闪购商品" + depositCode + "失败";
141 SmsAlarmEvent smsAlarmEvent = new SmsAlarmEvent("sellerOrder.create", "create", content); 155 SmsAlarmEvent smsAlarmEvent = new SmsAlarmEvent("sellerOrder.create", "create", content);
142 EventBusPublisher.publishEvent(smsAlarmEvent); 156 EventBusPublisher.publishEvent(smsAlarmEvent);
143 logger.warn("in publish quick deliver Prd create order fail , uid {}, depositCode {}", uid, depositCode, ex); 157 logger.warn("in publish quick deliver Prd create order fail , uid {}, depositCode {}", uid, depositCode, ex);
144 throw new ServiceException(ServiceError.EARNESTMONEY_ORDER_CREATE_FAIL); 158 throw new ServiceException(ServiceError.EARNESTMONEY_ORDER_CREATE_FAIL);
  159 + }finally {
  160 + //unlock
  161 + storageDepositSupport.unlock(uid, depositCode, sd.getId());
145 } 162 }
146 163
147 - syncPrd(context, depositCode);  
148 - successNum++;  
149 } 164 }
150 //在for循环中被用作值传递,部分数据会有变化,使用时需要注意动态变化的属性 165 //在for循环中被用作值传递,部分数据会有变化,使用时需要注意动态变化的属性
151 GoodsInfo goodsInfo = context.getSoldProduct(); 166 GoodsInfo goodsInfo = context.getSoldProduct();
@@ -23,7 +23,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -23,7 +23,10 @@ import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
24 24
25 import java.math.BigDecimal; 25 import java.math.BigDecimal;
26 -import java.util.*; 26 +import java.util.HashMap;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +import java.util.Objects;
27 30
28 @Service 31 @Service
29 public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliverOrderSubmitReq,QuickDeliverOrderContext> { 32 public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliverOrderSubmitReq,QuickDeliverOrderContext> {
@@ -78,18 +81,18 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv @@ -78,18 +81,18 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv
78 } 81 }
79 82
80 83
81 - List<String> depositCodes = new ArrayList<>(depositPrdsize);  
82 Map<String, AddressInfo> hiddenBackAddressMap = new HashMap<>(depositPrdsize), 84 Map<String, AddressInfo> hiddenBackAddressMap = new HashMap<>(depositPrdsize),
83 noHiddenBackAddressMap = new HashMap<>(depositPrdsize) 85 noHiddenBackAddressMap = new HashMap<>(depositPrdsize)
84 ; 86 ;
85 - 87 + Map<String, StorageDeposit> depositCodeSDMap = new HashMap<>(depositPrdsize);
86 for(StorageDeposit sd : depositPrds){ 88 for(StorageDeposit sd : depositPrds){
87 String depositCode = sd.getDepositCode(); 89 String depositCode = sd.getDepositCode();
88 AddressInfo hiddenBackAddress = buyerOrderMetaService.getHiddenAddressInfo(uid, sd.getOrderCode()); 90 AddressInfo hiddenBackAddress = buyerOrderMetaService.getHiddenAddressInfo(uid, sd.getOrderCode());
89 AddressInfo noHiddenBackAddress = buyerOrderMetaService.getAddressInfo(uid, sd.getOrderCode()); 91 AddressInfo noHiddenBackAddress = buyerOrderMetaService.getAddressInfo(uid, sd.getOrderCode());
90 - depositCodes.add(depositCode);  
91 hiddenBackAddressMap.put(depositCode, hiddenBackAddress); 92 hiddenBackAddressMap.put(depositCode, hiddenBackAddress);
92 noHiddenBackAddressMap.put(depositCode, noHiddenBackAddress); 93 noHiddenBackAddressMap.put(depositCode, noHiddenBackAddress);
  94 + //add 2 depositCodeSDMap
  95 + depositCodeSDMap.put(depositCode, sd);
93 } 96 }
94 97
95 98
@@ -100,11 +103,12 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv @@ -100,11 +103,12 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv
100 // 103 //
101 context.setHiddenBackAddressMap(hiddenBackAddressMap); 104 context.setHiddenBackAddressMap(hiddenBackAddressMap);
102 context.setNoHiddenBackAddressMap(noHiddenBackAddressMap); 105 context.setNoHiddenBackAddressMap(noHiddenBackAddressMap);
103 - context.setDepositCodes(depositCodes);  
104 context.setSoldProduct(goodsInfo); 106 context.setSoldProduct(goodsInfo);
105 // 107 //
106 context.setSkupType(skupType); 108 context.setSkupType(skupType);
107 context.setSellerOrderComputeResult(icpNode.getComputeResult()); 109 context.setSellerOrderComputeResult(icpNode.getComputeResult());
  110 + //
  111 + context.setDepositCodeSDMap(depositCodeSDMap);
108 return context; 112 return context;
109 } 113 }
110 } 114 }