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.CacheRoleFeatureResourceJob;
|
||||||
import cn.axzo.tyr.server.job.CacheRolePermissionJob;
|
import cn.axzo.tyr.server.job.CacheRolePermissionJob;
|
||||||
import cn.axzo.tyr.server.job.CacheSaasFeatureJob;
|
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.ProductModuleDao;
|
||||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||||
@ -169,6 +170,8 @@ public class PrivateController {
|
|||||||
private SaasRoleUserRelationService saasRoleUserRelationService;
|
private SaasRoleUserRelationService saasRoleUserRelationService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProductModuleDao productModuleDao;
|
private ProductModuleDao productModuleDao;
|
||||||
|
@Autowired
|
||||||
|
private CacheWorkspaceProductJob cacheWorkspaceProductJob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一层级的roleGroup按照id升序,sort从1递增
|
* 统一层级的roleGroup按照id升序,sort从1递增
|
||||||
@ -623,12 +626,24 @@ public class PrivateController {
|
|||||||
return featureCodeUtil.resolveFeatureCode(request.getFeatureCodes());
|
return featureCodeUtil.resolveFeatureCode(request.getFeatureCodes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/api/private/workspaceProduct/store")
|
@PostMapping("/api/private/productPermission/store")
|
||||||
public Object storeWorkspaceProduct(@RequestBody ProductSearchListReq request) throws Exception {
|
public Object storeProductPermission(@RequestBody ProductSearchListReq request) throws Exception {
|
||||||
cacheProductPermissionJob.execute(JSON.toJSONString(request));
|
cacheProductPermissionJob.execute(JSON.toJSONString(request));
|
||||||
return "ok";
|
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")
|
@PostMapping("/api/private/workspaceProduct/list")
|
||||||
public Object listWorkspaceProduct(@RequestBody WorkspaceProductService.WorkspaceProductParam request) {
|
public Object listWorkspaceProduct(@RequestBody WorkspaceProductService.WorkspaceProductParam request) {
|
||||||
return workspaceProductService.listWorkspaceProductCached(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 lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface WorkspaceProductService {
|
public interface WorkspaceProductService {
|
||||||
@ -43,6 +44,8 @@ public interface WorkspaceProductService {
|
|||||||
*/
|
*/
|
||||||
List<WorkspaceProductFeatureSource> listWorkspaceProductFeatureResourceCached(ListWorkspaceProductFeatureSourceCacheParam param);
|
List<WorkspaceProductFeatureSource> listWorkspaceProductFeatureResourceCached(ListWorkspaceProductFeatureSourceCacheParam param);
|
||||||
|
|
||||||
|
Map<Long, Set<Long>> listAllWorkspaceProductCached();
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package cn.axzo.tyr.server.service.impl;
|
|||||||
|
|
||||||
import cn.axzo.foundation.exception.Axssert;
|
import cn.axzo.foundation.exception.Axssert;
|
||||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
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.ServicePkgClient;
|
||||||
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
|
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
|
||||||
import cn.axzo.thrones.client.saas.entity.servicepkg.ServicePkgDetailRes;
|
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 com.google.common.collect.Streams;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
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.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
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.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -37,6 +33,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -67,7 +64,7 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
|||||||
@Value("${workspace.product.expire.minutes:14}")
|
@Value("${workspace.product.expire.minutes:14}")
|
||||||
private Long expireInMinutes;
|
private Long expireInMinutes;
|
||||||
|
|
||||||
private static final String WORKSPACE_PRODUCT_KEY = "workspace:product:%s";
|
private static final String WORKSPACE_PRODUCT_KEY = "workspace:product";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<WorkspaceProduct> listWorkspaceProduct(WorkspaceProductParam param) {
|
public List<WorkspaceProduct> listWorkspaceProduct(WorkspaceProductParam param) {
|
||||||
@ -184,35 +181,28 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
|||||||
public void storeWorkspaceProduct(StoreWorkspaceProductParam param) {
|
public void storeWorkspaceProduct(StoreWorkspaceProductParam param) {
|
||||||
Axssert.checkNotEmpty(param.getWorkspaceProducts(), REDIS_PRODUCT_NOT_NULL);
|
Axssert.checkNotEmpty(param.getWorkspaceProducts(), REDIS_PRODUCT_NOT_NULL);
|
||||||
|
|
||||||
|
Map<String, String> redisValues = param.getWorkspaceProducts().stream()
|
||||||
redisTemplate.executePipelined(new SessionCallback<Object>() {
|
.collect(Collectors.toMap(e -> e.getWorkspaceId().toString(), e -> Optional.ofNullable(e.getProductIds())
|
||||||
@Override
|
.map(JSON::toJSONString)
|
||||||
public Object execute(RedisOperations operations) throws DataAccessException {
|
.orElseGet(() -> JSON.toJSONString(Sets.newHashSet()))));
|
||||||
|
String redisKey = getKey();
|
||||||
for (WorkspaceProductDTO workspaceProduct : param.getWorkspaceProducts()) {
|
RedisClient.HashOps.hPutAll(redisKey, redisValues);
|
||||||
String redisKey = getKey(workspaceProduct.getWorkspaceId());
|
redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES);
|
||||||
RedisUtil.StringValueOps.setEx(redisKey, JSON.toJSONString(workspaceProduct.getProductIds()),
|
log.info("succeed to workspace product: redisKey:{} value:{}", redisKey, redisValues);
|
||||||
expireInMinutes, TimeUnit.MINUTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, Set<Long>> listWorkspaceProduct(ListWorkspaceProductParam param) {
|
private Map<Long, Set<Long>> listWorkspaceProduct(ListWorkspaceProductParam param) {
|
||||||
Axssert.checkNotEmpty(param.getWorkspaceIds(), WORKSPACE_ID_NOT_NULL);
|
Axssert.checkNotEmpty(param.getWorkspaceIds(), WORKSPACE_ID_NOT_NULL);
|
||||||
|
|
||||||
List<String> redisKeys = param.getWorkspaceIds().stream()
|
List<Object> redisValues = RedisClient.HashOps.hMultiGet(getKey(), param.getWorkspaceIds().stream()
|
||||||
.map(this::getKey)
|
.map(String::valueOf)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList()));
|
||||||
List<String> redisValues = redisTemplate.opsForValue().multiGet(redisKeys);
|
|
||||||
|
|
||||||
return Streams.zip(param.getWorkspaceIds().stream(),
|
return Streams.zip(param.getWorkspaceIds().stream(),
|
||||||
redisValues.stream(),
|
redisValues.stream(),
|
||||||
(workspaceId, redisValue) -> {
|
(workspaceId, redisValue) -> {
|
||||||
|
|
||||||
if (StringUtils.isBlank(redisValue)) {
|
if (Objects.isNull(redisValue)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +212,7 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
return Pair.of(workspaceId, productIds);
|
return Pair.of(workspaceId, productIds);
|
||||||
|
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||||
@ -275,8 +266,8 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
|||||||
storeWorkspaceProduct(storeWorkspaceProductParam);
|
storeWorkspaceProduct(storeWorkspaceProductParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey(Object... params) {
|
private String getKey() {
|
||||||
return String.format(WORKSPACE_PRODUCT_KEY, params);
|
return String.format(WORKSPACE_PRODUCT_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -398,4 +389,15 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService {
|
|||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.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