Authored by mali

Merge branch 'master' into test6.9.10

... ... @@ -89,9 +89,10 @@ public interface StorageDepositMapper {
int updateDelStatusByCode(@Param("uid")Integer uid, @Param("depositCode")String depositCode, @Param("status")Integer status);
int updateStorageLockFlagByCAS(@Param("uid")int uid,
@Param("depositCode")String depositCode,
int updateStorageLockFlagByCAS(@Param("id")int id,
@Param("status")int status,
@Param("expectStatus")int expectStatus
);
int removeStorageLockFlag(int id);
}
\ No newline at end of file
... ...
... ... @@ -420,10 +420,16 @@
<update id="updateStorageLockFlagByCAS">
update storage_deposit
set lock_flag = #{status,jdbcType=INTEGER} ,update_time = unix_timestamp(now())
where owner_uid = #{uid,jdbcType=INTEGER}
and deposit_code = #{depositCode,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
AND lock_flag = #{expectStatus,jdbcType=INTEGER}
and order_status = #{expectStatus,jdbcType=INTEGER}
AND del_status = 0
</update>
<update id="removeStorageLockFlag" parameterType="java.lang.Integer">
update storage_deposit
set lock_flag = 0 ,update_time = unix_timestamp(now())
where id = #{id,jdbcType=INTEGER}
AND lock_flag = 1
</update>
</mapper>
\ No newline at end of file
... ...
package com.yohoufo.order.model;
import com.yohobuy.ufo.model.order.vo.AddressInfo;
import com.yohoufo.dal.order.model.StorageDeposit;
import lombok.Data;
import java.util.List;
... ... @@ -10,9 +11,11 @@ import java.util.Map;
public class QuickDeliverOrderContext extends SellerOrderContext {
private List<String> depositCodes;
private Map<String, AddressInfo> hiddenBackAddressMap;
private Map<String, AddressInfo> noHiddenBackAddressMap;
//
private Map<String, StorageDeposit> depositCodeSDMap;
}
... ...
package com.yohoufo.order.service.deposit;
import com.yohoufo.dal.order.StorageDepositMapper;
import com.yohoufo.order.utils.LoggerUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class StorageDepositSupport {
private final Logger LOGGER = LoggerUtils.getSellerOrderLogger();
@Autowired
private StorageDepositMapper storageDepositMapper;
private class DepositLock{
private int sellerUid;
private String depositCode;
private int unlockStatus = 0, lockStatus = 1;
DepositLock(int sellerUid, String depositCode){
this.sellerUid = sellerUid;
this.depositCode = depositCode;
}
boolean lock(int id){
int rows = storageDepositMapper.updateStorageLockFlagByCAS(id, lockStatus, unlockStatus);
LOGGER.info("in DepositLock.lock id {} sellerUid {} depositCode {} rows {}", id, sellerUid, depositCode, rows);
return rows > 0;
}
boolean unlock(int id){
int rows = storageDepositMapper.removeStorageLockFlag(id);
LOGGER.info("in DepositLock.unlock id {} sellerUid {} depositCode {} rows {}", id, sellerUid, depositCode, rows);
return rows > 0;
}
}
public boolean lock(int uid, String depositCode, int id){
return new DepositLock(uid, depositCode).lock(id);
}
public boolean unlock(int uid, String depositCode, int depositId){
//unlock
return new DepositLock(uid, depositCode).unlock(depositId);
}
}
... ...
... ... @@ -30,11 +30,8 @@ import com.yohoufo.order.model.response.AppraiseAddressResp;
import com.yohoufo.order.service.DepositService;
import com.yohoufo.order.service.proxy.InBoxFacade;
import com.yohoufo.order.service.proxy.ProductProxyService;
import com.yohoufo.order.service.proxy.SellerNoticeFacade;
import com.yohoufo.order.service.seller.SkupService;
import com.yohoufo.order.utils.LoggerUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -78,8 +75,6 @@ public class DepositServiceImpl implements DepositService {
@Autowired
private SkupService skupService;
@Autowired
private SellerNoticeFacade sellerNoticeFacade;
@Autowired
private InBoxFacade inBoxFacade;
... ... @@ -265,8 +260,6 @@ public class DepositServiceImpl implements DepositService {
boolean result = storageDepositMapper.changeSaleStatusOn(uid, depositCode, skup) == 1;
if (result) {
cleanCacheWhenOnShelve(uid, depositCode);
//unlock
new DepositLock(uid, depositCode).unlock();
}
return result;
}
... ... @@ -309,27 +302,7 @@ public class DepositServiceImpl implements DepositService {
return null;
}
private class DepositLock{
private int sellerUid;
private String depositCode;
private int unlockStatus = 0, lockStatus = 1;
DepositLock(int sellerUid, String depositCode){
this.sellerUid = sellerUid;
this.depositCode = depositCode;
}
boolean lock(){
int rows = storageDepositMapper.updateStorageLockFlagByCAS(sellerUid, depositCode, lockStatus, unlockStatus);
LOGGER.info("in DepositLock.lock sellerUid {} depositCode {} rows {}", sellerUid, depositCode, rows);
return rows > 0;
}
boolean unlock(){
int rows = storageDepositMapper.updateStorageLockFlagByCAS(sellerUid, depositCode, unlockStatus, lockStatus);
LOGGER.info("in DepositLock.unlock sellerUid {} depositCode {} rows {}", sellerUid, depositCode, rows);
return rows > 0;
}
}
/**
* 批量上架-查询
* 应当锁定相关记录,加中间状态
... ... @@ -343,26 +316,8 @@ public class DepositServiceImpl implements DepositService {
if (CollectionUtils.isEmpty(sdList)){
LOGGER.warn("in getStorageDeposit4Publish StorageDeposit empty, uid {} storageId {} num {}",
uid, storageId, num);
return sdList;
}
List<StorageDeposit> lockedList = new ArrayList<>(sdList.size());
for (StorageDeposit sd : sdList) {
DepositLock lock = new DepositLock(uid, sd.getDepositCode());
try{
if (lock.lock()) {
lockedList.add(sd);
} else {
LOGGER.warn("getStorageDeposit4Publish updateStorageShelveStatusByCAS fail ,{}", sd);
}
}catch (Exception ex){
//release lock, give a second chance 2 survivor
lock.unlock();
LOGGER.warn("getStorageDeposit4Publish updateStorageShelveStatusByCAS occur exception {} - {}",
sd, Throwables.getStackTraceAsString(ex));
continue;
}
}
return lockedList;
return sdList;
}
// 批量下架
... ...
... ... @@ -16,16 +16,18 @@ import com.yohobuy.ufo.model.order.resp.PageResp;
import com.yohobuy.ufo.model.order.resp.SellerGoodsPageResp;
import com.yohoufo.common.alarm.EventBusPublisher;
import com.yohoufo.common.alarm.SmsAlarmEvent;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.common.lock.RedisLock;
import com.yohoufo.common.lock.RedisLockFactory;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.dal.order.SellerOrderGoodsViewMapper;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.dal.order.model.StorageDeposit;
import com.yohoufo.order.model.QuickDeliverOrderContext;
import com.yohoufo.order.model.request.OrderListRequest;
import com.yohoufo.order.model.request.SellerGoodsListRequest;
import com.yohoufo.order.model.response.DepositPublishResp;
import com.yohoufo.order.service.DepositService;
import com.yohoufo.order.service.deposit.StorageDepositSupport;
import com.yohoufo.order.service.handler.SellerOrderSubmitHandler;
import com.yohoufo.order.service.impl.SkupListService;
import com.yohoufo.order.service.proxy.ProductProxyService;
... ... @@ -41,7 +43,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
... ... @@ -85,6 +87,9 @@ public class QuickDeliverGoodsService {
@Autowired
private RedisLockFactory redisLockFactory;
@Autowired
private StorageDepositSupport storageDepositSupport;
public DepositPublishResp publish(QuickDeliverOrderSubmitReq req) {
RedisKeyBuilder redisLockKey = RedisKeyBuilder.newInstance()
.appendFixed("ufo:order:lock:publishQuickDeliverGoods:")
... ... @@ -94,7 +99,8 @@ public class QuickDeliverGoodsService {
try {
QuickDeliverOrderContext qdoc = quickDeliverPublishProcessor.buildPublishCtx(req);
return doPublish(qdoc);
} finally {
}finally {
//redis unlock
lock.unlock();
}
} else {
... ... @@ -111,7 +117,9 @@ public class QuickDeliverGoodsService {
int successNum = 0;
//submit all as atomic operation, use transaction of DB
//all include : 1. skup, 2. order , 3. 寄回地址
for(String depositCode : context.getDepositCodes()) {
for(Map.Entry<String, StorageDeposit> codeSDEntry: context.getDepositCodeSDMap().entrySet()) {
String depositCode = codeSDEntry.getKey();
StorageDeposit sd = codeSDEntry.getValue();
// step 2: create order, set status(not pay)
// generate a new real code
long orderCode = orderCodeGenerator.generate(OrderCodeType.SELLER_TYPE);
... ... @@ -129,23 +137,30 @@ public class QuickDeliverGoodsService {
//do submit
int skup;
try {
orderSubmitHandler.submit(context);
SellerOrderGoods psog = context.getSellerOrderGoods();
skup = psog.getId();
//record deposit code 4 deposit prd -> quick deliver
sellerOrderMetaService.saveDepositCode(depositCode, uid, skup);
logger.info("in QuickDeliverGoodsService.publish finish main local persistent, uid {} storageId {} salePrice {} orderCode {}",
uid, storageId, salePrice, orderCode);
if(storageDepositSupport.lock(uid, depositCode, sd.getId())) {
orderSubmitHandler.submit(context);
SellerOrderGoods psog = context.getSellerOrderGoods();
skup = psog.getId();
//record deposit code 4 deposit prd -> quick deliver
sellerOrderMetaService.saveDepositCode(depositCode, uid, skup);
syncPrd(context, depositCode);
successNum++;
logger.info("in QuickDeliverGoodsService.publish finish main local persistent, uid {} storageId {} salePrice {} depositCode {} orderCode {}",
uid, storageId, salePrice,depositCode, orderCode);
}else{
logger.warn("storageDepositSupport do updateStorageShelveStatusByCAS fail , {}", sd);
}
} catch (Exception ex) {
String content = "用户" + uid + "发布闪购商品" + depositCode + "失败";
SmsAlarmEvent smsAlarmEvent = new SmsAlarmEvent("sellerOrder.create", "create", content);
EventBusPublisher.publishEvent(smsAlarmEvent);
logger.warn("in publish quick deliver Prd create order fail , uid {}, depositCode {}", uid, depositCode, ex);
throw new ServiceException(ServiceError.EARNESTMONEY_ORDER_CREATE_FAIL);
}finally {
//unlock
storageDepositSupport.unlock(uid, depositCode, sd.getId());
}
syncPrd(context, depositCode);
successNum++;
}
//在for循环中被用作值传递,部分数据会有变化,使用时需要注意动态变化的属性
GoodsInfo goodsInfo = context.getSoldProduct();
... ...
... ... @@ -23,7 +23,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Service
public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliverOrderSubmitReq,QuickDeliverOrderContext> {
... ... @@ -78,18 +81,18 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv
}
List<String> depositCodes = new ArrayList<>(depositPrdsize);
Map<String, AddressInfo> hiddenBackAddressMap = new HashMap<>(depositPrdsize),
noHiddenBackAddressMap = new HashMap<>(depositPrdsize)
;
Map<String, StorageDeposit> depositCodeSDMap = new HashMap<>(depositPrdsize);
for(StorageDeposit sd : depositPrds){
String depositCode = sd.getDepositCode();
AddressInfo hiddenBackAddress = buyerOrderMetaService.getHiddenAddressInfo(uid, sd.getOrderCode());
AddressInfo noHiddenBackAddress = buyerOrderMetaService.getAddressInfo(uid, sd.getOrderCode());
depositCodes.add(depositCode);
hiddenBackAddressMap.put(depositCode, hiddenBackAddress);
noHiddenBackAddressMap.put(depositCode, noHiddenBackAddress);
//add 2 depositCodeSDMap
depositCodeSDMap.put(depositCode, sd);
}
... ... @@ -100,11 +103,12 @@ public class QuickDeliverPublishProcessor implements PublishProcessor<QuickDeliv
//
context.setHiddenBackAddressMap(hiddenBackAddressMap);
context.setNoHiddenBackAddressMap(noHiddenBackAddressMap);
context.setDepositCodes(depositCodes);
context.setSoldProduct(goodsInfo);
//
context.setSkupType(skupType);
context.setSellerOrderComputeResult(icpNode.getComputeResult());
//
context.setDepositCodeSDMap(depositCodeSDMap);
return context;
}
}
... ...