feat(制品库功能开发): 产品库支持Docker制品移入功能开发

由于Docker镜像文件打包后一般较大,所以docker镜像移入产品库需要较长时间,若再次期间,用户由于不清楚是否已移入成功,从而进行了重复点击将会占用过高的服务器资源,所以需要对移入过程中的docker镜像进行标记
This commit is contained in:
OTTO 2024-08-05 09:48:43 +08:00
parent eff8593029
commit 37594729e3
7 changed files with 119 additions and 9 deletions

View File

@ -176,6 +176,15 @@ public class CacheConstants
return LOCK_ENTERPRISE_IDENTIFIER_REPO_ID_KEY + enterpriseIdentifier + ":" + repoId;
}
/**
* 锁定制品库制品 Key前缀
*/
public final static String LOCK_PRODUCT_LIBRARY_ID_COMPONENT_ID_KEY = "lock_product_library_id_component_id_key:";
public static String getLockProductLibraryIdComponentIdKey(Long productRepoId, String componentId) {
return LOCK_PRODUCT_LIBRARY_ID_COMPONENT_ID_KEY + productRepoId + ":" + componentId;
}
/**
* 企业标识Redis Key前缀
*/

View File

@ -89,4 +89,13 @@ public interface PmsProductLibraryComponentMapper {
* @return 制品文件列表
*/
List<PmsProductLibraryComponent> selectPmsProductLibraryComponentUnderThePath(@Param("path") String path, @Param("repoId") Long repoId, @Param("pmsEnterpriseId") Long pmsEnterpriseId);
/**
* 通过制品标识查询制品
*
* @param repoId 制品库Id
* @param identifier 制品标识
* @return 制品
*/
PmsProductLibraryComponent selectPmsProductLibraryComponentByIdentifier(@Param("repoId") Long repoId, @Param("identifier") String identifier);
}

View File

@ -122,4 +122,16 @@ public interface IPmsProductLibraryComponentService {
List<PmsProductLibraryComponent> selectPmsProductLibraryComponentListByDatabase(Long repoId);
PmsProductLibraryRepositories getPmsProductLibraryRepositories(Boolean isProduct, String enterpriseIdentifier, String repositoryName, String snapshotName);
/**
* 批量锁定制品防止重复移入
*
* @param productRepoId 产品库Id
* @param componentIdList 制品Id列表
*/
void lockComponentList(Long productRepoId, List<String> componentIdList);
void unlockComponentList(Long productRepoId, List<String> componentIdList);
boolean getLockComponentStatus(Long productRepoId, String assetId);
}

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author OTTO
@ -73,6 +74,11 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
public void asyncAddCommonAssetToProductRepo(PmsProductLibraryRepositories productRepo, PmsProductLibraryRepositories repo, List<NexusAssetResultDataVo> nexusAssetResultDataVoList, String directory) {
CustomExecutorFactory.threadPoolExecutor.execute(() -> {
pmsProductLibraryRepositoriesService.lockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId());
if (nexusAssetResultDataVoList == null || nexusAssetResultDataVoList.isEmpty()) {
return;
}
List<String> componentIdList = nexusAssetResultDataVoList.stream().map(NexusAssetResultDataVo::getId).collect(Collectors.toList());
pmsProductLibraryComponentService.lockComponentList(productRepo.getId(), componentIdList);
try {
for (NexusAssetResultDataVo nexusAssetResultDataVo : nexusAssetResultDataVoList) {
if (StringUtils.isEmpty(nexusAssetResultDataVo.getVersion())) {
@ -99,6 +105,7 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
}
} finally {
pmsProductLibraryRepositoriesService.unlockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId());
pmsProductLibraryComponentService.unlockComponentList(productRepo.getId(), componentIdList);
}
});
}
@ -143,6 +150,11 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
public void asyncAddDockerComponentToProductRepo(PmsProductLibraryRepositories productRepo, PmsProductLibraryRepositories repo, List<NexusComponentResultDataVo> nexusComponentResultDataVoList, String directory) {
CustomExecutorFactory.threadPoolExecutor.execute(() -> {
pmsProductLibraryRepositoriesService.lockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId());
if (nexusComponentResultDataVoList == null || nexusComponentResultDataVoList.isEmpty()) {
return;
}
List<String> componentIdList = nexusComponentResultDataVoList.stream().map(NexusComponentResultDataVo::getId).collect(Collectors.toList());
pmsProductLibraryComponentService.lockComponentList(productRepo.getId(), componentIdList);
try {
// 解析docker库的映射端口
RepoAttributesVo dockerRepoAttributes = repo.getRepoAttributes();
@ -170,6 +182,7 @@ public class PmsProductLibraryAsyncServiceImpl implements IPmsProductLibraryAsyn
}
} finally {
pmsProductLibraryRepositoriesService.unlockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId());
pmsProductLibraryComponentService.unlockComponentList(productRepo.getId(), componentIdList);
}
});
}

