Compare commits

...

13 Commits

Author SHA1 Message Date
otto 385dd55c25 Merge pull request '优化获取项目列表接口性能' (#1178) from otto/microservices:master into master 2026-06-22 14:20:58 +08:00
otto 76f865624e fix(超算专区): 优化获取项目列表接口性能 2026-06-22 14:20:58 +08:00
otto 9d1d5527c8 Merge branch 'master' of code.gitlink.org.cn:Gitlink/microservices 2026-06-18 14:24:51 +08:00
otto 47e24de4fb Merge pull request 'fix(超算专区): 修复专区栏目需要删除两次才能删除的问题' (#1177) from otto/microservices:master into master 2026-06-18 14:24:28 +08:00
otto 7a44a2113d fix(超算专区): 修复专区栏目需要删除两次才能删除的问题 2026-06-18 14:24:08 +08:00
otto 1bf9522d8f Merge pull request 'fix(超算专区): 修复当专区存在审核未通过的相同文章名称时,会导致异常报错' (#1176) from otto/microservices:master into master 2026-06-18 10:44:40 +08:00
otto 5aa499f4de fix(超算专区): 修复当专区存在审核未通过的相同文章名称时,会导致异常报错 2026-06-18 10:42:07 +08:00
otto 35d5b1318e Merge pull request 'fix(超算专区): 修复专区栏目需要删除两次才能删除的问题' (#1175) from otto/microservices:master into master 2026-06-18 09:36:14 +08:00
otto 4ccc743bd2 Merge branch 'master' of code.gitlink.org.cn:Gitlink/microservices 2026-06-18 09:30:42 +08:00
otto 84f624fdb7 fix(超算专区): 修复专区栏目需要删除两次才能删除的问题 2026-06-18 09:27:33 +08:00
otto e43fb391fa feat(超算专区): 优化专区项目并发初始化逻辑 2026-06-16 17:19:06 +08:00
otto fc9e511aa0 Merge pull request '置顶项目信息新增url字段' (#1174) from amypeng/microservices:master into master 2026-06-16 09:28:53 +08:00
otto d2d2f7368c Merge pull request '超算置顶新闻查询条件修改' (#1173) from amypeng/microservices:master into master 2026-06-15 16:50:36 +08:00
4 changed files with 75 additions and 47 deletions

View File

@ -1504,6 +1504,17 @@ public class CmsDocServiceImpl implements ICmsDocService {
cmsAsyncService.updateCmsPublishDataByGitLink(cmsProject, cmsDoc, branchName);
}
private int deleteCmsDir(CmsProject cmsProject, CmsDoc cmsDir) {
if (!isNoAuditRequired(cmsDir.getDeptId()) || tokenService.hasDeptPerms(cmsDir.getDeptId(), UserConstants.CMS_PERMS_DOCS_AUDIT)) {
boolean deleteResult = cmsAsyncService.deleteCmsDocForGitLink(cmsDir, cmsProject, CmsConstants.BRANCH_MASTER);
if (deleteResult) {
return cmsDocMapper.deleteCmsDocById(cmsDir.getId());
}
throw new ServiceException("栏目删除失败");
}
throw new ServiceException("无权限删除栏目");
}
@Override
public int deleteCmsDocById(Long id) {
CmsDoc cmsDoc = cmsDocMapper.selectCmsDocById(id);
@ -1513,6 +1524,9 @@ public class CmsDocServiceImpl implements ICmsDocService {
checkCmsLockStatus(cmsDoc.getDeptId());
//2获取专区项目
CmsProject cmsProject = cmsProjectService.selectCmsProjectByDeptId(cmsDoc.getDeptId());
if (cmsDoc.getIsDir()) {
return deleteCmsDir(cmsProject, cmsDoc);
}
//删除待审核审核未通过文章删除临时分支拒绝合并请求
if (DocAuditStatus.TO_BE_AUDIT.getAuditCode().equals(cmsDoc.getAuditStatus())) {

View File

@ -229,6 +229,7 @@
<include refid="selectCmsDocVo"/>
<where>
and name = #{name}
and audit_status != 0
and dept_id = #{deptId}
<choose>
<when test="dirName != null">

View File

@ -170,11 +170,11 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
* Nthreads =Ncpu*Ucpu*(1+W/C)
*/
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2
5
, 10
, 10
, TimeUnit.SECONDS
, new ArrayBlockingQueue<>(100)
, new ArrayBlockingQueue<>(10000)
, Executors.defaultThreadFactory()
, (r, executor) -> {
throw new ServiceException("【%s】目前创建的人太多了请稍后再试", DateUtils.getNowDate());
@ -485,11 +485,6 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
List<ZoneProject> zoneProjectList = zoneProjectMapper.selectZoneProjectList(zoneProjectSearchVo);
for (ZoneProject zoneProject : zoneProjectList) {
setProjectGitlinkInfoCache(zoneProject);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
logger.error("初始化gitlink项目统计的定时任务延时被中断");
}
}
}
}
@ -541,23 +536,26 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
@Override
public List<JSONObject> getGitlinkProjectsDetail(List<String> gitLinkProjectIdList) {
int queryCount = gitLinkProjectIdList.size() / 50 + 1;
int total = gitLinkProjectIdList.size();
if (total == 0) {
return new ArrayList<>();
}
// 向上取整分片修复原 size/50+1 在整除时多出一个空分片会发出一次 ids 为空的请求
int queryCount = (total + 49) / 50;
CountDownLatch countDownLatch = new CountDownLatch(queryCount);
List<JSONObject> gitLinkProjectList = new ArrayList<>();
// 使用线程安全的 ConcurrentLinkedQueue 收集结果修复原 ArrayList 在多线程并发 addAll 下丢数据/越界的隐患
ConcurrentLinkedQueue<JSONObject> gitLinkProjectQueue = new ConcurrentLinkedQueue<>();
for (int i = 0; i < queryCount; i++) {
int finalI = i;
threadPoolExecutor.execute(() -> {
try {
int pageMaxCount = (finalI + 1) * 50;
if (pageMaxCount >= gitLinkProjectIdList.size()) {
pageMaxCount = gitLinkProjectIdList.size();
}
int pageMaxCount = Math.min((finalI + 1) * 50, total);
List<String> tmpIdList = gitLinkProjectIdList.subList(finalI * 50, pageMaxCount);
JSONObject result = gitLinkRequestHelper.doGet(
ZoneGitLinkRequestUrl.PROJECTS("?ids=" + String.join(ZoneConstants.ARRAY_SPLIT_SYMBOLS, tmpIdList))
);
gitLinkProjectList.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
gitLinkProjectQueue.addAll(result.getList(ZoneConstants.GITLINK_RESPONSE_PROJECTS_KEY, JSONObject.class));
} catch (Exception e) {
logger.error("异步批量获取项目详细信息失败:{}", e.getMessage());
} finally {
@ -571,7 +569,7 @@ public class ZoneAsyncServiceImpl implements IZoneAsyncService {
logger.error("根据gitlinkProjectId调用Gitlink接口批量获取项目详细信息失败{}", e.getMessage());
throw new ServiceException("获取平台项目详细信息失败");
}
return gitLinkProjectList;
return new ArrayList<>(gitLinkProjectQueue);
}
private Double calcProjectScore(ZoneProject zoneProject, String startDate, String endDate) {

View File

@ -128,44 +128,51 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
@Override
public List<ZoneProjectDataVo> toZoneProjectDataVoList(List<ZoneProject> zoneProjectList) {
List<ZoneProjectDataVo> zoneProjectDataVoList = new ArrayList<>();
if (zoneProjectList.isEmpty()) {
return new ArrayList<>();
}
// 原方案为遍历项目聚合再逐一从GitLink获取对应项目详情此方案延时过高调整为根据项目Id批量获取GitLink项目信息
List<String> gitLinkProjectIdList = zoneProjectList
.stream()
.map(x -> String.valueOf(x.getGitlinkProjectId()))
.collect(Collectors.toList());
List<JSONObject> gitLinkProjectList = zoneAsyncService.getGitlinkProjectsDetail(gitLinkProjectIdList);
List<String> resultGitLinkProjectIdList = gitLinkProjectList
.stream()
.map(x -> x.getString("id"))
.collect(Collectors.toList());
//检查查询的GitLink项目Id列表和需查询的项目Id列表是否一致不一致需要考虑是否该项目在GitLink中设置为私有或者删除了此时需要清理该项目
gitLinkProjectIdList.removeAll(resultGitLinkProjectIdList);
if (!gitLinkProjectIdList.isEmpty()) {
for (String gitLinkProjectId : gitLinkProjectIdList) {
Long projectId = zoneProjectList
.stream()
.filter(x -> gitLinkProjectId.equals(String.valueOf(x.getGitlinkProjectId())))
.map(ZoneProject::getId)
.findFirst().orElse(null);
if (projectId == null) {
throw new ServiceException("该GitLink项目对应的项目聚合不存在(GitLink项目Id[" + gitLinkProjectId + "])");
}
logger.info("GitLink中未查找到对应项目(GitLink项目Id为{}),对该项目进行删除(项目Id为{})"
, gitLinkProjectId
, projectId);
deleteZoneProjectById(projectId);
zoneProjectList = zoneProjectList.stream().filter(x -> !x.getId().equals(projectId)).collect(Collectors.toList());
}
// 性能优化整页 zoneId 恒定getGitlinkProjectKeys(每次2次DB) 与字典缓存(每次1次Redis) 提到循环外整页只查一次
String[] projectKeys = getGitlinkProjectKeys(zoneProjectList.get(0).getZoneId());
List<SysDictData> sysDictDataList = DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES);
// 性能优化构建索引Map将原本逐项 O(N²) stream 过滤改为 O(1) 查表
Map<Long, JSONObject> gitLinkByProjectId = new HashMap<>(gitLinkProjectList.size() * 2);
Set<String> returnedGitLinkIds = new HashSet<>(gitLinkProjectList.size() * 2);
for (JSONObject jp : gitLinkProjectList) {
gitLinkByProjectId.put(jp.getLong("id"), jp);
returnedGitLinkIds.add(jp.getString("id"));
}
//检查查询的GitLink项目Id列表和需查询的项目Id列表是否一致不一致需要考虑是否该项目在GitLink中设置为私有或者删除了此时需要清理该项目
//直接遍历zoneProject按gitlinkId查Set替代原本逐项的stream过滤删除时仅记录id并在富化循环中跳过不原地修改zoneProjectList以免影响外层PageHelper的分页total统计
Set<Long> removedProjectIds = new HashSet<>();
for (ZoneProject zp : zoneProjectList) {
if (returnedGitLinkIds.contains(String.valueOf(zp.getGitlinkProjectId()))) {
continue;
}
if (removedProjectIds.contains(zp.getId())) {
continue;
}
logger.info("GitLink中未查找到对应项目(GitLink项目Id为{}),对该项目进行删除(项目Id为{})"
, zp.getGitlinkProjectId()
, zp.getId());
deleteZoneProjectById(zp.getId());
removedProjectIds.add(zp.getId());
}
List<ZoneProjectDataVo> zoneProjectDataVoList = new ArrayList<>(zoneProjectList.size());
for (ZoneProject zoneProject : zoneProjectList) {
JSONObject gitLinkProject = gitLinkProjectList
.stream()
.filter(x -> zoneProject.getGitlinkProjectId().equals(x.getLong("id")))
.findFirst()
.orElse(null);
if (removedProjectIds.contains(zoneProject.getId())) {
continue;
}
JSONObject gitLinkProject = gitLinkByProjectId.get(zoneProject.getGitlinkProjectId());
if (gitLinkProject == null) {
throw new ServiceException("该项目聚合对应的GitLink项目不存在(项目Id[" + zoneProject.getId() + "])");
}
@ -179,7 +186,7 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
zoneProjectMapper.updateZoneProject(zoneProject);
}
}
zoneProjectDataVoList.add(zoneProjectToZoneProjectDataVo(zoneProject, gitLinkProject));
zoneProjectDataVoList.add(zoneProjectToZoneProjectDataVo(zoneProject, gitLinkProject, projectKeys, sysDictDataList));
}
return zoneProjectDataVoList;
}
@ -234,6 +241,16 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
}
private ZoneProjectDataVo zoneProjectToZoneProjectDataVo(ZoneProject zoneProject, JSONObject gitLinkProject) {
// 单项查询路径 selectZoneProjectDataById在此计算 keys 与字典再委托给 4 参重载
return zoneProjectToZoneProjectDataVo(
zoneProject,
gitLinkProject,
getGitlinkProjectKeys(zoneProject.getZoneId()),
DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES));
}
private ZoneProjectDataVo zoneProjectToZoneProjectDataVo(ZoneProject zoneProject, JSONObject gitLinkProject,
String[] projectKeys, List<SysDictData> sysDictDataList) {
//每次从GitLink查询项目时自动更新项目名称和项目标识
updateProjectNameAndFullName(gitLinkProject, zoneProject);
ZoneProjectDataVo zoneProjectDataVo = zoneProject.toZoneProjectDataVo();
@ -262,9 +279,7 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
projectPropertiesVo.put("description", description);
projectKeyName.put("description", "项目简介");
String[] projectKeys = getGitlinkProjectKeys(zoneProject.getZoneId());
//当专区设置的项目需展示的Key时通过Key获取值否则默认获取相关值
List<SysDictData> sysDictDataList = DictUtils.getDictCache(CacheConstants.SYS_DICT_GITLINK_PROJECT_PROPERTIES);
//当专区设置的项目需展示的Key时通过Key获取值否则默认获取相关值projectKeys sysDictDataList 已由调用方按页预算并传入避免逐项查询
if (sysDictDataList != null) {
for (String projectKey : projectKeys) {
SysDictData sysDictData = sysDictDataList.stream().filter(x -> projectKey.equals(x.getDictValue())).findFirst().orElse(null);