提交 7df1b8a2 作者: 沈振路

刷公众号用户标签的测试类接口改为多线程

上级 f430e24b
...@@ -51,6 +51,7 @@ import java.util.Objects; ...@@ -51,6 +51,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
...@@ -355,6 +356,11 @@ public class TestController { ...@@ -355,6 +356,11 @@ public class TestController {
private static final String TAG_NAME_ALL_USER = "全量用户"; private static final String TAG_NAME_ALL_USER = "全量用户";
private static final String TAG_NAME_MINI_PROGRAM_USER = "小程序用户"; private static final String TAG_NAME_MINI_PROGRAM_USER = "小程序用户";
private static final int BATCH_TAGGING_SIZE = 50; private static final int BATCH_TAGGING_SIZE = 50;
private static final int ACCOUNT_BATCH_SIZE = 100;
private static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(
3, 3, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(),
new ThreadPoolExecutor.CallerRunsPolicy());
@Resource @Resource
private WeChatTagCleanMapper weChatTagCleanMapper; private WeChatTagCleanMapper weChatTagCleanMapper;
...@@ -365,18 +371,14 @@ public class TestController { ...@@ -365,18 +371,14 @@ public class TestController {
public void refreshFullUserTag() { public void refreshFullUserTag() {
log.info("开始为公众号用户打全量用户标签..."); log.info("开始为公众号用户打全量用户标签...");
int startIdx = 0;
Object val = redisTemplate.opsForValue().get("operate:customer:refreshWechatTag:startIdx");
if (val != null) {
startIdx = Integer.parseInt(String.valueOf(val));
}
List<PendingAuthAccountVO> accounts = weChatTagCleanMapper.getPendingAuthAccounts(); List<PendingAuthAccountVO> accounts = weChatTagCleanMapper.getPendingAuthAccounts();
accounts = accounts.subList(Math.min(startIdx, accounts.size()), accounts.size());
log.info("待处理公众号数量: {}", accounts.size()); log.info("待处理公众号数量: {}", accounts.size());
Map<Long, Integer> fullUserWechatTagIdByAuthorizer = Collections.emptyMap(); if (accounts.isEmpty()) {
Map<Long, Integer> miniProgramUserWechatTagIdByAuthorizer = Collections.emptyMap(); log.info("没有待处理的公众号");
return;
}
List<Long> authorizerIdsToQuery = accounts.stream() List<Long> authorizerIdsToQuery = accounts.stream()
.map(PendingAuthAccountVO::getAuthId) .map(PendingAuthAccountVO::getAuthId)
...@@ -384,7 +386,9 @@ public class TestController { ...@@ -384,7 +386,9 @@ public class TestController {
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
if (!authorizerIdsToQuery.isEmpty()) { if (authorizerIdsToQuery.isEmpty()) {
return;
}
List<AuthorizerFullUserTagVO> dbTagRows = List<AuthorizerFullUserTagVO> dbTagRows =
weChatTagCleanMapper.listFullUserWechatTagByAuthorizers( weChatTagCleanMapper.listFullUserWechatTagByAuthorizers(
authorizerIdsToQuery, authorizerIdsToQuery,
...@@ -401,9 +405,9 @@ public class TestController { ...@@ -401,9 +405,9 @@ public class TestController {
AuthorizerFullUserTagVO::getWechatTagId, AuthorizerFullUserTagVO::getWechatTagId,
(left, right) -> left))); (left, right) -> left)));
fullUserWechatTagIdByAuthorizer = Map<Long, Integer> fullUserWechatTagIdByAuthorizer =
tagMapByTagName.getOrDefault(TAG_NAME_ALL_USER, Collections.emptyMap()); tagMapByTagName.getOrDefault(TAG_NAME_ALL_USER, Collections.emptyMap());
miniProgramUserWechatTagIdByAuthorizer = Map<Long, Integer> miniProgramUserWechatTagIdByAuthorizer =
tagMapByTagName.getOrDefault(TAG_NAME_MINI_PROGRAM_USER, Collections.emptyMap()); tagMapByTagName.getOrDefault(TAG_NAME_MINI_PROGRAM_USER, Collections.emptyMap());
log.info("从库中载入标签映射: 「{}」{} 条, 「{}」{} 条 (授权方候选数: {})", log.info("从库中载入标签映射: 「{}」{} 条, 「{}」{} 条 (授权方候选数: {})",
...@@ -412,32 +416,56 @@ public class TestController { ...@@ -412,32 +416,56 @@ public class TestController {
TAG_NAME_MINI_PROGRAM_USER, TAG_NAME_MINI_PROGRAM_USER,
miniProgramUserWechatTagIdByAuthorizer.size(), miniProgramUserWechatTagIdByAuthorizer.size(),
authorizerIdsToQuery.size()); authorizerIdsToQuery.size());
List<List<PendingAuthAccountVO>> accountBatches = Lists.partition(accounts, ACCOUNT_BATCH_SIZE);
int batchIdx = 0;
for (List<PendingAuthAccountVO> batch : accountBatches) {
batchIdx++;
log.info("开始处理第 {} / {} 组, 本组公众号数量: {}", batchIdx, accountBatches.size(), batch.size());
List<String> batchAppids = batch.stream()
.map(PendingAuthAccountVO::getAppid)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Map<String, String> tokenMap;
if (!batchAppids.isEmpty()) {
List<PendingAuthAccountVO> tokenResults = weChatTagCleanMapper.getTokensByAppids(batchAppids);
tokenMap = tokenResults.stream()
.filter(t -> t.getAppid() != null && t.getAuthorizerAccessToken() != null)
.collect(Collectors.toMap(
PendingAuthAccountVO::getAppid,
PendingAuthAccountVO::getAuthorizerAccessToken,
(a, b) -> a));
} else {
tokenMap = Collections.emptyMap();
} }
log.info("第 {} 组实时查询 token 结果: {} 条", batchIdx, tokenMap.size());
int idx = 1; List<Future<?>> futures = new ArrayList<>();
for (PendingAuthAccountVO account : accounts) { for (PendingAuthAccountVO account : batch) {
futures.add(THREAD_POOL.submit(() -> {
String appid = account.getAppid(); String appid = account.getAppid();
String nickName = account.getNickName(); String nickName = account.getNickName();
String accessToken = account.getAuthorizerAccessToken(); String accessToken = tokenMap.get(appid);
Long authId = account.getAuthId(); Long authId = account.getAuthId();
if (StringUtils.isAnyBlank(appid, accessToken)) { if (StringUtils.isAnyBlank(appid, accessToken)) {
log.warn("公众号信息缺失, 跳过: appid={}, nickName={}", appid, nickName); log.warn("公众号信息缺失, 跳过: appid={}, nickName={}", appid, nickName);
continue; return;
} }
if (authId == null) { if (authId == null) {
log.warn("公众号缺少 authId(authorizer_id), 跳过: appid={}, nickName={}", appid, nickName); log.warn("公众号缺少 authId(authorizer_id), 跳过: appid={}, nickName={}", appid, nickName);
continue; return;
} }
log.info("刷新公众号用户标签进度:{} / {},当前公众号:{}", idx++, accounts.size(), account.getNickName());
try { try {
Integer fullUserTagId = fullUserWechatTagIdByAuthorizer.get(authId); Integer fullUserTagId = fullUserWechatTagIdByAuthorizer.get(authId);
if (fullUserTagId == null) { if (fullUserTagId == null) {
log.warn("公众号 {}({}) 在库中未找到 [{}] 标签记录, 跳过", nickName, appid, log.warn("公众号 {}({}) 在库中未找到 [{}] 标签记录, 跳过", nickName, appid,
TAG_NAME_ALL_USER); TAG_NAME_ALL_USER);
continue; return;
} }
Integer miniProgramUserTagId = miniProgramUserWechatTagIdByAuthorizer.get(authId); Integer miniProgramUserTagId = miniProgramUserWechatTagIdByAuthorizer.get(authId);
...@@ -457,7 +485,7 @@ public class TestController { ...@@ -457,7 +485,7 @@ public class TestController {
.collect(Collectors.toList()); .collect(Collectors.toList());
if (needTagOpenidList.isEmpty()) { if (needTagOpenidList.isEmpty()) {
continue; return;
} }
List<List<String>> partitions = Lists.partition(needTagOpenidList, BATCH_TAGGING_SIZE); List<List<String>> partitions = Lists.partition(needTagOpenidList, BATCH_TAGGING_SIZE);
...@@ -480,10 +508,22 @@ public class TestController { ...@@ -480,10 +508,22 @@ public class TestController {
log.info("公众号 appid={}, 名称={}, 此次更新标签的用户数={}, 目标标签id={}", log.info("公众号 appid={}, 名称={}, 此次更新标签的用户数={}, 目标标签id={}",
appid, nickName, updatedCount, fullUserTagId); appid, nickName, updatedCount, fullUserTagId);
TimeUnit.MILLISECONDS.sleep(500);
} catch (Exception e) { } catch (Exception e) {
log.error("处理公众号 {}({}) 时发生错误: {}", nickName, appid, e.getMessage(), e); log.error("处理公众号 {}({}) 时发生错误: {}", nickName, appid, e.getMessage(), e);
} }
}));
}
for (Future<?> future : futures) {
try {
future.get();
} catch (Exception e) {
log.error("等待线程执行完成时发生错误: {}", e.getMessage(), e);
}
}
log.info("第 {} / {} 组处理完成", batchIdx, accountBatches.size());
} }
log.info("公众号用户全量用户标签清洗完成"); log.info("公众号用户全量用户标签清洗完成");
......
...@@ -32,5 +32,9 @@ public interface WeChatTagCleanMapper { ...@@ -32,5 +32,9 @@ public interface WeChatTagCleanMapper {
@Param("authorizerIds") List<Long> authorizerIds, @Param("authorizerIds") List<Long> authorizerIds,
@Param("tagNames") List<String> tagNames); @Param("tagNames") List<String> tagNames);
/**
* 根据 appid 列表实时查询 access_token
*/
List<PendingAuthAccountVO> getTokensByAppids(@Param("appids") List<String> appids);
} }
...@@ -6,15 +6,23 @@ ...@@ -6,15 +6,23 @@
SELECT SELECT
ai.id AS authId, ai.id AS authId,
ai.appid AS appid, ai.appid AS appid,
ai.nick_name AS nickName, ai.nick_name AS nickName
atk.authorizer_access_token AS authorizerAccessToken
FROM authorizer_info ai FROM authorizer_info ai
LEFT JOIN authorizer_token atk ON atk.authorizer_appid = ai.appid
WHERE ai.store_type IN ( WHERE ai.store_type IN (
'YANG_GUANG','TOMATO','YUE_WEN_1' 'YANG_GUANG','TOMATO','YUE_WEN_1'
) )
AND atk.create_time >= DATE_ADD(CURRENT_DATE,INTERVAL -1 DAY) </select>
<select id="getTokensByAppids" resultType="com.yaoyaozw.customer.vo.wechat.PendingAuthAccountVO">
SELECT
ai.appid AS appid,
atk.authorizer_access_token AS authorizerAccessToken
FROM authorizer_info ai
LEFT JOIN authorizer_token atk ON atk.authorizer_appid = ai.appid
WHERE ai.appid IN
<foreach collection="appids" item="appid" open="(" separator="," close=")">
#{appid}
</foreach>
</select> </select>
<select id="listFullUserWechatTagByAuthorizers" <select id="listFullUserWechatTagByAuthorizers"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论