View File

@ -2,10 +2,12 @@ package com.microservices.pms.productLibrary.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.redis.service.RedisService;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
@ -59,6 +61,8 @@ public class PmsProductLibraryComponentServiceImpl implements IPmsProductLibrary
private IPmsEnterpriseService pmsEnterpriseService;
@Autowired
private IPmsProductLibraryAsyncService pmsProductLibraryAsyncService;
@Autowired
private RedisService redisService;
/**
* 查询制品库-制品
@ -94,7 +98,7 @@ public class PmsProductLibraryComponentServiceImpl implements IPmsProductLibrary
*
* @param enterpriseIdentifier 组织标识
* @param componentSearchVo 制品库-制品
* @param isProduct
* @param isProduct 是否产品
* @return 制品库-制品
*/
@Override
@ -497,7 +501,6 @@ public class PmsProductLibraryComponentServiceImpl implements IPmsProductLibrary
}
builder.addBinaryBody(String.format("raw.asset%d", i + 1), fileBytes.getFileBytes(), ContentType.DEFAULT_BINARY, fileBytes.getFileName());
}
}
JSONObject bodyLog = toBodyLog(componentRawInputVo);
nexusRequestHelper.doRequest(NexusRequestUrl.UPLOAD_COMPONENTS(componentRawInputVo.getNexusRepoName()), builder.build(), bodyLog);
@ -581,7 +584,7 @@ public class PmsProductLibraryComponentServiceImpl implements IPmsProductLibrary
}
builder.addBinaryBody("pypi.asset1", fileBytes.getFileBytes(), ContentType.DEFAULT_BINARY, fileBytes.getFileName());
JSONObject bodyLog = toBodyLog(componentInputVo);
JSONObject res = null;
JSONObject res;
try {
res = nexusRequestHelper.doRequest(NexusRequestUrl.UPLOAD_COMPONENTS(componentInputVo.getNexusRepoName()), builder.build(), bodyLog);
} catch (Exception e) {
@ -649,4 +652,43 @@ public class PmsProductLibraryComponentServiceImpl implements IPmsProductLibrary
}
return true;
}
@Override
public void lockComponentList(Long productRepoId, List<String> componentIdList) {
for (String componentId : componentIdList) {
String lockComponentKey = CacheConstants.getLockProductLibraryIdComponentIdKey(productRepoId, componentId);
if (redisService.hasKey(lockComponentKey)) {
int count = redisService.getCacheObject(lockComponentKey);
redisService.setCacheObject(lockComponentKey, ++count);
} else {
redisService.setCacheObject(lockComponentKey, 1);
}
}
}
@Override
public void unlockComponentList(Long productRepoId, List<String> componentIdList) {
for (String componentId : componentIdList) {
String lockComponentKey = CacheConstants.getLockProductLibraryIdComponentIdKey(productRepoId, componentId);
if (redisService.hasKey(lockComponentKey)) {
int count = redisService.getCacheObject(lockComponentKey);
count--;
if (count <= 0) {
redisService.deleteObject(lockComponentKey);
} else {
redisService.setCacheObject(lockComponentKey, count);
}
}
}
}
@Override
public boolean getLockComponentStatus(Long productRepoId, String componentId) {
String lockComponentKey = CacheConstants.getLockProductLibraryIdComponentIdKey(productRepoId, componentId);
if (redisService.hasKey(lockComponentKey)) {
int count = redisService.getCacheObject(lockComponentKey);
return count > 0;
}
return false;
}
}

View File

