@@ -12,6 +12,18 @@ | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.openjdk.jmh</groupId> | |||
<artifactId>jmh-core</artifactId> | |||
<version>1.37</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.openjdk.jmh</groupId> | |||
<artifactId>jmh-generator-annprocess</artifactId> | |||
<version>1.37</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.google.guava</groupId> | |||
<artifactId>guava</artifactId> | |||
<version>33.0.0-jre</version> | |||
@@ -3,7 +3,7 @@ package com.hz.pm.api.common.statemachine.builder.impl; | |||
import com.hz.pm.api.common.statemachine.builder.BaseStateMachineBuilder; | |||
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent; | |||
import com.hz.pm.api.common.statemachine.factory.ProjectGuardFactory; | |||
import com.hz.pm.api.common.statemachine.factory.ProjectGuardFactory.ProjectPurchaseToFirstAcceptGuard; | |||
import com.hz.pm.api.common.statemachine.factory.ProjectGuardFactory.ProjectPurchaseToAcceptGuard; | |||
import com.hz.pm.api.projectlib.model.entity.Project; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus; | |||
import lombok.RequiredArgsConstructor; | |||
@@ -32,13 +32,15 @@ import java.util.EnumSet; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@EnableStateMachine(name = ProjectStateMachineBuilderImpl.MACHINE_ID) | |||
@RequiredArgsConstructor | |||
@EnableStateMachine(name = ProjectStateMachineBuilderImpl.MACHINE_ID) | |||
public class ProjectStateMachineBuilderImpl implements BaseStateMachineBuilder<Project, ProjectStateChangeEvent, ProjectStatus> { | |||
public static final String MACHINE_ID = "projectDeclareStateMachine"; | |||
private final BeanFactory beanFactory; | |||
private final ProjectPurchaseToAcceptGuard projectPurchaseToAcceptGuard; | |||
private final ProjectGuardFactory.ProjectPurchaseToAdaptGuard projectPurchaseToAdaptGuard; | |||
@Override | |||
public StateMachine<ProjectStatus, ProjectStateChangeEvent> build() throws StateMachineException { | |||
@@ -149,13 +151,15 @@ public class ProjectStateMachineBuilderImpl implements BaseStateMachineBuilder<P | |||
.withExternal() | |||
.source(ProjectStatus.ON_PURCHASING) | |||
.target(ProjectStatus.ON_ADAPTING) | |||
.event(ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD).and() | |||
.event(ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD) | |||
.guard(projectPurchaseToAdaptGuard) | |||
.and() | |||
// 填写试试计划 -> 待初验 | |||
.withExternal() | |||
.source(ProjectStatus.ON_PURCHASING) | |||
.target(ProjectStatus.TO_BE_FIRST_INSPECTED) | |||
.event(ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD) | |||
.guard(new ProjectPurchaseToFirstAcceptGuard()) | |||
.guard(projectPurchaseToAcceptGuard) | |||
.and() | |||
// 填写试试计划 -> 待初验 | |||
.withExternal() | |||
@@ -3,7 +3,7 @@ package com.hz.pm.api.common.statemachine.builder.impl; | |||
import cn.hutool.core.collection.ListUtil; | |||
import com.hz.pm.api.common.statemachine.builder.BaseStateMachineBuilder; | |||
import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; | |||
import com.hz.pm.api.common.statemachine.factory.TenderGuardFactory; | |||
import com.hz.pm.api.common.statemachine.factory.TenderGuardFactory.PurchaseContractRecordToAcceptGuard; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ITenderStatus; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.TenderAdaptStatus; | |||
@@ -26,6 +26,8 @@ import org.springframework.stereotype.Component; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import static com.hz.pm.api.common.statemachine.factory.TenderGuardFactory.PurchaseContractRecordToOperationGuard; | |||
/** | |||
* <p> | |||
* 标段状态机 | |||
@@ -36,13 +38,16 @@ import java.util.List; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@EnableStateMachine(name = TenderStateMachineBuilderImpl.MACHINE_ID) | |||
@RequiredArgsConstructor | |||
@EnableStateMachine(name = TenderStateMachineBuilderImpl.MACHINE_ID) | |||
public class TenderStateMachineBuilderImpl implements BaseStateMachineBuilder<Purchase, TenderStateChangeEvent, ITenderStatus> { | |||
public static final String MACHINE_ID = "tenderStateMachine"; | |||
private final BeanFactory beanFactory; | |||
private final PurchaseContractRecordToAcceptGuard purchaseContractRecordToAcceptGuard; | |||
private final PurchaseContractRecordToOperationGuard purchaseContractRecordToOperationGuard; | |||
@Override | |||
public StateMachine<ITenderStatus, TenderStateChangeEvent> build() throws StateMachineException { | |||
@@ -81,12 +86,13 @@ public class TenderStateMachineBuilderImpl implements BaseStateMachineBuilder<Pu | |||
.source(TenderMainStatus.TO_BE_SUBMIT_PURCHASE_CONSTRUCTION_INFO) | |||
.target(TenderMainStatus.TO_BE_SUBMIT_OPERATION_PLAN) | |||
.event(TenderStateChangeEvent.SUBMIT_PURCHASE_CONSTRUCTION_INFO) | |||
.guard(purchaseContractRecordToOperationGuard) | |||
.and() | |||
.withExternal() | |||
.source(TenderMainStatus.TO_BE_SUBMIT_PURCHASE_CONSTRUCTION_INFO) | |||
.target(TenderMainStatus.TO_BE_SUBMIT_FIRST_INSPECTED_INFO) | |||
.event(TenderStateChangeEvent.SUBMIT_PURCHASE_CONSTRUCTION_INFO) | |||
.guard(new TenderGuardFactory.PurchaseContractRecordGuard()) | |||
.guard(purchaseContractRecordToAcceptGuard) | |||
.and() | |||
// 填写实施计划 | |||
.withExternal() | |||
@@ -4,7 +4,6 @@ import com.hz.pm.api.common.statemachine.builder.BaseStateMachineBuilder; | |||
import com.hz.pm.api.common.statemachine.event.XcfhxStateChangeEvent; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.TenderXcfhxApplyStatus; | |||
import com.ningdatech.basic.exception.BizException; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.BeanFactory; | |||
@@ -2,7 +2,6 @@ package com.hz.pm.api.common.statemachine.factory; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.baomidou.mybatisplus.core.conditions.Wrapper; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.common.statemachine.action.ProjectStateChangeAction; | |||
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent; | |||
@@ -11,8 +10,9 @@ import com.hz.pm.api.projectdeclared.model.enumerization.BidTypeEnum; | |||
import com.hz.pm.api.projectdeclared.service.IPurchaseService; | |||
import com.hz.pm.api.projectlib.model.entity.Project; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.TenderMainStatus; | |||
import com.ningdatech.basic.util.SpringUtils; | |||
import lombok.AllArgsConstructor; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.statemachine.StateContext; | |||
import org.springframework.statemachine.guard.Guard; | |||
@@ -26,25 +26,58 @@ import java.util.List; | |||
* @author WendyYang | |||
* @since 11:28 2024/8/22 | |||
*/ | |||
@Configuration | |||
public class ProjectGuardFactory { | |||
private ProjectGuardFactory() { | |||
private final IPurchaseService purchaseService; | |||
public ProjectGuardFactory(IPurchaseService purchaseService) { | |||
this.purchaseService = purchaseService; | |||
} | |||
@AllArgsConstructor | |||
public static class ProjectPurchaseToAcceptGuard implements Guard<ProjectStatus, ProjectStateChangeEvent> { | |||
private IPurchaseService purchaseService; | |||
@Override | |||
public boolean evaluate(StateContext<ProjectStatus, ProjectStateChangeEvent> ctx) { | |||
return !canTurnToAdapt(ctx, purchaseService); | |||
} | |||
} | |||
public static class ProjectPurchaseToFirstAcceptGuard implements Guard<ProjectStatus, ProjectStateChangeEvent> { | |||
@AllArgsConstructor | |||
public static class ProjectPurchaseToAdaptGuard implements Guard<ProjectStatus, ProjectStateChangeEvent> { | |||
private final IPurchaseService purchaseService = SpringUtils.getBean(IPurchaseService.class); | |||
private IPurchaseService purchaseService; | |||
@Override | |||
public boolean evaluate(StateContext<ProjectStatus, ProjectStateChangeEvent> stateContext) { | |||
Project project = ProjectStateChangeAction.getProject(stateContext.getMessage()); | |||
Wrapper<Purchase> query = Wrappers.lambdaQuery(Purchase.class) | |||
.select(Purchase::getId, Purchase::getBidType) | |||
.eq(Purchase::getProjectId, project.getId()); | |||
List<Purchase> purchases = purchaseService.list(query); | |||
return CollUtil.allMatch(purchases, w -> !BidTypeEnum.BUILD_APP.eq(w.getBidType())); | |||
public boolean evaluate(StateContext<ProjectStatus, ProjectStateChangeEvent> ctx) { | |||
return canTurnToAdapt(ctx, purchaseService); | |||
} | |||
} | |||
private static boolean canTurnToAdapt(StateContext<ProjectStatus, ProjectStateChangeEvent> ctx, | |||
IPurchaseService purchaseService) { | |||
Project project = ProjectStateChangeAction.getProject(ctx.getMessage()); | |||
Wrapper<Purchase> query = Wrappers.lambdaQuery(Purchase.class) | |||
.select(Purchase::getId, Purchase::getBidType) | |||
.eq(Purchase::getProjectId, project.getId()); | |||
List<Purchase> purchases = purchaseService.list(query); | |||
return CollUtil.anyMatch(purchases, w -> BidTypeEnum.BUILD_APP.eq(w.getBidType())); | |||
} | |||
@Bean | |||
public ProjectPurchaseToAcceptGuard projectPurchaseToAcceptGuard() { | |||
return new ProjectPurchaseToAcceptGuard(purchaseService); | |||
} | |||
@Bean | |||
public ProjectPurchaseToAdaptGuard projectPurchaseToAdaptGuard() { | |||
return new ProjectPurchaseToAdaptGuard(purchaseService); | |||
} | |||
} |
@@ -5,6 +5,8 @@ import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import com.hz.pm.api.projectdeclared.model.enumerization.BidTypeEnum; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ITenderStatus; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.statemachine.StateContext; | |||
import org.springframework.statemachine.guard.Guard; | |||
@@ -16,12 +18,28 @@ import org.springframework.statemachine.guard.Guard; | |||
* @author WendyYang | |||
* @since 17:51 2024/8/20 | |||
*/ | |||
@Configuration | |||
public class TenderGuardFactory { | |||
private TenderGuardFactory() { | |||
@Bean | |||
public PurchaseContractRecordToOperationGuard purchaseContractRecordToOperationGuard() { | |||
return new PurchaseContractRecordToOperationGuard(); | |||
} | |||
public static class PurchaseContractRecordGuard implements Guard<ITenderStatus, TenderStateChangeEvent> { | |||
@Bean | |||
public PurchaseContractRecordToAcceptGuard purchaseContractRecordToAcceptGuard() { | |||
return new PurchaseContractRecordToAcceptGuard(); | |||
} | |||
public static class PurchaseContractRecordToOperationGuard implements Guard<ITenderStatus, TenderStateChangeEvent> { | |||
@Override | |||
public boolean evaluate(StateContext<ITenderStatus, TenderStateChangeEvent> context) { | |||
Purchase purchase = TenderStateChangeActionUtil.getPurchaseInfo(context.getMessage()); | |||
return BidTypeEnum.BUILD_APP.eq(purchase.getBidType()); | |||
} | |||
} | |||
public static class PurchaseContractRecordToAcceptGuard implements Guard<ITenderStatus, TenderStateChangeEvent> { | |||
@Override | |||
public boolean evaluate(StateContext<ITenderStatus, TenderStateChangeEvent> context) { | |||
Purchase purchase = TenderStateChangeActionUtil.getPurchaseInfo(context.getMessage()); | |||
@@ -1,9 +1,10 @@ | |||
package com.hz.pm.api.common.statemachine.util; | |||
import cn.hutool.log.Log; | |||
import cn.hutool.log.LogFactory; | |||
import com.hz.pm.api.common.statemachine.event.AbstractStateChangeEvent; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.wflow.exception.BusinessException; | |||
import org.slf4j.LoggerFactory; | |||
import java.lang.reflect.ParameterizedType; | |||
import java.lang.reflect.Type; | |||
@@ -19,6 +20,8 @@ import java.util.function.Function; | |||
*/ | |||
public interface AbstractStateMachineUtil<O, E extends Enum<E> & AbstractStateChangeEvent> { | |||
Log LOG = LogFactory.get(AbstractStateMachineUtil.class); | |||
/** | |||
* 获取状态变更事件类型 | |||
* | |||
@@ -29,12 +32,19 @@ public interface AbstractStateMachineUtil<O, E extends Enum<E> & AbstractStateCh | |||
return (Class<E>) ((ParameterizedType) type).getActualTypeArguments()[1]; | |||
} | |||
default AbstractStateMachineUtil<O, E> getLockClass() { | |||
LOG.info("acquire state machine lock:{}", this.getClass().getSimpleName()); | |||
return this; | |||
} | |||
//通过审核 | |||
default void pass(O obj) { | |||
try { | |||
execute(obj, AbstractStateChangeEvent.getPassEvent(eventClass(), statusFunction().apply(obj))); | |||
synchronized (getLockClass()) { | |||
execute(obj, AbstractStateChangeEvent.getPassEvent(eventClass(), statusFunction().apply(obj))); | |||
} | |||
} catch (Exception e) { | |||
LoggerFactory.getLogger(this.getClass()).info("状态机 通过失败", e); | |||
LOG.error("状态机通过失败", e); | |||
throw BizException.wrap("状态机通过失败"); | |||
} | |||
} | |||
@@ -43,9 +53,11 @@ public interface AbstractStateMachineUtil<O, E extends Enum<E> & AbstractStateCh | |||
//拒绝 | |||
default void reject(O obj) { | |||
try { | |||
execute(obj, AbstractStateChangeEvent.getRejectEvent(eventClass(), statusFunction().apply(obj))); | |||
synchronized (getLockClass()) { | |||
execute(obj, AbstractStateChangeEvent.getRejectEvent(eventClass(), statusFunction().apply(obj))); | |||
} | |||
} catch (Exception e) { | |||
LoggerFactory.getLogger(this.getClass()).info("状态机 拒绝失败 :{}", e.getMessage()); | |||
LOG.error("状态机拒绝失败", e); | |||
throw new BusinessException("状态机拒绝失败"); | |||
} | |||
} | |||
@@ -53,9 +65,11 @@ public interface AbstractStateMachineUtil<O, E extends Enum<E> & AbstractStateCh | |||
//撤回 | |||
default void withDraw(O obj) { | |||
try { | |||
execute(obj, AbstractStateChangeEvent.getWithdrawEvent(eventClass(), statusFunction().apply(obj))); | |||
synchronized (getLockClass()) { | |||
execute(obj, AbstractStateChangeEvent.getWithdrawEvent(eventClass(), statusFunction().apply(obj))); | |||
} | |||
} catch (Exception e) { | |||
LoggerFactory.getLogger(this.getClass()).info("状态机 撤回失败 :{}", e.getMessage()); | |||
LOG.error("状态机撤回失败", e); | |||
throw new BusinessException("状态机撤回失败"); | |||
} | |||
} | |||
@@ -5,10 +5,8 @@ import com.hz.pm.api.common.statemachine.event.AdaptStateChangeEvent; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import com.hz.pm.api.projectdeclared.utils.ProjectIdCodeCacheUtil; | |||
import com.hz.pm.api.projectlib.entity.PurchaseStatusChange; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ITenderStatus; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.TenderAdaptStatus; | |||
import com.hz.pm.api.projectlib.service.IPurchaseStatusChangeService; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.messaging.Message; | |||
import org.springframework.messaging.support.MessageBuilder; | |||
@@ -29,16 +27,23 @@ import java.util.function.Function; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class AdaptStateMachineUtil implements AbstractStateMachineUtil<Purchase, AdaptStateChangeEvent> { | |||
public static final String PURCHASE = "purchaseInfo"; | |||
//================================================================================================================== | |||
private final AdaptStateMachineBuilderImpl adaptStateMachineBuilder; | |||
private final StateMachinePersister<TenderAdaptStatus, AdaptStateChangeEvent, Purchase> stateMachinePersister; | |||
private final StateMachine<TenderAdaptStatus, AdaptStateChangeEvent> stateMachine; | |||
private final IPurchaseStatusChangeService purchaseStatusChangeService; | |||
public AdaptStateMachineUtil(AdaptStateMachineBuilderImpl adaptStateMachineBuilder, | |||
IPurchaseStatusChangeService purchaseStatusChangeService) { | |||
this.purchaseStatusChangeService = purchaseStatusChangeService; | |||
this.stateMachine = adaptStateMachineBuilder.build(); | |||
this.stateMachinePersister = adaptStateMachineBuilder.stateMachinePersister(); | |||
} | |||
@Override | |||
public Function<Purchase, Integer> statusFunction() { | |||
return Purchase::getAdaptStatus; | |||
@@ -46,8 +51,6 @@ public class AdaptStateMachineUtil implements AbstractStateMachineUtil<Purchase, | |||
@Override | |||
public void execute(Purchase purchase, AdaptStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的标段状态为:{}", purchase.getStatus()); | |||
// 获取TO状态机 | |||
PurchaseStatusChange change = new PurchaseStatusChange(); | |||
change.setBeforeStatus(purchase.getAdaptStatus()); | |||
change.setEvent(event.name()); | |||
@@ -55,17 +58,15 @@ public class AdaptStateMachineUtil implements AbstractStateMachineUtil<Purchase, | |||
change.setProjectId(purchase.getProjectId()); | |||
change.setProjectCode(ProjectIdCodeCacheUtil.get(purchase.getProjectId())); | |||
change.setCreateOn(LocalDateTime.now()); | |||
StateMachine<TenderAdaptStatus, AdaptStateChangeEvent> stateMachine = adaptStateMachineBuilder.build(); | |||
Message<AdaptStateChangeEvent> message = MessageBuilder.withPayload(event) | |||
.setHeader(PURCHASE, purchase) | |||
.build(); | |||
//初始化状态机 | |||
StateMachinePersister<TenderAdaptStatus, AdaptStateChangeEvent, Purchase> stateMachinePersister = adaptStateMachineBuilder.stateMachinePersister(); | |||
stateMachinePersister.restore(stateMachine, purchase); | |||
stateMachine.sendEvent(message); | |||
change.setAfterStatus(purchase.getAdaptStatus()); | |||
purchaseStatusChangeService.save(change); | |||
log.info("调用状态机后的标段状态为:{}", purchase.getAdaptStatus()); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -27,7 +27,6 @@ import java.util.function.Function; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class ProjectStateMachineUtil implements AbstractStateMachineUtil<Project, ProjectStateChangeEvent> { | |||
private static final String PROJECT_DECLARE = StateMachineConst.PROJECT_DECLARE; | |||
@@ -36,12 +35,20 @@ public class ProjectStateMachineUtil implements AbstractStateMachineUtil<Project | |||
//================================================================================================================== | |||
private final ProjectStateMachineBuilderImpl projectStateMachineBuilder; | |||
private final StateMachinePersister<ProjectStatus, ProjectStateChangeEvent, Project> stateMachinePersister; | |||
private final StateMachine<ProjectStatus, ProjectStateChangeEvent> stateMachine; | |||
private final IProjectStatusChangeService projectStatusChangeService; | |||
private final IProjectApplicationService projectApplicationService; | |||
public ProjectStateMachineUtil(ProjectStateMachineBuilderImpl projectStateMachineBuilder, | |||
IProjectStatusChangeService projectStatusChangeService, | |||
IProjectApplicationService projectApplicationService) { | |||
this.projectStatusChangeService = projectStatusChangeService; | |||
this.projectApplicationService = projectApplicationService; | |||
this.stateMachinePersister = projectStateMachineBuilder.stateMachinePersister(); | |||
this.stateMachine = projectStateMachineBuilder.build(); | |||
} | |||
@Override | |||
public Function<Project, Integer> statusFunction() { | |||
return Project::getStatus; | |||
@@ -49,29 +56,25 @@ public class ProjectStateMachineUtil implements AbstractStateMachineUtil<Project | |||
@Override | |||
public void execute(Project project, ProjectStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的项目状态为:{}", project.getStatus()); | |||
// 将状态变更记录保存到项目状态变更表中 | |||
ProjectStatusChange projectStatusChange = new ProjectStatusChange(); | |||
projectStatusChange.setBeforeStatus(project.getStatus()); | |||
ProjectStatusChange change = new ProjectStatusChange(); | |||
change.setBeforeStatus(project.getStatus()); | |||
// 获取TO状态机 | |||
StateMachine<ProjectStatus, ProjectStateChangeEvent> stateMachine = projectStateMachineBuilder.build(); | |||
Message<ProjectStateChangeEvent> message = MessageBuilder.withPayload(event) | |||
.setHeader(PROJECT_DECLARE, project) | |||
.setHeader(APPLICATION_DECLARE, projectApplicationService.getApplicationsByProject(project)) | |||
.build(); | |||
//初始化状态机 | |||
StateMachinePersister<ProjectStatus, ProjectStateChangeEvent, Project> projectDeclareStateMachinePersister = projectStateMachineBuilder.stateMachinePersister(); | |||
projectDeclareStateMachinePersister.restore(stateMachine, project); | |||
stateMachinePersister.restore(stateMachine, project); | |||
stateMachine.sendEvent(message); | |||
projectStatusChange.setProjectId(project.getId()); | |||
projectStatusChange.setAfterStatus(project.getStatus()); | |||
projectStatusChange.setEvent(event.name()); | |||
projectStatusChange.setCreateOn(LocalDateTime.now()); | |||
projectStatusChange.setProjectCode(project.getProjectCode()); | |||
change.setProjectId(project.getId()); | |||
change.setAfterStatus(project.getStatus()); | |||
change.setEvent(event.name()); | |||
change.setCreateOn(LocalDateTime.now()); | |||
change.setProjectCode(project.getProjectCode()); | |||
// 插入项目状态变更表中 | |||
projectStatusChangeService.save(projectStatusChange); | |||
log.info("调用状态机后的项目状态为:{}", project.getStatus()); | |||
projectStatusChangeService.save(change); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -28,15 +28,21 @@ import java.util.function.Function; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class SelfTestStateMachineUtil implements AbstractStateMachineUtil<Purchase, SelfTestStateChangeEvent> { | |||
public static final String PURCHASE = "purchaseInfo"; | |||
//================================================================================================================== | |||
private final SelfTestStateMachineBuilderImpl selfTestStateMachineBuilder; | |||
private final IPurchaseStatusChangeService purchaseStatusChangeService; | |||
private final StateMachinePersister<TenderSelfTestStatus, SelfTestStateChangeEvent, Purchase> stateMachinePersister; | |||
private final StateMachine<TenderSelfTestStatus, SelfTestStateChangeEvent> stateMachine; | |||
public SelfTestStateMachineUtil(SelfTestStateMachineBuilderImpl selfTestStateMachineBuilder, IPurchaseStatusChangeService purchaseStatusChangeService) { | |||
this.purchaseStatusChangeService = purchaseStatusChangeService; | |||
this.stateMachinePersister = selfTestStateMachineBuilder.stateMachinePersister(); | |||
this.stateMachine = selfTestStateMachineBuilder.build(); | |||
} | |||
@Override | |||
public Function<Purchase, Integer> statusFunction() { | |||
@@ -45,7 +51,6 @@ public class SelfTestStateMachineUtil implements AbstractStateMachineUtil<Purcha | |||
@Override | |||
public void execute(Purchase purchase, SelfTestStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的标段状态为:{}", purchase.getSelfTestStatus()); | |||
// 获取TO状态机 | |||
PurchaseStatusChange change = new PurchaseStatusChange(); | |||
change.setBeforeStatus(purchase.getSelfTestStatus()); | |||
@@ -54,17 +59,15 @@ public class SelfTestStateMachineUtil implements AbstractStateMachineUtil<Purcha | |||
change.setProjectId(purchase.getProjectId()); | |||
change.setProjectCode(ProjectIdCodeCacheUtil.get(purchase.getProjectId())); | |||
change.setCreateOn(LocalDateTime.now()); | |||
StateMachine<TenderSelfTestStatus, SelfTestStateChangeEvent> stateMachine = selfTestStateMachineBuilder.build(); | |||
Message<SelfTestStateChangeEvent> message = MessageBuilder.withPayload(event) | |||
.setHeader(PURCHASE, purchase) | |||
.build(); | |||
//初始化状态机 | |||
StateMachinePersister<TenderSelfTestStatus, SelfTestStateChangeEvent, Purchase> stateMachinePersister = selfTestStateMachineBuilder.stateMachinePersister(); | |||
stateMachinePersister.restore(stateMachine, purchase); | |||
stateMachine.sendEvent(message); | |||
change.setAfterStatus(purchase.getSelfTestStatus()); | |||
purchaseStatusChangeService.save(change); | |||
log.info("调用状态机后的标段状态为:{}", purchase.getSelfTestStatus()); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -1,6 +1,5 @@ | |||
package com.hz.pm.api.common.statemachine.util; | |||
import cn.hutool.core.util.ObjUtil; | |||
import com.hz.pm.api.common.statemachine.builder.impl.TenderStateMachineBuilderImpl; | |||
import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
@@ -30,15 +29,21 @@ import java.util.function.Function; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class TenderStateMachineUtil implements AbstractStateMachineUtil<Purchase, TenderStateChangeEvent> { | |||
public static final String PURCHASE = "purchaseInfo"; | |||
//================================================================================================================== | |||
private final TenderStateMachineBuilderImpl tenderStateMachineBuilder; | |||
private final IPurchaseStatusChangeService purchaseStatusChangeService; | |||
private final StateMachinePersister<ITenderStatus, TenderStateChangeEvent, Purchase> stateMachinePersister; | |||
private final StateMachine<ITenderStatus, TenderStateChangeEvent> stateMachine; | |||
public TenderStateMachineUtil(IPurchaseStatusChangeService purchaseStatusChangeService, TenderStateMachineBuilderImpl tenderStateMachineBuilder) { | |||
this.purchaseStatusChangeService = purchaseStatusChangeService; | |||
this.stateMachinePersister = tenderStateMachineBuilder.stateMachinePersister(); | |||
this.stateMachine = tenderStateMachineBuilder.build(); | |||
} | |||
@Override | |||
public Function<Purchase, Integer> statusFunction() { | |||
@@ -47,7 +52,6 @@ public class TenderStateMachineUtil implements AbstractStateMachineUtil<Purchase | |||
@Override | |||
public void execute(Purchase purchase, TenderStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的标段状态为:{}", purchase.getStatus()); | |||
// 获取TO状态机 | |||
PurchaseStatusChange change = new PurchaseStatusChange(); | |||
change.setBeforeStatus(purchase.getStatus()); | |||
@@ -56,21 +60,15 @@ public class TenderStateMachineUtil implements AbstractStateMachineUtil<Purchase | |||
change.setProjectId(purchase.getProjectId()); | |||
change.setProjectCode(ProjectIdCodeCacheUtil.get(purchase.getProjectId())); | |||
change.setCreateOn(LocalDateTime.now()); | |||
StateMachine<ITenderStatus, TenderStateChangeEvent> stateMachine = tenderStateMachineBuilder.build(); | |||
Message<TenderStateChangeEvent> message = MessageBuilder.withPayload(event) | |||
.setHeader(PURCHASE, purchase) | |||
.build(); | |||
//初始化状态机 | |||
StateMachinePersister<ITenderStatus, TenderStateChangeEvent, Purchase> stateMachinePersister = tenderStateMachineBuilder.stateMachinePersister(); | |||
stateMachinePersister.restore(stateMachine, purchase); | |||
stateMachine.sendEvent(message); | |||
change.setAfterStatus(purchase.getStatus()); | |||
purchaseStatusChangeService.save(change); | |||
if (ObjUtil.equal(change.getBeforeStatus(), change.getBeforeStatus())) { | |||
log.error("状态变更失败:{} {}", purchase, event); | |||
throw BizException.wrap("状态变更失败"); | |||
} | |||
log.info("调用状态机后的标段状态为:{}", purchase.getStatus()); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -45,8 +45,6 @@ public class TestValidStateMachineUtil implements AbstractStateMachineUtil<Purch | |||
@Override | |||
public void execute(Purchase purchase, TestValidStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的标段状态为:{}", purchase.getStatus()); | |||
// 获取TO状态机 | |||
PurchaseStatusChange change = new PurchaseStatusChange(); | |||
change.setBeforeStatus(purchase.getTestValidStatus()); | |||
change.setEvent(event.name()); | |||
@@ -64,7 +62,7 @@ public class TestValidStateMachineUtil implements AbstractStateMachineUtil<Purch | |||
stateMachine.sendEvent(message); | |||
change.setAfterStatus(purchase.getTestValidStatus()); | |||
purchaseStatusChangeService.save(change); | |||
log.info("调用状态机后的标段状态为:{}", purchase.getStatus()); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -28,15 +28,22 @@ import java.util.function.Function; | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class XcfhxStateMachineUtil implements AbstractStateMachineUtil<Purchase, XcfhxStateChangeEvent> { | |||
public static final String PURCHASE = "purchaseInfo"; | |||
//================================================================================================================== | |||
private final XcfhxStateMachineBuilderImpl xcfhxStateMachineBuilder; | |||
private final IPurchaseStatusChangeService purchaseStatusChangeService; | |||
private final StateMachinePersister<TenderXcfhxApplyStatus, XcfhxStateChangeEvent, Purchase> stateMachinePersister; | |||
private final StateMachine<TenderXcfhxApplyStatus, XcfhxStateChangeEvent> stateMachine; | |||
public XcfhxStateMachineUtil(XcfhxStateMachineBuilderImpl xcfhxStateMachineBuilder, | |||
IPurchaseStatusChangeService purchaseStatusChangeService) { | |||
this.purchaseStatusChangeService = purchaseStatusChangeService; | |||
this.stateMachine = xcfhxStateMachineBuilder.build(); | |||
this.stateMachinePersister = xcfhxStateMachineBuilder.stateMachinePersister(); | |||
} | |||
@Override | |||
public Function<Purchase, Integer> statusFunction() { | |||
@@ -45,8 +52,6 @@ public class XcfhxStateMachineUtil implements AbstractStateMachineUtil<Purchase, | |||
@Override | |||
public void execute(Purchase purchase, XcfhxStateChangeEvent event) throws Exception { | |||
log.info("调用状态机前的标段状态为:{}", purchase.getXcfhxApplyStatus()); | |||
// 获取TO状态机 | |||
PurchaseStatusChange change = new PurchaseStatusChange(); | |||
change.setBeforeStatus(purchase.getXcfhxApplyStatus()); | |||
change.setEvent(event.name()); | |||
@@ -54,17 +59,15 @@ public class XcfhxStateMachineUtil implements AbstractStateMachineUtil<Purchase, | |||
change.setProjectId(purchase.getProjectId()); | |||
change.setProjectCode(ProjectIdCodeCacheUtil.get(purchase.getProjectId())); | |||
change.setCreateOn(LocalDateTime.now()); | |||
StateMachine<TenderXcfhxApplyStatus, XcfhxStateChangeEvent> stateMachine = xcfhxStateMachineBuilder.build(); | |||
Message<XcfhxStateChangeEvent> message = MessageBuilder.withPayload(event) | |||
.setHeader(PURCHASE, purchase) | |||
.build(); | |||
//初始化状态机 | |||
StateMachinePersister<TenderXcfhxApplyStatus, XcfhxStateChangeEvent, Purchase> stateMachinePersister = xcfhxStateMachineBuilder.stateMachinePersister(); | |||
stateMachinePersister.restore(stateMachine, purchase); | |||
stateMachine.sendEvent(message); | |||
change.setAfterStatus(purchase.getXcfhxApplyStatus()); | |||
purchaseStatusChangeService.save(change); | |||
log.info("调用状态机后的标段状态为:{}", purchase.getXcfhxApplyStatus()); | |||
log.info("调用状态机后的标段状态为:{} ==> {}", change.getBeforeStatus(), change.getAfterStatus()); | |||
} | |||
} |
@@ -28,7 +28,6 @@ public class ThreadPoolUtil { | |||
static { | |||
ThreadPoolUtilProperties properties = SpringUtil.getBean(ThreadPoolUtilProperties.class); | |||
log.info("ThreadPoolUtilProperties:{}", properties); | |||
ThreadPoolProperties requestProps = properties.getRequest(); | |||
REQUEST = new MDCThreadPoolTaskExecutor(); | |||
REQUEST.setCorePoolSize(requestProps.getCorePoolSize()); | |||
@@ -1,5 +1,7 @@ | |||
package com.hz.pm.api.meeting.task; | |||
import com.hz.pm.api.common.config.ThreadPoolUtilProperties.ThreadPoolProperties; | |||
import com.hz.pm.api.common.util.MDCThreadPoolTaskScheduler; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | |||
@@ -16,13 +18,14 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | |||
public class ExpertInviteExecutorConfig { | |||
@Bean(name = "expertInviteScheduler") | |||
public ThreadPoolTaskScheduler threadPoolTaskScheduler() { | |||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); | |||
scheduler.setPoolSize(3); | |||
public ThreadPoolTaskScheduler threadPoolTaskScheduler(RandomInviteProperties properties) { | |||
ThreadPoolProperties threadPoolProperties = properties.getThreadPoolProperties(); | |||
MDCThreadPoolTaskScheduler scheduler = new MDCThreadPoolTaskScheduler(); | |||
scheduler.setPoolSize(threadPoolProperties.getCorePoolSize()); | |||
scheduler.setThreadGroupName("expert-invite"); | |||
scheduler.setThreadNamePrefix("invite-executor-"); | |||
scheduler.setAwaitTerminationSeconds(60); | |||
scheduler.setWaitForTasksToCompleteOnShutdown(true); | |||
scheduler.setThreadNamePrefix(threadPoolProperties.getThreadNamePrefix()); | |||
scheduler.setAwaitTerminationSeconds(120); | |||
scheduler.setWaitForTasksToCompleteOnShutdown(threadPoolProperties.getWaitForTasksToCompleteOnShutdown()); | |||
return scheduler; | |||
} | |||
@@ -48,13 +48,15 @@ public class MsgCallReplyRewriteTask { | |||
static { | |||
// 初始化线程池 | |||
EXECUTOR = new MDCThreadPoolTaskExecutor(); | |||
EXECUTOR.setBeanName("msgCallReplyRewriteExecutor"); | |||
EXECUTOR.setCorePoolSize(2); | |||
EXECUTOR.setMaxPoolSize(4); | |||
EXECUTOR.setQueueCapacity(100); | |||
EXECUTOR.setKeepAliveSeconds(120); | |||
EXECUTOR.setThreadPriority(Thread.NORM_PRIORITY); | |||
EXECUTOR.setThreadPriority(Thread.NORM_PRIORITY - 1); | |||
EXECUTOR.setWaitForTasksToCompleteOnShutdown(true); | |||
EXECUTOR.setThreadNamePrefix("callRewriteExecutor-"); | |||
EXECUTOR.setAllowCoreThreadTimeOut(true); | |||
EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); | |||
} | |||
@@ -1,7 +1,10 @@ | |||
package com.hz.pm.api.meeting.task; | |||
import com.hz.pm.api.common.config.ThreadPoolUtilProperties; | |||
import com.hz.pm.api.common.config.ThreadPoolUtilProperties.ThreadPoolProperties; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.boot.context.properties.NestedConfigurationProperty; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
@@ -56,4 +59,7 @@ public class RandomInviteProperties { | |||
private Integer inviteEndHour = 20; | |||
@NestedConfigurationProperty | |||
private ThreadPoolProperties threadPoolProperties; | |||
} |
@@ -224,4 +224,8 @@ thread-pool-util: | |||
thread-name-prefix: request-executor- | |||
scheduler: | |||
core-pool-size: 2 | |||
thread-name-prefix: scheduler-executor- | |||
thread-name-prefix: scheduler-executor- | |||
random-invite: | |||
thread-pool-properties: | |||
core-pool-size: 2 | |||
thread-name-prefix: expert-invite-executor- |
@@ -248,3 +248,7 @@ wflow-thread-pool-util: | |||
queue-capacity: 300 | |||
keep-alive-seconds: 120 | |||
max-pool-size: 8 | |||
random-invite: | |||
thread-pool-properties: | |||
core-pool-size: 3 | |||
thread-name-prefix: expert-invite-executor- |
@@ -0,0 +1,46 @@ | |||
package com.hz.pm.api.common; | |||
import com.hz.pm.api.AppTests; | |||
import com.hz.pm.api.common.statemachine.util.TenderStateMachineUtil; | |||
import com.hz.pm.api.common.statemachine.util.XcfhxStateMachineUtil; | |||
import com.hz.pm.api.common.util.ThreadPoolUtil; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import org.junit.Test; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import java.util.concurrent.CountDownLatch; | |||
/** | |||
* <p> | |||
* StateMachineTest | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 19:43 2024/8/29 | |||
*/ | |||
public class StateMachineTest extends AppTests { | |||
@Autowired | |||
private TenderStateMachineUtil tenderStateMachineUtil; | |||
@Autowired | |||
private XcfhxStateMachineUtil xcfhxStateMachineUtil; | |||
@Test | |||
public void test() { | |||
CountDownLatch count = new CountDownLatch(1000); | |||
for (int j = 0; j < 100; j++) { | |||
ThreadPoolUtil.REQUEST.execute(() -> { | |||
Purchase purchase = new Purchase(); | |||
purchase.setProjectId(3496L); | |||
for (int i = 0; i < 5; i++) { | |||
purchase.setBidType(i % 2 == 0 ? 2 : 1); | |||
purchase.setStatus(101); | |||
purchase.setXcfhxApplyStatus(301); | |||
xcfhxStateMachineUtil.pass(purchase); | |||
} | |||
count.countDown(); | |||
}); | |||
} | |||
} | |||
} |
@@ -16,7 +16,7 @@ spring: | |||
timeout: 5000 | |||
host: 47.98.125.47 | |||
port: 26379 | |||
database: 5 | |||
database: 7 | |||
password: Ndkj1234 | |||
jedis: | |||
pool: | |||
@@ -153,17 +153,6 @@ sa-token: | |||
# 是否输出操作日志 | |||
is-log: false | |||
yxt: | |||
# wsdl-url: http://115.239.137.23:9501/ws/v1?wsdl | |||
wsdl-url: classpath:/wsdl.xml | |||
#账号 | |||
user-code: hzndkj | |||
#密码 | |||
password: hzndkj@2021 | |||
#音信通开关 | |||
sms-enable: true | |||
tel-enable: true | |||
login: | |||
phone-verify-code: | |||
skip: true | |||
@@ -176,26 +165,63 @@ sync-mh-user: | |||
sync-mh-company: | |||
open: false | |||
mh: | |||
zwdd-work-notice: | |||
sso: | |||
client-id: ningda-74a5e5da-3bc3-414a-b9e6-004b7d87e310 | |||
client-secret: ningda-df746ce4-0c79-4242-b3c7-90ff8630c9742c6727cd-3ae7-48ae-87ad-2b39188ebabd | |||
sso: | |||
zwdd-work-notice: | |||
client-id: ningda-74a5e5da-3bc3-414a-b9e6-004b7d87e310 | |||
client-secret: ningda-df746ce4-0c79-4242-b3c7-90ff8630c9742c6727cd-3ae7-48ae-87ad-2b39188ebabd | |||
api-host: https://hzszxc.hzswb.cn:8443/mh-gateway/auth-single | |||
api-host: https://hzszxc.hzswb.cn:8443/test/mh-gateway/auth-single | |||
expert-qr-code-url: https://jiema.wwei.cn/uploads/2023/12/28/658d7a3f15f06.jpg | |||
file: | |||
down-url: https://weixin.hzszxc.hzswb.cn:8443/test/mh-gateway/oss/oss/previewFileLogin | |||
detail-url: https://weixin.hzszxc.hzswb.cn:8443/test/mh-gateway/oss/ossfile/getFileInfoList | |||
upload-url: https://weixin.hzszxc.hzswb.cn:8443/test/mh-gateway/oss/oss/uploadFileSkipLogin | |||
file-preview: | |||
public-host: http://ztzz2.hzswb.cn/yl | |||
auth-code: | |||
secret-key: nqkmzqojg5j4eiypr3rb8s7nb4noa8b2 | |||
agent-login: | |||
proxy: | |||
secret-key: nqkwiqojg7g4eiypr3rb8s7nb4noa8b2 | |||
# 短信服务地址 | |||
sms-send: | |||
host: http://10.54.38.13:8081/mh-gateway/auth-single | |||
# 电话服务地址 | |||
sms-client: | |||
host: http://10.54.38.13:8081/mh-gateway/auth-single | |||
open: false | |||
mobile-call: | |||
host: http://183.158.240.86:18181/blue_esl_api | |||
host: http://183.158.240.86:18181/blue_esl_api | |||
# 提醒任务 | |||
reminder-task: | |||
declared-record: | |||
open: false | |||
cron: 0 30 8 * * ? | |||
hz-pm: | |||
interfaceKey: hz_meeting_expert_info | |||
web: | |||
login: | |||
url: http://hzpm.ningdatech.com | |||
api: | |||
url: http://hzpm.ningdatech.com/hzpm | |||
expert-invite: | |||
skip-send-call: true | |||
skip-send-sms: true | |||
mh-system-replace-sync: | |||
open: false | |||
thread-pool-util: | |||
request: | |||
core-pool-size: 5 | |||
max-pool-size: 10 | |||
queue-capacity: 100 | |||
keep-alive-seconds: 120 | |||
thread-name-prefix: request-executor- | |||
scheduler: | |||
core-pool-size: 2 | |||
thread-name-prefix: scheduler-executor- |
@@ -103,7 +103,7 @@ | |||
<dependency> | |||
<groupId>org.springframework.statemachine</groupId> | |||
<artifactId>spring-statemachine-core</artifactId> | |||
<version>2.0.1.RELEASE</version> | |||
<version>2.2.0.RELEASE</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.oshi</groupId> | |||