记得上下班打卡 | git大法好,push需谨慎

Commit 7ca36097 authored by wangyifan's avatar wangyifan

草莓护照-添加缓存

parent d1c3fb46
...@@ -22,6 +22,10 @@ public class AdamRedisConst { ...@@ -22,6 +22,10 @@ public class AdamRedisConst {
public static final String INFO_ADDRESSES = PREFIX.concat("info:addresses:"); public static final String INFO_ADDRESSES = PREFIX.concat("info:addresses:");
public static final String INFO_CAOMEI_BADGE_PUBLISHED = PREFIX.concat("info:caomei:badge:published"); public static final String INFO_CAOMEI_BADGE_PUBLISHED = PREFIX.concat("info:caomei:badge:published");
public static final String INFO_CAOMEI_BADGE_USER = PREFIX.concat("info:caomei:badge:user:"); public static final String INFO_CAOMEI_BADGE_USER = PREFIX.concat("info:caomei:badge:user:");
/**
* 身份证号已支付演出ID列表(短缓存,缓解 kylin_order_ticket_entities 无身份证索引时的热点查询压力)
*/
public static final String INFO_CAOMEI_PAID_PERFORMANCE_IDS_BY_IDCARD = PREFIX.concat("info:caomei:paid_performance_ids:idcard:");
/** /**
* {adam:info:biz:{uid},List<com.liquidnet.service.adam.dto.vo.AdamUserBizAcctVo>} * {adam:info:biz:{uid},List<com.liquidnet.service.adam.dto.vo.AdamUserBizAcctVo>}
*/ */
......
...@@ -697,6 +697,38 @@ public class AdamRdmService { ...@@ -697,6 +697,38 @@ public class AdamRdmService {
return badges; return badges;
} }
/**
* 用户认领徽章时追加一条(与收货地址 addAddressesVoByUid 相同:写回整列表到 Redis)
*/
public boolean addUserCaomeiBadgeDtoByUid(String uid,
List<AdamCaomeiPassportUserBadgeDto> vos,
AdamCaomeiPassportUserBadgeDto dto) {
if (vos == null) {
vos = new ArrayList<>();
}
vos.add(dto);
return setUserCaomeiBadgesByUid(uid, vos);
}
/**
* 根据身份证获取已支付演出ID列表(60秒短缓存,缓解无索引热点查询)
*/
public List<String> getPaidPerformanceIdsByIdCard(String idCard) {
if (StringUtils.isEmpty(idCard)) {
return Collections.emptyList();
}
String rk = AdamRedisConst.INFO_CAOMEI_PAID_PERFORMANCE_IDS_BY_IDCARD.concat(idCard);
List<String> performanceIds = (List<String>) redisUtil.get(rk);
if (CollectionUtils.isEmpty(performanceIds)) {
performanceIds = adamCaomeiBadgeMapper.selectPaidPerformanceIdsByIdCard(idCard);
if (performanceIds == null) {
performanceIds = Collections.emptyList();
}
redisUtil.set(rk, performanceIds, 60);
}
return performanceIds;
}
/** /**
* 删除用户徽章redis * 删除用户徽章redis
* @param uid * @param uid
......
...@@ -2,6 +2,7 @@ package com.liquidnet.service.adam.service.impl; ...@@ -2,6 +2,7 @@ package com.liquidnet.service.adam.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.liquidnet.commons.lang.util.IDGenerator; import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.adam.dto.AdamCaomeiPassportUserBadgeDto;
import com.liquidnet.service.adam.dto.param.AdamCaomeiBadgeApplyParam; import com.liquidnet.service.adam.dto.param.AdamCaomeiBadgeApplyParam;
import com.liquidnet.service.adam.dto.AdamCaomeiBadgeApplyRecordUserDto; import com.liquidnet.service.adam.dto.AdamCaomeiBadgeApplyRecordUserDto;
import com.liquidnet.service.adam.dto.vo.AdamCaomeiBadgeApplyRecordUserVo; import com.liquidnet.service.adam.dto.vo.AdamCaomeiBadgeApplyRecordUserVo;
...@@ -14,14 +15,18 @@ import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeMapper; ...@@ -14,14 +15,18 @@ import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeMapper;
import com.liquidnet.service.adam.mapper.AdamCaomeiPassportMapper; import com.liquidnet.service.adam.mapper.AdamCaomeiPassportMapper;
import com.liquidnet.service.adam.service.AdamRdmService; import com.liquidnet.service.adam.service.AdamRdmService;
import com.liquidnet.service.adam.service.IAdamCaomeiBadgeUserService; import com.liquidnet.service.adam.service.IAdamCaomeiBadgeUserService;
import com.liquidnet.service.adam.util.QueueUtils;
import com.liquidnet.service.base.ErrorMapping; import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
...@@ -39,6 +44,8 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -39,6 +44,8 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
private AdamCaomeiBadgeApplyRecordMapper badgeApplyRecordMapper; private AdamCaomeiBadgeApplyRecordMapper badgeApplyRecordMapper;
@Autowired @Autowired
private AdamRdmService adamRdmService; private AdamRdmService adamRdmService;
@Autowired
private QueueUtils queueUtils;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
...@@ -58,7 +65,17 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -58,7 +65,17 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
return ResponseDto.failure(ErrorMapping.get("10607")); return ResponseDto.failure(ErrorMapping.get("10607"));
} }
// 2. 检查用户是否已经领取过该徽章 // 2. 与收货地址 add 一致:先取 Redis(或回源)用户徽章列表,再判重;DB 再兜一层防缓存未命中或其它写入路径
List<AdamCaomeiPassportUserBadgeDto> badgeVos = adamRdmService.getUserCaomeiBadgesByUid(uid);
if (badgeVos == null) {
badgeVos = new ArrayList<>();
} else {
badgeVos = new ArrayList<>(badgeVos);
}
if (badgeVos.stream().anyMatch(b -> badgeId.equals(b.getBadgeId()))) {
log.info("[claimBadge] 用户已领取过该徽章(Redis列表), uid: {}, badgeId: {}", uid, badgeId);
return ResponseDto.failure(ErrorMapping.get("10608"));
}
int count = adamCaomeiBadgeMapper.checkUserBadgeExists(uid, badgeId); int count = adamCaomeiBadgeMapper.checkUserBadgeExists(uid, badgeId);
if (count > 0) { if (count > 0) {
log.info("[claimBadge] 用户已领取过该徽章, uid: {}, badgeId: {}", uid, badgeId); log.info("[claimBadge] 用户已领取过该徽章, uid: {}, badgeId: {}", uid, badgeId);
...@@ -67,9 +84,7 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -67,9 +84,7 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
int type = badge.getType() == null ? 0 : badge.getType(); int type = badge.getType() == null ? 0 : badge.getType();
// 3. 根据徽章类型执行不同的认领逻辑
if (type == 1) { if (type == 1) {
// 护照纪念徽章:需要绑定了护照才能领取
AdamCaomeiPassport bound = adamCaomeiPassportMapper.selectOne( AdamCaomeiPassport bound = adamCaomeiPassportMapper.selectOne(
Wrappers.lambdaQuery(AdamCaomeiPassport.class) Wrappers.lambdaQuery(AdamCaomeiPassport.class)
.eq(AdamCaomeiPassport::getUserId, uid) .eq(AdamCaomeiPassport::getUserId, uid)
...@@ -80,15 +95,13 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -80,15 +95,13 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
log.error("[claimBadge] 认领护照纪念徽章需先绑定护照, uid: {}, badgeId: {}", uid, badgeId); log.error("[claimBadge] 认领护照纪念徽章需先绑定护照, uid: {}, badgeId: {}", uid, badgeId);
return ResponseDto.failure(ErrorMapping.get("10609")); return ResponseDto.failure(ErrorMapping.get("10609"));
} }
// 发放徽章 (source: 1-绑定护照自动发放/护照徽章认领) // 发放徽章 (source: 1-绑定护照自动发放/护照徽章认领):先写 Redis,再 MQ 落库
adamCaomeiBadgeMapper.insertUserBadge(uid, badgeId, 1); grantUserBadgeRedisThenMq(uid, badge, 1, badgeVos);
adamRdmService.delUserCaomeiBadgesByUid(uid);
log.info("[claimBadge] 护照纪念徽章认领成功, uid: {}, badgeId: {}", uid, badgeId); log.info("[claimBadge] 护照纪念徽章认领成功, uid: {}, badgeId: {}", uid, badgeId);
return ResponseDto.success(badgeId); return ResponseDto.success(badgeId);
} else if (type == 2) { } else if (type == 2) {
// 演出纪念徽章:需要实名认证 +(购票记录 或 补签审核已通过)
AdamRealInfoVo real = adamRdmService.getRealInfoVoByUidPlain(uid); AdamRealInfoVo real = adamRdmService.getRealInfoVoByUidPlain(uid);
if (real == null || real.getState() == null || real.getState() != 1 || StringUtils.isBlank(real.getIdCard())) { if (real == null || real.getState() == null || real.getState() != 1 || StringUtils.isBlank(real.getIdCard())) {
log.error("[claimBadge] 认领演出徽章需先实名, uid: {}, badgeId: {}", uid, badgeId); log.error("[claimBadge] 认领演出徽章需先实名, uid: {}, badgeId: {}", uid, badgeId);
...@@ -96,8 +109,7 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -96,8 +109,7 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
} }
String idCard = real.getIdCard(); String idCard = real.getIdCard();
List<String> paidPerformanceIds = adamCaomeiBadgeMapper.selectPaidPerformanceIdsByIdCard(idCard); List<String> paidPerformanceIds = adamRdmService.getPaidPerformanceIdsByIdCard(idCard);
// 有支付记录
boolean hasPaidRecord = paidPerformanceIds != null && paidPerformanceIds.contains(badge.getPerformanceId()); boolean hasPaidRecord = paidPerformanceIds != null && paidPerformanceIds.contains(badge.getPerformanceId());
Integer passedApplyCount = badgeApplyRecordMapper.selectCount( Integer passedApplyCount = badgeApplyRecordMapper.selectCount(
Wrappers.lambdaQuery(AdamCaomeiBadgeApplyRecord.class) Wrappers.lambdaQuery(AdamCaomeiBadgeApplyRecord.class)
...@@ -112,26 +124,13 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -112,26 +124,13 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
return ResponseDto.failure(ErrorMapping.get("10611")); return ResponseDto.failure(ErrorMapping.get("10611"));
} }
// 自动发放该演出所有关联徽章
// List<AdamCaomeiBadge> performanceBadges = adamCaomeiBadgeMapper.selectList(
// Wrappers.lambdaQuery(AdamCaomeiBadge.class)
// .eq(AdamCaomeiBadge::getPerformanceId, badge.getPerformanceId())
// .eq(AdamCaomeiBadge::getDisplayStatus, 1)
// .eq(AdamCaomeiBadge::getType, 2)
// );
// for (AdamCaomeiBadge perfBadge : performanceBadges) {
// 发放徽章:2-购票自动发放/演出徽章认领,3-补签审核通过后认领
int source = hasPaidRecord ? 2 : 3; int source = hasPaidRecord ? 2 : 3;
adamCaomeiBadgeMapper.insertUserBadge(uid, badgeId, source); grantUserBadgeRedisThenMq(uid, badge, source, badgeVos);
adamRdmService.delUserCaomeiBadgesByUid(uid);
// }
log.info("[claimBadge] 演出纪念徽章认领成功, uid: {}, badgeId: {}, 发放数量: {}", uid, badgeId, 1); log.info("[claimBadge] 演出纪念徽章认领成功, uid: {}, badgeId: {}, 发放数量: {}", uid, badgeId, 1);
return ResponseDto.success(badgeId); return ResponseDto.success(badgeId);
} else if (type == 3) { } else if (type == 3) {
// 特殊徽章不可自助领取
log.error("[claimBadge] 特殊徽章不可自助领取, uid: {}, badgeId: {}", uid, badgeId); log.error("[claimBadge] 特殊徽章不可自助领取, uid: {}, badgeId: {}", uid, badgeId);
return ResponseDto.failure(ErrorMapping.get("10612")); return ResponseDto.failure(ErrorMapping.get("10612"));
} }
...@@ -140,6 +139,31 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -140,6 +139,31 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
return ResponseDto.failure(ErrorMapping.get("10613")); return ResponseDto.failure(ErrorMapping.get("10613"));
} }
/**
* Redis 追加用户徽章展示 DTO,再发 MQ 异步执行 sqlmap 中的 INSERT。
*/
private void grantUserBadgeRedisThenMq(String uid, AdamCaomeiBadge badge, int source,
List<AdamCaomeiPassportUserBadgeDto> badgeVos) {
Date now = new Date();
AdamCaomeiPassportUserBadgeDto dto = new AdamCaomeiPassportUserBadgeDto();
dto.setBadgeId(badge.getBadgeId());
dto.setBadgeName(StringUtils.defaultString(badge.getName()));
dto.setIcon(StringUtils.defaultString(badge.getIcon()));
dto.setShareText(StringUtils.defaultString(badge.getShareText()));
dto.setType(badge.getType());
dto.setClaimedAt(now);
dto.setSource(source);
adamRdmService.addUserCaomeiBadgeDtoByUid(uid, badgeVos, dto);
long t = System.currentTimeMillis();
queueUtils.sendMsgByRedis(
MQConst.AdamQueue.SQL_UCENTER.getKey(),
SqlMapping.get("adam_caomei_user_badge.add", uid, badge.getBadgeId(), source)
);
log.debug("[claimBadge] MQ耗时:{}ms, uid: {}, badgeId: {}", System.currentTimeMillis() - t, uid, badge.getBadgeId());
}
@Override @Override
public ResponseDto<List<AdamCaomeiBadgeApplyRecordUserVo>> getApplyRecords(String uid) { public ResponseDto<List<AdamCaomeiBadgeApplyRecordUserVo>> getApplyRecords(String uid) {
if (StringUtils.isBlank(uid)) { if (StringUtils.isBlank(uid)) {
...@@ -164,7 +188,6 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -164,7 +188,6 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public ResponseDto<String> applyBadge(AdamCaomeiBadgeApplyParam param, String uid) { public ResponseDto<String> applyBadge(AdamCaomeiBadgeApplyParam param, String uid) {
if (StringUtils.isBlank(uid)) { if (StringUtils.isBlank(uid)) {
return ResponseDto.failure(ErrorMapping.get("10001")); return ResponseDto.failure(ErrorMapping.get("10001"));
...@@ -202,21 +225,19 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi ...@@ -202,21 +225,19 @@ public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserServi
return ResponseDto.failure("您已有待审核的补签申请,请勿重复提交"); return ResponseDto.failure("您已有待审核的补签申请,请勿重复提交");
} }
Date now = new Date(); final String applyRecordId = IDGenerator.nextSnowId();
AdamCaomeiBadgeApplyRecord record = new AdamCaomeiBadgeApplyRecord(); long t = System.currentTimeMillis();
record.setApplyRecordId(IDGenerator.nextSnowId()); queueUtils.sendMsgByRedis(
record.setUserId(uid); MQConst.AdamQueue.SQL_UCENTER.getKey(),
record.setBadgeId(badgeId); SqlMapping.get("adam_caomei_badge_apply_record.add",
record.setPerformanceId(StringUtils.defaultString(badge.getPerformanceId())); applyRecordId,
record.setProofImageUrl(proofImageUrl); uid,
record.setAuditStatus(0); badgeId,
record.setRejectReason(""); badge.getPerformanceId(),
record.setCreatedAt(now); proofImageUrl)
record.setUpdatedAt(now); );
int inserted = badgeApplyRecordMapper.insert(record); log.info("[claimBadge] MQ耗时:{}ms, uid: {}, badgeId: {}", System.currentTimeMillis() - t, uid, badge.getBadgeId());
if (inserted <= 0) {
return ResponseDto.failure(); return ResponseDto.success(applyRecordId);
}
return ResponseDto.success(record.getApplyRecordId());
} }
} }
...@@ -153,7 +153,7 @@ public class AdamCaomeiPassportUserServiceImpl implements IAdamCaomeiPassportUse ...@@ -153,7 +153,7 @@ public class AdamCaomeiPassportUserServiceImpl implements IAdamCaomeiPassportUse
// 5. TODO 优化点 // 5. TODO 优化点
final List<String> paidPerformanceIds = StringUtils.isNotBlank(idCard) final List<String> paidPerformanceIds = StringUtils.isNotBlank(idCard)
? adamCaomeiBadgeMapper.selectPaidPerformanceIdsByIdCard(idCard) ? adamRdmService.getPaidPerformanceIdsByIdCard(idCard)
: new ArrayList<>(); : new ArrayList<>();
log.info("[getPassportHome] 用户已支付的演出订单数量, uid: {}, 数量: {}", uid, paidPerformanceIds.size()); log.info("[getPassportHome] 用户已支付的演出订单数量, uid: {}, 数量: {}", uid, paidPerformanceIds.size());
......
...@@ -80,10 +80,13 @@ adam_user_mobile_locate.update_province=UPDATE adam_user_mobile_locate SET provi ...@@ -80,10 +80,13 @@ adam_user_mobile_locate.update_province=UPDATE adam_user_mobile_locate SET provi
adam_user_mobile_locate.close=UPDATE adam_user_mobile_locate SET `state`=2, updated_at=? WHERE uid=? AND `state`=1 adam_user_mobile_locate.close=UPDATE adam_user_mobile_locate SET `state`=2, updated_at=? WHERE uid=? AND `state`=1
# ---------------------------------------------------- # ----------------------------------------------------
# 草莓护照-用户徽章获得记录 (adam_caomei_user_badge)
# 用户端 claimBadge:与 AdamCaomeiBadgeUserServiceImpl 中「先写 Redis 用户徽章列表、再 MQ 异步落库」配套;参数顺序 user_id, badge_id, source;created_at 由库端 now() 写入
adam_caomei_user_badge.add=INSERT INTO adam_caomei_user_badge (user_id, badge_id, source, created_at) VALUES (?,?,?,now())
# 草莓护照-徽章补签申请 (adam_caomei_badge_apply_record)
# ---------------------------------------------------- # 用户端 applyBadge:与「先写 Redis 补签列表、再 MQ 异步落库」配套;参数顺序 apply_record_id, user_id, badge_id, performance_id, proof_image_url;audit_status=0、reject_reason 空串、时间由 now() 写入
adam_caomei_badge_apply_record.add=INSERT INTO adam_caomei_badge_apply_record (apply_record_id, user_id, badge_id, performance_id, proof_image_url, audit_status, reject_reason, created_at, updated_at) VALUES (?,?,?,?,?,0,'',now(),now())
# ---------------------------------------------------- # ----------------------------------------------------
candy_user_coupon.close=UPDATE candy_user_coupon SET state=2,updated_at=sysdate(),operator='close' WHERE uid=? AND state=1 candy_user_coupon.close=UPDATE candy_user_coupon SET state=2,updated_at=sysdate(),operator='close' WHERE uid=? AND state=1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment