From 37594729e37159420a6bbdb866deedb0213b89af Mon Sep 17 00:00:00 2001 From: OTTO <731554297@qq.com> Date: Mon, 5 Aug 2024 09:48:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=88=B6=E5=93=81=E5=BA=93=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BC=80=E5=8F=91):=20=E4=BA=A7=E5=93=81=E5=BA=93?= =?UTF-8?q?=E6=94=AF=E6=8C=81Docker=E5=88=B6=E5=93=81=E7=A7=BB=E5=85=A5?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 由于Docker镜像文件打包后一般较大,所以docker镜像移入产品库需要较长时间,若再次期间,用户由于不清楚是否已移入成功,从而进行了重复点击将会占用过高的服务器资源,所以需要对移入过程中的docker镜像进行标记 --- .../common/core/constant/CacheConstants.java | 9 ++++ .../PmsProductLibraryComponentMapper.java | 9 ++++ .../IPmsProductLibraryComponentService.java | 12 +++++ .../PmsProductLibraryAsyncServiceImpl.java | 13 +++++ ...PmsProductLibraryComponentServiceImpl.java | 48 +++++++++++++++++-- ...sProductLibraryProductRepoServiceImpl.java | 32 ++++++++++--- .../pms/PmsProductLibraryComponentMapper.xml | 5 ++ 7 files changed, 119 insertions(+), 9 deletions(-) diff --git a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java index 5ffd7bde1..60c443219 100644 --- a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java +++ b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java @@ -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前缀 */ diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/mapper/PmsProductLibraryComponentMapper.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/mapper/PmsProductLibraryComponentMapper.java index 8e623ae01..691bc26ce 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/mapper/PmsProductLibraryComponentMapper.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/mapper/PmsProductLibraryComponentMapper.java @@ -89,4 +89,13 @@ public interface PmsProductLibraryComponentMapper { * @return 制品文件列表 */ List 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); } diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/IPmsProductLibraryComponentService.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/IPmsProductLibraryComponentService.java index 596019d2a..dde038426 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/IPmsProductLibraryComponentService.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/IPmsProductLibraryComponentService.java @@ -122,4 +122,16 @@ public interface IPmsProductLibraryComponentService { List selectPmsProductLibraryComponentListByDatabase(Long repoId); PmsProductLibraryRepositories getPmsProductLibraryRepositories(Boolean isProduct, String enterpriseIdentifier, String repositoryName, String snapshotName); + + /** + * 批量锁定制品,防止重复移入 + * + * @param productRepoId 产品库Id + * @param componentIdList 制品Id列表 + */ + void lockComponentList(Long productRepoId, List componentIdList); + + void unlockComponentList(Long productRepoId, List componentIdList); + + boolean getLockComponentStatus(Long productRepoId, String assetId); } diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryAsyncServiceImpl.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryAsyncServiceImpl.java index 909ffbd8c..c8890aa82 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryAsyncServiceImpl.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryAsyncServiceImpl.java @@ -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 nexusAssetResultDataVoList, String directory) { CustomExecutorFactory.threadPoolExecutor.execute(() -> { pmsProductLibraryRepositoriesService.lockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId()); + if (nexusAssetResultDataVoList == null || nexusAssetResultDataVoList.isEmpty()) { + return; + } + List 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 nexusComponentResultDataVoList, String directory) { CustomExecutorFactory.threadPoolExecutor.execute(() -> { pmsProductLibraryRepositoriesService.lockRepository(repo.getPmsEnterpriseIdentifier(), repo.getId()); + if (nexusComponentResultDataVoList == null || nexusComponentResultDataVoList.isEmpty()) { + return; + } + List 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); } }); } diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryComponentServiceImpl.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryComponentServiceImpl.java index 4b244fe3f..8672d5c26 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryComponentServiceImpl.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryComponentServiceImpl.java @@ -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 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 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; + } } diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryProductRepoServiceImpl.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryProductRepoServiceImpl.java index 918729e10..1d5495295 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryProductRepoServiceImpl.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/productLibrary/service/impl/PmsProductLibraryProductRepoServiceImpl.java @@ -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> nexusComponentResultStateVo = assetResultDataVo.getResult(); if (nexusComponentResultStateVo.getSuccess()) { List 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 productComponentList, List nexusResultDataVoList, boolean isDocker) { + private void setNexusResultDataVoChoose(PmsProductLibraryRepositories productRepo, List productComponentList, List 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); } diff --git a/microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/PmsProductLibraryComponentMapper.xml b/microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/PmsProductLibraryComponentMapper.xml index ca21436a2..091bd686d 100644 --- a/microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/PmsProductLibraryComponentMapper.xml +++ b/microservices-modules/microservices-modules-pms/src/main/resources/mapper/pms/PmsProductLibraryComponentMapper.xml @@ -92,6 +92,11 @@ and repo_id = #{repoId} and pms_enterprise_id = #{pmsEnterpriseId} +