fix(测试跟踪): 优化同步第三方平台缺陷缺少并行限制

--bug=1014127 --user=陈建星 【测试跟踪】同步第三方平台缺陷缺少并行限制 https://www.tapd.cn/55049933/s/1188601
This commit is contained in:
chenjianxing 2022-06-22 16:58:58 +08:00 committed by jianxing
parent 6857cb8c71
commit 1a1dff7814
7 changed files with 84 additions and 22 deletions

View File

@ -18,7 +18,6 @@ import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.jira.JiraIssueType;
import io.metersphere.track.issue.domain.jira.JiraTransitionsResponse;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.issues.JiraIssueTypeRequest;
import io.metersphere.track.request.issues.PlatformIssueTypeRequest;
@ -139,8 +138,13 @@ public class IssuesController {
}
@GetMapping("/sync/{projectId}")
public void getPlatformIssue(@PathVariable String projectId) {
issuesService.syncThirdPartyIssues(projectId);
public boolean getPlatformIssue(@PathVariable String projectId) {
return issuesService.syncThirdPartyIssues(projectId);
}
@GetMapping("/sync/check/{projectId}")
public boolean checkSync(@PathVariable String projectId) {
return issuesService.checkSync(projectId);
}
@PostMapping("/change/status")

View File

@ -6,7 +6,10 @@ import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.IssueFollowMapper;
import io.metersphere.base.mapper.IssuesMapper;
import io.metersphere.base.mapper.TestCaseIssuesMapper;
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
import io.metersphere.commons.constants.IssueRefType;
import io.metersphere.commons.constants.IssuesManagePlatform;
@ -26,7 +29,6 @@ import io.metersphere.track.dto.*;
import io.metersphere.track.issue.*;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.jira.JiraIssueType;
import io.metersphere.track.issue.domain.jira.JiraTransitionsResponse;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.issues.JiraIssueTypeRequest;
import io.metersphere.track.request.issues.PlatformIssueTypeRequest;
@ -490,19 +492,39 @@ public class IssuesService {
LogUtil.info("测试计划-测试用例同步缺陷信息结束");
}
public void syncThirdPartyIssues(String projectId) {
if (StringUtils.isNotBlank(projectId)) {
String syncValue = stringRedisTemplate.opsForValue().get(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
public boolean checkSync(String projectId) {
String syncValue = getSyncKey(projectId);
if (StringUtils.isNotEmpty(syncValue)) {
MSException.throwException("当前项目正在同步缺陷, 请稍等");
return false;
}
return true;
}
public String getSyncKey(String projectId) {
return stringRedisTemplate.opsForValue().get(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
}
public void setSyncKey(String projectId) {
stringRedisTemplate.opsForValue().set(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId,
UUID.randomUUID().toString(), 60 * 10, TimeUnit.SECONDS);
}
public void deleteSyncKey(String projectId) {
stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
}
public boolean syncThirdPartyIssues(String projectId) {
if (StringUtils.isNotBlank(projectId)) {
String syncValue = getSyncKey(projectId);
if (StringUtils.isNotEmpty(syncValue)) {
return false;
}
setSyncKey(projectId);
Project project = projectService.getProjectById(projectId);
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId);
if (CollectionUtils.isEmpty(issues)) {
return;
return true;
}
List<IssuesDao> tapdIssues = issues.stream()
@ -549,8 +571,9 @@ public class IssuesService {
LogUtil.error(e);
}
}
stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
deleteSyncKey(projectId);
}
return true;
}

View File

@ -182,7 +182,7 @@ import {
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
import IssueEdit from "@/business/components/track/issue/IssueEdit";
import {getIssuePartTemplateWithProject, getIssues, syncIssues} from "@/network/Issue";
import {checkSyncIssues, getIssuePartTemplateWithProject, getIssues, syncIssues} from "@/network/Issue";
import {
getCustomFieldValue,
getCustomTableWidth,
@ -370,8 +370,15 @@ export default {
return false;
},
syncIssues() {
this.page.result = syncIssues(() => {
this.page.result.loading = true;
syncIssues((data) => {
if (data === false) {
checkSyncIssues(this.page.result);
} else {
this.$success(this.$t('test_track.issue.sync_complete'));
this.page.result.loading = false;
this.getIssues();
}
});
}
}

View File

@ -2415,6 +2415,8 @@ export default {
use_third_party: "Enable Jira Issue Template",
update_third_party_bugs: "Update the defects of third-party platforms",
sync_bugs: "Synchronization Issue",
sync_complete: "Synchronization complete",
issue_sync_tip: "The current project is synchronizing defects, please wait!",
save_before_open_comment: "Please save issue before comment",
delete_tip: "Confirm Delete Issue",
check_id_exist: "Check",

View File

@ -2425,6 +2425,8 @@ export default {
use_third_party: "使用 Jira 缺陷模板",
update_third_party_bugs: "更新第三方平台的缺陷",
sync_bugs: "同步缺陷",
sync_complete: "同步完成",
issue_sync_tip: "当前项目正在同步缺陷, 请稍等!",
save_before_open_comment: "请先保存缺陷再添加评论",
delete_tip: "确认删除缺陷:",
check_id_exist: "检查",
@ -2436,7 +2438,7 @@ export default {
tapd_status_verified: "已验证",
tapd_status_closed: "已关闭",
tapd_status_resolved: "已解决",
please_choose_platform_status: "请选择平台状态",
please_choose_platform_status: "请选择平台状态"
},
report: {
name: "测试计划报告",

View File

@ -2419,6 +2419,8 @@ export default {
use_third_party: "使用 Jira 缺陷模板",
update_third_party_bugs: "更新第三方平臺的缺陷",
sync_bugs: "同步缺陷",
sync_complete: "同步完成",
issue_sync_tip: "當前項目正在同步缺陷, 請稍等!",
save_before_open_comment: "請先保存缺陷再添加評論",
delete_tip: "確認刪除缺陷:",
check_id_exist: "檢查",

View File

@ -1,10 +1,12 @@
import {post, get} from "@/common/js/ajax";
import {getPageDate, parseCustomFilesForList} from "@/common/js/tableUtils";
import {getCurrentProjectID, getCurrentWorkspaceId, hasLicense} from "@/common/js/utils";
import {getCurrentProjectID, getCurrentWorkspaceId, getUUID, hasLicense} from "@/common/js/utils";
import {baseGet, basePost} from "@/network/base-network";
import {getCurrentProject} from "@/network/project";
import {JIRA, LOCAL} from "@/common/js/constants";
import {getIssueTemplate} from "@/network/custom-field-template";
import {success, warning} from "@/common/js/message";
import i18n from "@/i18n/i18n";
export function buildIssues(page) {
let data = page.data;
@ -99,13 +101,33 @@ export function getRelateIssues(page) {
}
export function syncIssues(success) {
let uri = 'issues/sync/';
let url = 'issues/sync/';
if (hasLicense()) {
uri = 'xpack/issue/sync/';
url = 'xpack/issue/sync/';
}
// 浏览器默认策略请求同一个url可能导致 stalled 时间过长加个uuid防止请求阻塞
url = url + getCurrentProjectID() + "?stamp=" + getUUID();
return baseGet(url, success);
}
// 轮询同步状态
export function checkSyncIssues(result, isNotFirst) {
let url = 'issues/sync/check/' + getCurrentProjectID() + "?stamp=" + getUUID();
return baseGet(url, (data) => {
if (data === false) {
if (result.loading === true) {
if (!isNotFirst) {
// 第一次才提示
warning(i18n.t('test_track.issue.issue_sync_tip'));
}
setTimeout(() => checkSyncIssues(result, true), 1000);
}
} else {
if (result.loading === true) {
success(i18n.t('test_track.issue.sync_complete'));
result.loading = false;
}
return get(uri + getCurrentProjectID(), (response) => {
if (success) {
success(response);
}
});
}