feat:(REQ-2699) 修改项目产品的缓存结构和定时job去刷新项目的产品
This commit is contained in:
parent
cba58c9c63
commit
38e711217c
@ -32,6 +32,7 @@ import cn.axzo.tyr.server.job.CacheProductPermissionJob;
|
||||
import cn.axzo.tyr.server.job.CacheRoleFeatureResourceJob;
|
||||
import cn.axzo.tyr.server.job.CacheRolePermissionJob;
|
||||
import cn.axzo.tyr.server.job.CacheSaasFeatureJob;
|
||||
import cn.axzo.tyr.server.job.CacheWorkspaceProductJob;
|
||||
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||
@ -169,6 +170,8 @@ public class PrivateController {
|
||||
private SaasRoleUserRelationService saasRoleUserRelationService;
|
||||
@Autowired
|
||||
private ProductModuleDao productModuleDao;
|
||||
@Autowired
|
||||
private CacheWorkspaceProductJob cacheWorkspaceProductJob;
|
||||
|
||||
/**
|
||||
* 统一层级的roleGroup按照id升序,sort从1递增
|
||||
@ -623,12 +626,24 @@ public class PrivateController {
|
||||
return featureCodeUtil.resolveFeatureCode(request.getFeatureCodes());
|
||||
}
|
||||
|
||||
@PostMapping("/api/private/workspaceProduct/store")
|
||||
public Object storeWorkspaceProduct(@RequestBody ProductSearchListReq request) throws Exception {
|
||||
@PostMapping("/api/private/productPermission/store")
|
||||
public Object storeProductPermission(@RequestBody ProductSearchListReq request) throws Exception {
|
||||
cacheProductPermissionJob.execute(JSON.toJSONString(request));
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@PostMapping("/api/private/workspaceProduct/store")
|
||||
public Object storeWorkspaceProduct(@RequestBody WorkspaceProductService.StoreWorkspaceProductParam request) throws Exception {
|
||||
workspaceProductService.storeWorkspaceProduct(request);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@PostMapping("/api/private/workspaceProduct/job")
|
||||
public Object storeWorkspaceProductJob() throws Exception {
|
||||
cacheWorkspaceProductJob.execute(null);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@PostMapping("/api/private/workspaceProduct/list")
|
||||
public Object listWorkspaceProduct(@RequestBody WorkspaceProductService.WorkspaceProductParam request) {
|
||||
return workspaceProductService.listWorkspaceProductCached(request);
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
package cn.axzo.tyr.server.job;
|
||||
|
||||
import cn.axzo.thrones.client.saas.ServicePkgClient;
|
||||
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
|
||||
import cn.axzo.thrones.client.saas.entity.servicepkg.ServicePkgDetailRes;
|
||||
import cn.axzo.tyr.server.service.WorkspaceProductService;
|
||||
import cn.axzo.tyr.server.utils.RpcInternalUtil;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CacheWorkspaceProductJob extends IJobHandler {
|
||||
|
||||
@Autowired
|
||||
private WorkspaceProductService workspaceProductService;
|
||||
@Autowired
|
||||
private ServicePkgClient servicePkgClient;
|
||||
|
||||
@Override
|
||||
@XxlJob("CacheWorkspaceProductJob")
|
||||
public ReturnT<String> execute(String s) throws Exception {
|
||||
|
||||
log.info("start CacheWorkspaceProductJob, s:{}", s);
|
||||
|
||||
// 全量更新所有项目的产品数量比较大,所以这里只从缓存中的项目去更新产品
|
||||
Map<Long, Set<Long>> allWorkspaceProducts = workspaceProductService.listAllWorkspaceProductCached();
|
||||
|
||||
Set<Long> workspaceIds = allWorkspaceProducts.keySet();
|
||||
|
||||
if (CollectionUtils.isEmpty(workspaceIds)) {
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
List<ServicePkgDetailRes> servicePkgDetailRes = RpcInternalUtil.rpcListProcessor(() -> servicePkgClient.getServicePkgDetailBySpaceId(workspaceIds),
|
||||
"查询项目的产品", workspaceIds).getData();
|
||||
|
||||
List<WorkspaceProductService.WorkspaceProductDTO> workspaceProducts = servicePkgDetailRes.stream()
|
||||
.map(e -> WorkspaceProductService.WorkspaceProductDTO.builder()
|
||||
.workspaceId(e.getSpaceId())
|
||||
.productIds(Optional.ofNullable(e.getProducts())
|
||||
.map(products -> products.stream()
|
||||
.map(ServicePkgProduct::getProductId)
|
||||
.collect(Collectors.toSet()))
|
||||
.orElse(null))
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
WorkspaceProductService.StoreWorkspaceProductParam storeWorkspaceProductParam = WorkspaceProductService.StoreWorkspaceProductParam.builder()
|
||||
.workspaceProducts(workspaceProducts)
|
||||
.build();
|
||||
workspaceProductService.storeWorkspaceProduct(storeWorkspaceProductParam);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface WorkspaceProductService {
|
||||
@ -43,6 +44,8 @@ public interface WorkspaceProductService {
|
||||
*/
|
||||
List<WorkspaceProductFeatureSource> listWorkspaceProductFeatureResourceCached(ListWorkspaceProductFeatureSourceCacheParam param);
|
||||
|
||||
Map<Long, Set<Long>> listAllWorkspaceProductCached();
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
||||
@ -2,7 +2,7 @@ package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.foundation.exception.Axssert;
|
||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.pokonyan.config.redis.RedisUtil;
|
||||
import cn.axzo.pokonyan.config.redis.RedisClient;
|
||||
import cn.axzo.thrones.client.saas.ServicePkgClient;
|
||||
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
|
||||
import cn.axzo.thrones.client.saas.entity.servicepkg.ServicePkgDetailRes;
|
||||
@ -22,13 +22,9 @@ import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.data.redis.core.SessionCallback;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -37,6 +33,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@ -67,7 +64,7 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
||||
@Value("${workspace.product.expire.minutes:14}")
|
||||
private Long expireInMinutes;
|
||||
|
||||
private static final String WORKSPACE_PRODUCT_KEY = "workspace:product:%s";
|
||||
private static final String WORKSPACE_PRODUCT_KEY = "workspace:product";
|
||||
|
||||
@Override
|
||||
public List<WorkspaceProduct> listWorkspaceProduct(WorkspaceProductParam param) {
|
||||
@ -184,35 +181,28 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
||||
public void storeWorkspaceProduct(StoreWorkspaceProductParam param) {
|
||||
Axssert.checkNotEmpty(param.getWorkspaceProducts(), REDIS_PRODUCT_NOT_NULL);
|
||||
|
||||
|
||||
redisTemplate.executePipelined(new SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object execute(RedisOperations operations) throws DataAccessException {
|
||||
|
||||
for (WorkspaceProductDTO workspaceProduct : param.getWorkspaceProducts()) {
|
||||
String redisKey = getKey(workspaceProduct.getWorkspaceId());
|
||||
RedisUtil.StringValueOps.setEx(redisKey, JSON.toJSONString(workspaceProduct.getProductIds()),
|
||||
expireInMinutes, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<String, String> redisValues = param.getWorkspaceProducts().stream()
|
||||
.collect(Collectors.toMap(e -> e.getWorkspaceId().toString(), e -> Optional.ofNullable(e.getProductIds())
|
||||
.map(JSON::toJSONString)
|
||||
.orElseGet(() -> JSON.toJSONString(Sets.newHashSet()))));
|
||||
String redisKey = getKey();
|
||||
RedisClient.HashOps.hPutAll(redisKey, redisValues);
|
||||
redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES);
|
||||
log.info("succeed to workspace product: redisKey:{} value:{}", redisKey, redisValues);
|
||||
}
|
||||
|
||||
private Map<Long, Set<Long>> listWorkspaceProduct(ListWorkspaceProductParam param) {
|
||||
Axssert.checkNotEmpty(param.getWorkspaceIds(), WORKSPACE_ID_NOT_NULL);
|
||||
|
||||
List<String> redisKeys = param.getWorkspaceIds().stream()
|
||||
.map(this::getKey)
|
||||
.collect(Collectors.toList());
|
||||
List<String> redisValues = redisTemplate.opsForValue().multiGet(redisKeys);
|
||||
List<Object> redisValues = RedisClient.HashOps.hMultiGet(getKey(), param.getWorkspaceIds().stream()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return Streams.zip(param.getWorkspaceIds().stream(),
|
||||
redisValues.stream(),
|
||||
(workspaceId, redisValue) -> {
|
||||
|
||||
if (StringUtils.isBlank(redisValue)) {
|
||||
if (Objects.isNull(redisValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -222,6 +212,7 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return Pair.of(workspaceId, productIds);
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||
@ -275,8 +266,8 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
||||
storeWorkspaceProduct(storeWorkspaceProductParam);
|
||||
}
|
||||
|
||||
private String getKey(Object... params) {
|
||||
return String.format(WORKSPACE_PRODUCT_KEY, params);
|
||||
private String getKey() {
|
||||
return String.format(WORKSPACE_PRODUCT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -398,4 +389,15 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Set<Long>> listAllWorkspaceProductCached() {
|
||||
|
||||
return RedisClient.HashOps.hGetAll(getKey()).entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(e -> Long.valueOf(e.getKey().toString()), e -> JSON.parseArray(e.getValue().toString())
|
||||
.stream()
|
||||
.map(productId -> Long.valueOf(productId.toString()))
|
||||
.collect(Collectors.toSet())));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user