|
@@ -0,0 +1,209 @@
|
|
|
|
|
+package com.fs.admin.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.fs.admin.param.AdjustCidServerQuotaParam;
|
|
|
|
|
+import com.fs.admin.param.AllocateCidServerQuotaParam;
|
|
|
|
|
+import com.fs.admin.service.IAdminCidServerQuotaService;
|
|
|
|
|
+import com.fs.admin.vo.TenantCidServerQuotaVO;
|
|
|
|
|
+import com.fs.common.enums.DataSourceType;
|
|
|
|
|
+import com.fs.common.utils.DateUtils;
|
|
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
|
|
+import com.fs.company.domain.CompanyAiWorkflowServer;
|
|
|
|
|
+import com.fs.company.mapper.CompanyAiWorkflowServerMapper;
|
|
|
|
|
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
|
|
|
|
|
+import com.fs.framework.datasource.TenantDataSourceManager;
|
|
|
|
|
+import com.fs.tenant.domain.TenantInfo;
|
|
|
|
|
+import com.fs.tenant.service.TenantInfoService;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.function.Supplier;
|
|
|
|
|
+
|
|
|
|
|
+@Service
|
|
|
|
|
+public class AdminCidServerQuotaServiceImpl implements IAdminCidServerQuotaService {
|
|
|
|
|
+
|
|
|
|
|
+ private static final int MAX_TENANT_QUERY_SIZE = 10;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private TenantDataSourceManager tenantDataSourceManager;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private TenantInfoService tenantInfoService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private CompanyAiWorkflowServerMapper companyAiWorkflowServerMapper;
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<TenantCidServerQuotaVO> listQuotaByTenantIds(List<Long> tenantIds) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(tenantIds)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (tenantIds.size() > MAX_TENANT_QUERY_SIZE) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u4e00\u6b21\u6700\u591a\u67e5\u8be210\u4e2a\u79df\u6237");
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<Long, TenantInfo> tenantMap = loadTenantMap(tenantIds);
|
|
|
|
|
+ List<TenantCidServerQuotaVO> result = new ArrayList<>();
|
|
|
|
|
+ for (Long tenantId : tenantIds) {
|
|
|
|
|
+ TenantInfo tenant = tenantMap.get(tenantId);
|
|
|
|
|
+ if (tenant == null) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ runInTenant(tenantId, () -> {
|
|
|
|
|
+ List<CompanyAiWorkflowServer> servers = companyAiWorkflowServerMapper
|
|
|
|
|
+ .selectCompanyAiWorkflowServerList(new CompanyAiWorkflowServer());
|
|
|
|
|
+ if (servers == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (CompanyAiWorkflowServer server : servers) {
|
|
|
|
|
+ result.add(buildQuotaVo(tenant, server));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int allocateQuota(AllocateCidServerQuotaParam param) {
|
|
|
|
|
+ validateAllocateParam(param);
|
|
|
|
|
+ return runInTenant(param.getTenantId(), () -> {
|
|
|
|
|
+ CompanyAiWorkflowServer existing = companyAiWorkflowServerMapper.selectByGroupNo(param.getGroupNo());
|
|
|
|
|
+ if (existing != null) {
|
|
|
|
|
+ int addCount = param.getAllocateCount();
|
|
|
|
|
+ existing.setTotalCount(safeInt(existing.getTotalCount()) + addCount);
|
|
|
|
|
+ existing.setCount(safeInt(existing.getCount()) + addCount);
|
|
|
|
|
+ if (StringUtils.isNotEmpty(param.getTitle())) {
|
|
|
|
|
+ existing.setTitle(param.getTitle());
|
|
|
|
|
+ }
|
|
|
|
|
+ return companyAiWorkflowServerMapper.updateCompanyAiWorkflowServer(existing);
|
|
|
|
|
+ }
|
|
|
|
|
+ CompanyAiWorkflowServer server = new CompanyAiWorkflowServer();
|
|
|
|
|
+ server.setTitle(param.getTitle());
|
|
|
|
|
+ server.setGroupNo(param.getGroupNo());
|
|
|
|
|
+ server.setTotalCount(param.getAllocateCount());
|
|
|
|
|
+ server.setCount(param.getAllocateCount());
|
|
|
|
|
+ server.setCreateTime(DateUtils.getNowDate());
|
|
|
|
|
+ return companyAiWorkflowServerMapper.insertCompanyAiWorkflowServer(server);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int adjustQuota(AdjustCidServerQuotaParam param) {
|
|
|
|
|
+ if (param == null || param.getTenantId() == null || param.getServerId() == null || param.getTotalCount() == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u53c2\u6570\u4e0d\u5b8c\u6574");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (param.getTotalCount() < 0) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u603b\u540d\u989d\u4e0d\u80fd\u5c0f\u4e8e0");
|
|
|
|
|
+ }
|
|
|
|
|
+ return runInTenant(param.getTenantId(), () -> {
|
|
|
|
|
+ CompanyAiWorkflowServer server = companyAiWorkflowServerMapper.selectCompanyAiWorkflowServerById(param.getServerId());
|
|
|
|
|
+ if (server == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u670d\u52a1\u8bb0\u5f55\u4e0d\u5b58\u5728");
|
|
|
|
|
+ }
|
|
|
|
|
+ int usedCount = calcUsedCount(server);
|
|
|
|
|
+ if (param.getTotalCount() < usedCount) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u603b\u540d\u989d\u4e0d\u80fd\u5c0f\u4e8e\u5df2\u7528\u540d\u989d\uff08" + usedCount + "\uff09");
|
|
|
|
|
+ }
|
|
|
|
|
+ server.setTotalCount(param.getTotalCount());
|
|
|
|
|
+ server.setCount(param.getTotalCount() - usedCount);
|
|
|
|
|
+ return companyAiWorkflowServerMapper.updateCompanyAiWorkflowServer(server);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 切到租户库执行(先主库校验租户,再 switchTenant,避免事务绑定主库或静默回退主库)
|
|
|
|
|
+ */
|
|
|
|
|
+ private <T> T runInTenant(Long tenantId, Supplier<T> action) {
|
|
|
|
|
+ TenantInfo tenant = loadActiveTenant(tenantId);
|
|
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
|
|
+ try {
|
|
|
|
|
+ tenantDataSourceManager.switchTenant(tenant);
|
|
|
|
|
+ return action.get();
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ tenantDataSourceManager.clear();
|
|
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void runInTenant(Long tenantId, Runnable action) {
|
|
|
|
|
+ runInTenant(tenantId, () -> {
|
|
|
|
|
+ action.run();
|
|
|
|
|
+ return null;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private TenantInfo loadActiveTenant(Long tenantId) {
|
|
|
|
|
+ if (tenantId == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u79df\u6237ID\u4e0d\u80fd\u4e3a\u7a7a");
|
|
|
|
|
+ }
|
|
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
|
|
+ TenantInfo tenant = tenantInfoService.getById(tenantId);
|
|
|
|
|
+ if (tenant == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u79df\u6237\u4e0d\u5b58\u5728");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (tenant.getStatus() == null || tenant.getStatus() != 1) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u79df\u6237\u672a\u542f\u7528\uff0c\u6682\u4e0d\u53ef\u64cd\u4f5c");
|
|
|
|
|
+ }
|
|
|
|
|
+ return tenant;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private TenantCidServerQuotaVO buildQuotaVo(TenantInfo tenant, CompanyAiWorkflowServer server) {
|
|
|
|
|
+ TenantCidServerQuotaVO vo = new TenantCidServerQuotaVO();
|
|
|
|
|
+ vo.setTenantId(tenant.getId());
|
|
|
|
|
+ vo.setTenantName(tenant.getTenantName());
|
|
|
|
|
+ vo.setTenantCode(tenant.getTenantCode());
|
|
|
|
|
+ vo.setServerId(server.getId());
|
|
|
|
|
+ vo.setTitle(server.getTitle());
|
|
|
|
|
+ vo.setGroupNo(server.getGroupNo());
|
|
|
|
|
+ vo.setTotalCount(safeInt(server.getTotalCount()));
|
|
|
|
|
+ vo.setRemainCount(safeInt(server.getCount()));
|
|
|
|
|
+ vo.setUsedCount(calcUsedCount(server));
|
|
|
|
|
+ vo.setCreateTime(server.getCreateTime());
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int calcUsedCount(CompanyAiWorkflowServer server) {
|
|
|
|
|
+ int total = safeInt(server.getTotalCount());
|
|
|
|
|
+ int remain = safeInt(server.getCount());
|
|
|
|
|
+ int used = total - remain;
|
|
|
|
|
+ if (used < 0) {
|
|
|
|
|
+ used = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ int boundCount = companyAiWorkflowServerMapper.countBoundUsersByServerId(server.getId());
|
|
|
|
|
+ return Math.max(used, boundCount);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void validateAllocateParam(AllocateCidServerQuotaParam param) {
|
|
|
|
|
+ if (param == null || param.getTenantId() == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u8bf7\u9009\u62e9\u79df\u6237");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (param.getGroupNo() == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u8bf7\u586b\u5199\u5206\u7ec4\u53f7");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (param.getAllocateCount() == null || param.getAllocateCount() <= 0) {
|
|
|
|
|
+ throw new IllegalArgumentException("\u5206\u914d\u6570\u91cf\u5fc5\u987b\u5927\u4e8e0");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isEmpty(param.getTitle())) {
|
|
|
|
|
+ param.setTitle("CID\u670d\u52a1\u7ec4-" + param.getGroupNo());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<Long, TenantInfo> loadTenantMap(List<Long> tenantIds) {
|
|
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
|
|
+ Map<Long, TenantInfo> map = new HashMap<>();
|
|
|
|
|
+ for (Long tenantId : tenantIds) {
|
|
|
|
|
+ TenantInfo tenant = tenantInfoService.getById(tenantId);
|
|
|
|
|
+ if (tenant != null) {
|
|
|
|
|
+ map.put(tenantId, tenant);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return map;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int safeInt(Integer value) {
|
|
|
|
|
+ return value == null ? 0 : value;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|