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

View File

@ -6,7 +6,10 @@ import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.*; 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.base.mapper.ext.ExtIssuesMapper;
import io.metersphere.commons.constants.IssueRefType; import io.metersphere.commons.constants.IssueRefType;
import io.metersphere.commons.constants.IssuesManagePlatform; 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.*;
import io.metersphere.track.issue.domain.PlatformUser; import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.jira.JiraIssueType; 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.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.issues.JiraIssueTypeRequest; import io.metersphere.track.request.issues.JiraIssueTypeRequest;
import io.metersphere.track.request.issues.PlatformIssueTypeRequest; import io.metersphere.track.request.issues.PlatformIssueTypeRequest;
@ -490,19 +492,39 @@ public class IssuesService {
LogUtil.info("测试计划-测试用例同步缺陷信息结束"); LogUtil.info("测试计划-测试用例同步缺陷信息结束");
} }
public void syncThirdPartyIssues(String projectId) { public boolean checkSync(String projectId) {
if (StringUtils.isNotBlank(projectId)) { String syncValue = getSyncKey(projectId);
String syncValue = stringRedisTemplate.opsForValue().get(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
if (StringUtils.isNotEmpty(syncValue)) { 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, stringRedisTemplate.opsForValue().set(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId,
UUID.randomUUID().toString(), 60 * 10, TimeUnit.SECONDS); 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); Project project = projectService.getProjectById(projectId);
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId); List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId);
if (CollectionUtils.isEmpty(issues)) { if (CollectionUtils.isEmpty(issues)) {
return; return true;
} }
List<IssuesDao> tapdIssues = issues.stream() List<IssuesDao> tapdIssues = issues.stream()
@ -549,8 +571,9 @@ public class IssuesService {
LogUtil.error(e); 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 MsTableHeader from "@/business/components/common/components/MsTableHeader";
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem"; import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
import IssueEdit from "@/business/components/track/issue/IssueEdit"; import IssueEdit from "@/business/components/track/issue/IssueEdit";
import {getIssuePartTemplateWithProject, getIssues, syncIssues} from "@/network/Issue"; import {checkSyncIssues, getIssuePartTemplateWithProject, getIssues, syncIssues} from "@/network/Issue";
import { import {
getCustomFieldValue, getCustomFieldValue,
getCustomTableWidth, getCustomTableWidth,
@ -370,8 +370,15 @@ export default {
return false; return false;
}, },
syncIssues() { 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(); this.getIssues();
}
}); });
} }
} }

View File

@ -2415,6 +2415,8 @@ export default {
use_third_party: "Enable Jira Issue Template", use_third_party: "Enable Jira Issue Template",
update_third_party_bugs: "Update the defects of third-party platforms", update_third_party_bugs: "Update the defects of third-party platforms",
sync_bugs: "Synchronization Issue", 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", save_before_open_comment: "Please save issue before comment",
delete_tip: "Confirm Delete Issue", delete_tip: "Confirm Delete Issue",
check_id_exist: "Check", check_id_exist: "Check",

View File

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

View File

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

View File

@ -1,10 +1,12 @@
import {post, get} from "@/common/js/ajax"; import {post, get} from "@/common/js/ajax";
import {getPageDate, parseCustomFilesForList} from "@/common/js/tableUtils"; 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 {baseGet, basePost} from "@/network/base-network";
import {getCurrentProject} from "@/network/project"; import {getCurrentProject} from "@/network/project";
import {JIRA, LOCAL} from "@/common/js/constants"; import {JIRA, LOCAL} from "@/common/js/constants";
import {getIssueTemplate} from "@/network/custom-field-template"; import {getIssueTemplate} from "@/network/custom-field-template";
import {success, warning} from "@/common/js/message";
import i18n from "@/i18n/i18n";
export function buildIssues(page) { export function buildIssues(page) {
let data = page.data; let data = page.data;
@ -99,13 +101,33 @@ export function getRelateIssues(page) {
} }
export function syncIssues(success) { export function syncIssues(success) {
let uri = 'issues/sync/'; let url = 'issues/sync/';
if (hasLicense()) { 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);
} }
}); });
} }