diff --git a/tyr-server/pom.xml b/tyr-server/pom.xml index 1a4cc423..3c2ab346 100644 --- a/tyr-server/pom.xml +++ b/tyr-server/pom.xml @@ -95,6 +95,12 @@ feign-httpclient ${feign-httpclient.version} + + + cn.axzo.maokai + maokai-api + + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/UserRoleRelationCleanJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/UserRoleRelationCleanJob.java index 253fe135..d4a191f9 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/UserRoleRelationCleanJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/UserRoleRelationCleanJob.java @@ -1,8 +1,17 @@ package cn.axzo.tyr.server.job; +import cn.axzo.basics.common.BeanMapper; +import cn.axzo.maokai.api.client.CooperateShipQueryApi; +import cn.axzo.maokai.api.vo.request.PersonIdentityCheckReq; +import cn.axzo.pokonyan.config.redis.RedisUtil; +import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao; +import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation; +import cn.axzo.tyr.server.util.RpcInternalUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.StopWatch; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.annotation.XxlJob; @@ -17,11 +26,9 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.lang.reflect.InvocationTargetException; -import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; /** * 用户角色关系清理任务 @@ -33,38 +40,59 @@ import java.util.concurrent.TimeUnit; @Slf4j @Component public class UserRoleRelationCleanJob extends IJobHandler { + + private static final String CACHE_KEY = "tyr:job:u-r-r-c"; private volatile boolean runFlag = false; @Qualifier("userRoleCleanExecutor") @Autowired private ExecutorService userRoleCleanExecutor; + @Autowired + private SaasRoleUserRelationDao roleUserRelationDao; + + @Autowired + private CooperateShipQueryApi cooperateShipQueryApi; + @XxlJob("userRoleRelationCleanJob") @Override public ReturnT execute(String param) throws Exception { + StopWatch watch = new StopWatch("userRoleRelationCleanJob"); XxlJobLogger.log("start user role relation clean job param:{}", param); CleanTarget cleanParam = parseParam(param); + //加载待处理数据 + watch.start("load data"); + loadCleanTarget(cleanParam); + watch.stop(); + watch.start("check clean"); runFlag = true; - Integer page = 1; while (runFlag) { - List targetList = pullCleanTarget(cleanParam, page); - if (CollectionUtil.isEmpty(targetList)) { - XxlJobLogger.log("no target need to clean"); - break; - } - for (CleanTarget target : targetList) { - CompletableFuture.runAsync(() -> doClean(target), userRoleCleanExecutor); + CleanTarget target = getTarget(); + if (target == null) { + XxlJobLogger.log("all clean target are processed"); } + //数据库并发锁? + CompletableFuture.runAsync(() -> doClean(target), userRoleCleanExecutor); } + watch.stop(); - - XxlJobLogger.log("user role relation clean job finish"); + XxlJobLogger.log("user role relation clean job finish, cost:{} s", watch.getTotalTimeSeconds()); return ReturnT.SUCCESS; } + private CleanTarget getTarget() { + try { + String cacheTarget = RedisUtil.ListOps.lRightPop(CACHE_KEY); + return StrUtil.isBlank(cacheTarget) ? null : JSON.parseObject(cacheTarget, CleanTarget.class); + } catch (Exception ex) { + XxlJobLogger.log("get cached data error:{}", ex.getMessage()); + } + return null; + } + @Override public void destroy() throws InvocationTargetException, IllegalAccessException { this.runFlag = false; @@ -73,16 +101,49 @@ public class UserRoleRelationCleanJob extends IJobHandler { private void doClean(CleanTarget target) { try { - TimeUnit.SECONDS.sleep(5); + //检查person profile是否存在 ? + //检查人是否还在工作台 + PersonIdentityCheckReq checkReq = BeanMapper.copyBean(target, PersonIdentityCheckReq.class); + Boolean exists = RpcInternalUtil.rpcProcessor(() -> cooperateShipQueryApi.checkPersonIdentity(checkReq), + "check identity in workspace", checkReq).getData(); + if (exists) { + return; + } + XxlJobLogger.log("---------> user role relation need to clean for:{} <----------", JSON.toJSONString(target)); + roleUserRelationDao.cleanTargetRelation(target); } catch (Exception ex) { XxlJobLogger.log("clean target:{} error", JSON.toJSONString(target)); log.warn("clean target:{} error", JSON.toJSONString(target), ex); } } - private List pullCleanTarget(CleanTarget cleanParam, Integer page) { - XxlJobLogger.log("get bat clean target, page:{}", page); - return Collections.singletonList(new CleanTarget()); + private void loadCleanTarget(CleanTarget cleanParam) { + XxlJobLogger.log("clear cache data"); + RedisUtil.KeyOps.delete(CACHE_KEY); + XxlJobLogger.log("load all clean target data from db"); + SaasRoleUserRelation condition = new SaasRoleUserRelation(); + condition.setOuId(cleanParam.getOuId()); + condition.setWorkspaceId(cleanParam.getWorkspaceId()); + condition.setNaturalPersonId(cleanParam.getPersonId()); + int page = 1; + int count = 0; + while (true) { + Page pageResult = roleUserRelationDao.batListCleanRelation(condition, new Page<>(page++, 20)); + List records = pageResult.getRecords(); + if (CollectionUtil.isEmpty(records)) { + break; + } + count += records.size(); + records.forEach(r -> RedisUtil.ListOps.lLeftPush("key", JSON.toJSONString(CleanTarget.builder() + .ouId(r.getOuId()) + .workspaceId(r.getWorkspaceId()) + .personId(r.getNaturalPersonId()) + .identityId(r.getIdentityId()) + .identityType(r.getIdentityType()) + .build()))); + } + + XxlJobLogger.log("all target need to check count:{}", count); } private CleanTarget parseParam(String param) { @@ -98,10 +159,14 @@ public class UserRoleRelationCleanJob extends IJobHandler { @AllArgsConstructor public static class CleanTarget { - private Long personId; - private Long ouId; private Long workspaceId; + + private Long personId; + + private Long identityId; + + private Integer identityType; } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleUserRelationDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleUserRelationDao.java index 0bdd62a3..4f3994e6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleUserRelationDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasRoleUserRelationDao.java @@ -6,12 +6,16 @@ import cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum; import cn.axzo.tyr.client.model.BaseWorkspaceModel; import cn.axzo.tyr.client.model.enums.IdentityType; import cn.axzo.tyr.client.model.roleuser.dto.IdentityInfo; +import cn.axzo.tyr.server.job.UserRoleRelationCleanJob; import cn.axzo.tyr.server.model.RoleUserInfo; import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation; import cn.axzo.tyr.server.repository.mapper.SaasRoleUserRelationMapper; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Repository; @@ -166,5 +170,17 @@ public class SaasRoleUserRelationDao extends ServiceImpl batListCleanRelation(SaasRoleUserRelation cleanParam, IPage page) { + + return this.baseMapper.batListCleanRelation(page, cleanParam); + } + + public void cleanTargetRelation(UserRoleRelationCleanJob.CleanTarget target) { + this.remove(new LambdaQueryWrapper() + .eq(SaasRoleUserRelation::getOuId, target.getOuId()) + .eq(SaasRoleUserRelation::getWorkspaceId, target.getWorkspaceId()) + .eq(SaasRoleUserRelation::getIdentityId, target.getIdentityId()) + .eq(SaasRoleUserRelation::getIdentityType, target.getIdentityType())); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleUserRelationMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleUserRelationMapper.java index 60dd9d61..7547cf51 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleUserRelationMapper.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleUserRelationMapper.java @@ -1,12 +1,15 @@ package cn.axzo.tyr.server.repository.mapper; -import cn.axzo.tyr.server.repository.entity.SaasRole; import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; @Mapper public interface SaasRoleUserRelationMapper extends BaseMapper { + Page batListCleanRelation(IPage page, @Param("param") SaasRoleUserRelation cleanParam); } diff --git a/tyr-server/src/main/resources/mapper/SaasRoleUserRelationMapper.xml b/tyr-server/src/main/resources/mapper/SaasRoleUserRelationMapper.xml new file mode 100644 index 00000000..7a559ebe --- /dev/null +++ b/tyr-server/src/main/resources/mapper/SaasRoleUserRelationMapper.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file