@ -142,7 +142,15 @@ public class PmsProductLibraryProductRepoServiceImpl implements IPmsProductLibra
if (nexusAssetResultVo == null || nexusAssetResultVo.getResult() == null || !nexusAssetResultVo.getResult().getSuccess()) {
throw new ServiceException("该制品不存在(制品库[%s],制品Id[%s])", commonAssetAddToProductRepoVo.getRepoName(), assetId);
} else {
nexusAssetResultDataVoList.add(nexusAssetResultVo.getResult().getData());
NexusAssetResultDataVo data = nexusAssetResultVo.getResult().getData();
if (pmsProductLibraryComponentService.getLockComponentStatus(productRepo.getId(), assetId)) {
throw new ServiceException("制品锁定中,无法被移入产品库(制品名称[%s],产品库名称[%s])", data.getName(), productRepo.getName());
}
PmsProductLibraryComponent pmsProductLibraryComponent = pmsProductLibraryComponentMapper.selectPmsProductLibraryComponentByIdentifier(productRepo.getId(), assetId);
if (pmsProductLibraryComponent != null) {
throw new ServiceException("制品已被移入产品库中,无法重复移入(制品名称[%s],产品库名称[%s])", data.getName(), productRepo.getName());
}
nexusAssetResultDataVoList.add(data);
}
}
pmsProductLibraryAsyncService.asyncAddCommonAssetToProductRepo(productRepo, repo, nexusAssetResultDataVoList, commonAssetAddToProductRepoVo.getDirectory());
@ -181,7 +189,7 @@ public class PmsProductLibraryProductRepoServiceImpl implements IPmsProductLibra
}
}
setNexusResultDataVoChoose(productComponentList, keyNexusResultDataVoList, true);
setNexusResultDataVoChoose(productRepo, productComponentList, keyNexusResultDataVoList, true);
setNexusResultDataVoPath(repo, keyNexusResultDataVoList);
return buildDockerResultVo(keyNexusResultDataVoList);
} else {
@ -191,7 +199,7 @@ public class PmsProductLibraryProductRepoServiceImpl implements IPmsProductLibra
NexusComponentResultStateVo<List<NexusResultDataVo>> nexusComponentResultStateVo = assetResultDataVo.getResult();
if (nexusComponentResultStateVo.getSuccess()) {
List<NexusResultDataVo> nexusResultDataVoList = nexusComponentResultStateVo.getData();
setNexusResultDataVoChoose(productComponentList, nexusResultDataVoList, false);
setNexusResultDataVoChoose(productRepo, productComponentList, nexusResultDataVoList, false);
setNexusResultDataVoPath(repo, nexusResultDataVoList);
// 当制品库为Maven时需排除自动生成的制品数据
if (ProductLibraryRepositoriesFormatEnum.MAVEN.getKey().equals(repo.getFormat())) {
@ -230,18 +238,30 @@ public class PmsProductLibraryProductRepoServiceImpl implements IPmsProductLibra
if (nexusAssetResultVo == null || nexusAssetResultVo.getResult() == null || !nexusAssetResultVo.getResult().getSuccess()) {
throw new ServiceException("该制品不存在(制品库[%s],制品Id[%s])", dockerComponentAddToProductRepoVo.getRepoName(), componentId);
} else {
nexusComponentResultDataVoList.add(nexusAssetResultVo.getResult().getData());
NexusComponentResultDataVo data = nexusAssetResultVo.getResult().getData();
if (pmsProductLibraryComponentService.getLockComponentStatus(productRepo.getId(), componentId)) {
throw new ServiceException("制品锁定中,无法被移入产品库(制品名称[%s],产品库名称[%s])", data.getName(), productRepo.getName());
}
PmsProductLibraryComponent pmsProductLibraryComponent = pmsProductLibraryComponentMapper.selectPmsProductLibraryComponentByIdentifier(productRepo.getId(), componentId);
if (pmsProductLibraryComponent != null) {
throw new ServiceException("制品已被移入产品库中,无法重复移入(制品名称[%s],产品库名称[%s])", data.getName(), productRepo.getName());
}
nexusComponentResultDataVoList.add(data);
}
}
pmsProductLibraryAsyncService.asyncAddDockerComponentToProductRepo(productRepo, repo, nexusComponentResultDataVoList, dockerComponentAddToProductRepoVo.getDirectory());
return true;
}
private void setNexusResultDataVoChoose(List<PmsProductLibraryComponent> productComponentList, List<NexusResultDataVo> nexusResultDataVoList, boolean isDocker) {
private void setNexusResultDataVoChoose(PmsProductLibraryRepositories productRepo, List<PmsProductLibraryComponent> productComponentList, List<NexusResultDataVo> nexusResultDataVoList, boolean isDocker) {
for (PmsProductLibraryComponent component : productComponentList) {
nexusResultDataVoList.forEach(x -> {
if (isDocker && StringUtils.isNotEmpty(x.getComponentId()) && x.getComponentId().equals(component.getIdentifier())) {
if (pmsProductLibraryComponentService.getLockComponentStatus(productRepo.getId(), x.getComponentId())) {
x.setIsChoose(true);
} else if (isDocker && StringUtils.isNotEmpty(x.getComponentId())) {
if (x.getComponentId().equals(component.getIdentifier())) {
x.setIsChoose(true);
}
} else if (StringUtils.isNotEmpty(x.getAssetId()) && x.getAssetId().equals(component.getIdentifier())) {
x.setIsChoose(true);
}

View File

@ -92,6 +92,11 @@
and repo_id = #{repoId}
and pms_enterprise_id = #{pmsEnterpriseId}
</select>
<select id="selectPmsProductLibraryComponentByIdentifier" resultMap="PmsProductLibraryComponentResult">
<include refid="selectPmsProductLibraryComponentVo"/>
where repo_id = #{repoId}
and identifier = #{identifier}
</select>
<insert id="insertPmsProductLibraryComponent" parameterType="PmsProductLibraryComponent" useGeneratedKeys="true"
keyProperty="id">