Merge branch 'refs/heads/master' into feature/REQ-2655

This commit is contained in:
yanglin 2024-07-17 09:35:32 +08:00
commit 1bc9bb0e67
7 changed files with 71 additions and 60 deletions

View File

@ -21,6 +21,10 @@
</properties>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.trade</groupId>
<artifactId>trade-web-spring-boot-starter</artifactId>

View File

@ -3,7 +3,10 @@ package cn.axzo.msg.center.message.service.group;
import cn.axzo.maokai.api.vo.response.tree.NodeValue;
import cn.axzo.msg.center.domain.entity.MessageGroupNode;
import cn.axzo.msg.center.utils.TreeHelperUtil;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
@ -16,6 +19,13 @@ public class NodeWrapper implements NodeValue {
private final MessageGroupNode node;
private final Map<String, Long> code2Id;
/**
* cache path for better performance
* visit via {@link RootNodeWrapper#getPath}
*/
@Setter(AccessLevel.PACKAGE)
@Getter(AccessLevel.PACKAGE)
private String cachedPath;
@Override
public Long id() {

View File

@ -1,22 +1,17 @@
package cn.axzo.msg.center.message.service.group;
import cn.axzo.maokai.api.util.Ref;
import cn.axzo.maokai.api.vo.response.tree.Node;
import cn.axzo.maokai.api.vo.response.tree.RootNode;
import cn.axzo.maokai.api.vo.response.tree.ValueNode;
import cn.axzo.msg.center.common.utils.BizAssertions;
import cn.axzo.msg.center.domain.entity.MessageGroupNode;
import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
@ -25,13 +20,14 @@ import static java.util.stream.Collectors.toMap;
*/
public class RootNodeWrapper {
private final RootNode<NodeWrapper> root;
private final Map<String, ValueNode<NodeWrapper>> code2Node;
private final Map<Long, ValueNode<NodeWrapper>> id2Node;
public RootNodeWrapper(RootNode<NodeWrapper> root) {
this.root = root;
RootNodeWrapper(RootNode<NodeWrapper> root) {
this.code2Node = root.getValueNodes().stream()
.collect(toMap(node -> node.getValue().getNodeCode(), Function.identity()));
.collect(toMap(node -> node.getValue().getNodeCode(), identity()));
this.id2Node = root.getValueNodes().stream()
.collect(toMap(node -> node.getValue().unwrap().getId(), identity()));
}
public Optional<ValueNode<NodeWrapper>> findValueNode(String groupNodeCode) {
@ -39,18 +35,7 @@ public class RootNodeWrapper {
}
public Optional<ValueNode<NodeWrapper>> findValueNode(Long id) {
Ref<ValueNode<NodeWrapper>> ref = Ref.create();
unwrap().walkDown(node -> {
//noinspection unchecked
ValueNode<NodeWrapper> valueNode = node.tryCast(ValueNode.class);
if (valueNode == null)
return true;
MessageGroupNode groupNode = valueNode.getValue().unwrap();
if (id.equals(groupNode.getId()))
ref.set(valueNode);
return ref.isNull();
});
return Optional.ofNullable(ref.get());
return Optional.ofNullable(id2Node.get(id));
}
public List<ValueNode<NodeWrapper>> getNodes(Collection<String> groupNodeCodes) {
@ -63,24 +48,33 @@ public class RootNodeWrapper {
}
public String getPath(ValueNode<NodeWrapper> node) {
ArrayList<String> paths = new ArrayList<>();
NodeWrapper wrapper = node.getValue();
if (wrapper.getCachedPath() == null)
wrapper.setCachedPath(getPathImpl(node));
return wrapper.getCachedPath();
}
private String getPathImpl(ValueNode<NodeWrapper> node) {
// a1912618861c4dab8aaee954069762a0:a1912618861c4dab8aaee954069762a1:a1912618861c4dab8aaee954069762a2
// code是uuid去掉-, 一般层级为3, 通过冒号分割, 所有长度为: 32 * 3 + 2 = 98
// 初始长度直接设置为98, 避免频繁扩容
StringBuilder builder = new StringBuilder(98);
Node current = node;
int stack = 0;
while (current != null) {
BizAssertions.assertTrue(stack <= 500, String.format(
"分类层级过多或者数据错误, 最大层级: %s", JSON.toJSONString(current)));
// Assuming a reasonable maximum depth to avoid frequent resizing
BizAssertions.assertTrue(stack <= 500, "分类层级过多或者数据错误");
stack++;
//noinspection unchecked
@SuppressWarnings("unchecked")
ValueNode<NodeWrapper> valueNode = current.tryCast(ValueNode.class);
if (valueNode != null)
paths.add(valueNode.getValue().getNodeCode());
if (valueNode != null) {
if (builder.length() > 0)
builder.insert(0, ":");
builder.insert(0, valueNode.getValue().getNodeCode());
}
current = current.getParent();
}
Collections.reverse(paths);
return String.join(":", paths);
return builder.toString();
}
public RootNode<NodeWrapper> unwrap() {
return root;
}
}

View File

@ -7,8 +7,9 @@ import cn.axzo.msg.center.message.service.group.NodeWrapper;
import cn.axzo.msg.center.service.enums.TodoType;
import lombok.RequiredArgsConstructor;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author yanglin
@ -20,32 +21,24 @@ class LeafNodeStats {
private final List<Todo> stats;
private final GroupTemplates groupTemplates;
int getCount(ValueNode<NodeWrapper> node, TodoType todoType) {
return getCount(Collections.singletonList(node), todoType);
}
int getCount(List<ValueNode<NodeWrapper>> nodes, TodoType todoType) {
int count = 0;
Map<TodoType, Integer> collectStat(ValueNode<NodeWrapper> node) {
HashMap<TodoType, Integer> type2Count = new HashMap<>();
for (Todo stat : stats) {
if (stat.getType() != todoType)
continue;
// 只统计叶子节点的数据, 显示列表不关心中间节点
boolean leafNodeContainsTemplate = nodes.stream()
.map(ValueNode::getValue)
.filter(NodeWrapper::isLeaf)
.anyMatch(node -> groupTemplates
.groupContainsTemplate(node.getNodeCode(), stat.getTemplateCode()));
if (leafNodeContainsTemplate)
count += stat.getCount();
boolean leafNodeContainsTemplate = groupTemplates.groupContainsTemplate(
node.getValue().getNodeCode(), stat.getTemplateCode());
if (leafNodeContainsTemplate) {
Integer prevCount = type2Count.get(stat.getType());
if (prevCount == null) prevCount = 0;
Integer currentCount = prevCount + stat.getCount();
type2Count.put(stat.getType(), currentCount);
}
}
return count;
}
int getCount(TodoType todoType) {
return stats.stream()
.filter(s -> s.getType() == todoType)
.mapToInt(Todo::getCount)
.sum();
for (TodoType type : TodoType.values()) {
if (!type2Count.containsKey(type))
type2Count.put(type, 0);
}
return type2Count;
}
}

View File

@ -58,6 +58,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import static cn.axzo.msg.center.inside.notices.utils.Queries.query;
@ -273,9 +274,10 @@ public class TodoRangeQueryService {
groupStat.setGroupCode(node.getCode());
groupStat.setGroupName(node.getName());
groupStat.setGroupIcon(node.getIcon());
Map<TodoType, Integer> type2Count = nodeStats.collectStat(valueNode);
groupStat.setStat(new Stat(
nodeStats.getCount(valueNode, TodoType.EXECUTABLE),
nodeStats.getCount(valueNode, TodoType.COPIED_TO_ME)));
type2Count.get(TodoType.EXECUTABLE),
type2Count.get(TodoType.COPIED_TO_ME)));
}
PendingMessageStatisticResponseV2 resp = new PendingMessageStatisticResponseV2();
resp.addGroupStats(stats);

View File

@ -95,6 +95,11 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spring-boot-starter</artifactId>
<version>3.7.1</version>
</dependency>
<!-- 子项目会直接继承的公共依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>

View File

@ -17,7 +17,10 @@ spring:
web:
resources:
add-mappings: false
arthas:
app-name: ${spring.application.name}
agent-id: ${ARTHAS_AGENT_ID:${spring.profiles.active}-${spring.application.name}}
tunnel-server: ${ARTHAS_TUNNEL_SERVER:ws://localhost:7777/ws}
# redis:
# #外网地址和端口 禁止使用外网地址会导致jenkins 部署 服务起不来
# #host: 123.249.44.111