package com.example.demo.framework.ability;
import com.example.demo.framework.model.AbilityAnnotation;
import com.example.demo.framework.model.ProductAnnotation;
@ProductAnnotation(productType = "animallife")
public class AnimalLifeProduct {
@AbilityAnnotation(abilityType = "eat")
public void eat(){
System.out.printf("animal eat");
}
@AbilityAnnotation(abilityType = "sleep")
public void sleep(){
System.out.println("animal sleep");
}
}
package com.example.demo.framework.ability;
import com.example.demo.framework.model.AbilityAnnotation;
import com.example.demo.framework.model.ProductAnnotation;
@ProductAnnotation(productType = "life")
public class LifeProduct {
@AbilityAnnotation(abilityType = "eat")
public void eat(){
System.out.printf("common eat");
}
@AbilityAnnotation(abilityType = "sleep")
public void sleep(){
System.out.println("common sleep");
}
}
package com.example.demo.framework.factory;
import com.example.demo.framework.model.AbilityContext;
public interface AFactory {
void eat(AbilityContext abilityContext);
void sleep(AbilityContext abilityContext);
}
package com.example.demo.framework.factory;
import com.example.demo.framework.ProductPipeline;
import com.example.demo.framework.model.AbilityContext;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component("AnimalFactory")
public class AnimalFactory implements AFactory{
@Autowired
private ProductPipeline productPipeline;
@Override
public void eat(AbilityContext abilityContext) {
List abilitys=new ArrayList<>();
abilitys.add(Pair.of("animallife","eat"));
productPipeline.executeAbilityList(abilityContext,abilitys);
}
@Override
public void sleep(AbilityContext abilityContext) {
List abilitys=new ArrayList<>();
abilitys.add(Pair.of("animallife","sleep"));
productPipeline.executeAbilityList(abilityContext,abilitys);
}
}
package com.example.demo.framework.factory;
import com.example.demo.framework.ProductPipeline;
import com.example.demo.framework.model.AbilityContext;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component("HumanAFactory")
public class HumanAFactory implements AFactory{
@Autowired
private ProductPipeline productPipeline;
@Override
public void eat(AbilityContext abilityContext) {
List abilitys=new ArrayList<>();
abilitys.add(Pair.of("life","eat"));
productPipeline.executeAbilityList(abilityContext,abilitys);
}
@Override
public void sleep(AbilityContext abilityContext) {
List abilitys=new ArrayList<>();
abilitys.add(Pair.of("life","sleep"));
productPipeline.executeAbilityList(abilityContext,abilitys);
}
}
package com.example.demo.framework.model;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AbilityAnnotation {
String abilityType();
}
package com.example.demo.framework.model;
public class AbilityContext {
}
package com.example.demo.framework.model;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Component
public @interface ProductAnnotation {
String productType();
}
package com.example.demo.framework;
import com.example.demo.framework.model.AbilityAnnotation;
import com.example.demo.framework.model.AbilityContext;
import com.example.demo.framework.model.ProductAnnotation;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Component
public class ProductPipeline implements ApplicationListener<ContextRefreshedEvent> {
private static final Map<String, Map<String,AbliityEntry>> PRODUCT_ABILITY_MAP=new HashMap<>();
private static ApplicationContext applicationContext;
private CommonBizProcessTemplate commonBizProcessTemplate;
public void executeAbilityiesWithLog(AbliityContext context,boolean needRetryTask,boolean needRollBack,List<Pair<String,String>){
commonBizProcessTemplate.executeWithLog(new CommonBizCallBack(){
protected booelan preCheck(){
// 根据业务id获取所有进行中的流水,互斥校验
}
protected inirBizLog(){
return new CommonLogmodel();
}
protect void process(){
List<Pair<String,String>> executeMap=new ArrayList<>();
try{
for(Pair<String,String> entry:abilityMap){
if(StringUtils.isBlank(entry.getKey())||StringUtils.isBlank(entry.getValue())){
continue;
}
executeAbility(abilityContext,entry.getValue(),entry.getKey());
executeMap.add(entry);
}
}catch(BizException e)
if(e.getNeedReyry()&&needRetryTask){
saveFailedScene(getRemainAbliites(abilityMap,executeMap));
}
if(!e.getNeedReyry()){
if(needRollBack){
sendRollbackMsg(commonLog);
}
throw e;
}
}catch(Exception){
if(needRetryTask){
saveFailedScene(getRemainAbliites(abilityMap,executeMap));
throw e;
}
}
})
}
priavte void saveFailScene(List<String> remainAbilities,AbiolityContext context){
if(remainAbilities==null){
return;
}
TaskModel taskModel=new taskModel();
taskModel.setTaskStatus(INIT);
taskMode.setRetryCnt(0);
taskModel.setGmtFire(new Date());
taskModel.setbizId()
taskModel.seyBizType();
taskMode.setTaskParam(remainAbilities)
taskManager.registerTask(TaskModel);
}
private List<String> getRemainAbliites(List<Pair<String,String>> avilityMap,List<Pair<String,String>> executeMap){
List<String> remainAbilityies=new ArrayList();
if(executeMap.size()!=avilityMap.size()){
for(<Pair<String,String> entry:avilityMap){
if(executeMap.contains(entry)){
continue;
}
remainAbilityies.add(entry.getKey()+":"+entry.getValue());
}
}
return remainAbilityies;
}
public void executeAbilityList(AbilityContext abilityContext, List<Pair<String,String>> abilityMap){
if(CollectionUtils.isEmpty(abilityMap)){
return;
}
for(Pair<String,String> entry:abilityMap){
if(StringUtils.isBlank(entry.getKey())||StringUtils.isBlank(entry.getValue())){
continue;
}
executeAbility(abilityContext,entry.getValue(),entry.getKey());
}
}
private void executeAbility(AbilityContext abilityContext, String abilityType, String productType) {
if(PRODUCT_ABILITY_MAP==null){
return;
}
Map<String, AbliityEntry> abilitys = PRODUCT_ABILITY_MAP.get(productType);
if(abilitys==null){
//抛异常
}
AbliityEntry abliityEntry = abilitys.get(abilityType);
try{
Object product=applicationContext.getBean(abliityEntry.productBean);
abliityEntry.getAbilityMethod().invoke(product,abilityContext);
}catch (Exception e){
}
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent()!=null){
return;
}
try{
Map<String,Object> objectMap=event.getApplicationContext().getBeansWithAnnotation(ProductAnnotation.class);
if(objectMap!=null&&objectMap.size()!=0){
for(Map.Entry<String,Object> entry:objectMap.entrySet()){
Object extProduct=entry.getValue();
if(Objects.isNull(extProduct)){
continue;
}
ProductAnnotation productAnnotation= AnnotationUtils.findAnnotation(extProduct.getClass(),ProductAnnotation.class);
if(Objects.isNull(productAnnotation)){
continue;
}
String productType=productAnnotation.productType();
Map<String, AbliityEntry> abilitys = PRODUCT_ABILITY_MAP.get(productType);
if(abilitys==null){
abilitys=new HashMap<>();
}
Method[] methods=extProduct.getClass().getMethods();
for(Method method:methods){
if(method.isAnnotationPresent(AbilityAnnotation.class)) {
AbilityAnnotation abilityAnnotation=method.getAnnotation(AbilityAnnotation.class);
if(Objects.isNull(abilityAnnotation)&&abilityAnnotation.abilityType()!=null){
AbliityEntry abliityEntry=new AbliityEntry();
abliityEntry.setProductBean(entry.getKey());
abliityEntry.setAbilityMethod(method);
abilitys.put(abilityAnnotation.abilityType(),abliityEntry);
}
}
}
PRODUCT_ABILITY_MAP.put(productType,abilitys);
}
}
applicationContext=event.getApplicationContext();
}catch (Exception e){
throw e;
}
}
class AbliityEntry{
String productBean;
Method abilityMethod;
public String getProductBean() {
return productBean;
}
public void setProductBean(String productBean) {
this.productBean = productBean;
}
public Method getAbilityMethod() {
return abilityMethod;
}
public void setAbilityMethod(Method abilityMethod) {
this.abilityMethod = abilityMethod;
}
}
}
package com.example.demo.task;
import com.example.demo.task.model.ExecuteModeEnum;
import com.example.demo.task.model.TaskContext;
import java.util.List;
public interface TaskEngine {
String registerAndTrigger(TaskContext taskContext);
String register(TaskContext taskContext);
void trigger(TaskContext taskContext);
void trigger(String taskId, ExecuteModeEnum executeMode);
void batchTrigger(List<String> taskIds, ExecuteModeEnum executeModeEnum);
}
package com.example.demo.task;
import com.example.demo.task.model.TaskContext;
public interface TaskExecutor {
void execute(TaskContext taskContext);
boolean support(TaskContext taskContext);
}
package com.example.demo.task;
import com.example.demo.task.model.TaskStrategy;
import java.util.Date;
public class TaskHelper {
public static Date computeRetryFireTime(TaskStrategy taskStrategy){
int interval= taskStrategy.getInterval();
Date gmtNextFire=new Date(System.currentTimeMillis() + (interval*60*1000));
return gmtNextFire;
}
}
package com.example.demo.task;
import com.example.demo.task.model.TaskModel;
public interface TaskRepositiry {
String insertTask(TaskModel taskModel);
TaskModel lockByTaskId(String taskId);
int updateStatus(TaskModel taskModel);
TaskModel getTaskById(String taskId);
}
package com.example.demo.task.model;
public class CommonTaskParam {
private String requestId;
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
}
package com.example.demo.task.model;
import org.apache.commons.lang3.StringUtils;
public enum ExecuteModeEnum {
SYNC("SYNC","同步"),
ASYNC("ASYNC","异步"),
;
private String code;
private String desc;
public static ExecuteModeEnum getByCode(String code){
if(StringUtils.isBlank(code)){
return null;
}
for(ExecuteModeEnum modeEnum:values()){
if(StringUtils.equals(modeEnum.getCode(),code)){
return modeEnum;
}
}
return null;
}
ExecuteModeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.example.demo.task.model;
import java.util.Date;
public class Task {
private String taskId;
private String uniqueId;
private String bizId;
private String bizTaskType;
private String bizTaskStatus;
private String taskParam;
private Date gmtFire;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getUniqueId() {
return uniqueId;
}
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
public String getBizId() {
return bizId;
}
public void setBizId(String bizId) {
this.bizId = bizId;
}
public String getBizTaskType() {
return bizTaskType;
}
public void setBizTaskType(String bizTaskType) {
this.bizTaskType = bizTaskType;
}
public String getBizTaskStatus() {
return bizTaskStatus;
}
public void setBizTaskStatus(String bizTaskStatus) {
this.bizTaskStatus = bizTaskStatus;
}
public String getTaskParam() {
return taskParam;
}
public void setTaskParam(String taskParam) {
this.taskParam = taskParam;
}
public Date getGmtFire() {
return gmtFire;
}
public void setGmtFire(Date gmtFire) {
this.gmtFire = gmtFire;
}
}
package com.example.demo.task.model;
public class TaskContext {
private Task task;
private ExecuteModeEnum executeMode=ExecuteModeEnum.ASYNC;
private TaskResult result;
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
public ExecuteModeEnum getExecuteMode() {
return executeMode;
}
public void setExecuteMode(ExecuteModeEnum executeMode) {
this.executeMode = executeMode;
}
public TaskResult getResult() {
return result;
}
public void setResult(TaskResult result) {
this.result = result;
}
}
package com.example.demo.task.model;
import java.util.Date;
public class TaskModel {
private String taskId;
private String uniqueId;
private String bizId;
private String bizType;
private String taskStatus;
private Integer retryCnt;
private String machineName;
private String taskParam;
private Date gmtFire;
private String memo;
private Date gmtCreate;
private Date gmtModified;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getUniqueId() {
return uniqueId;
}
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
public String getBizId() {
return bizId;
}
public void setBizId(String bizId) {
this.bizId = bizId;
}
public String getBizType() {
return bizType;
}
public void setBizType(String bizType) {
this.bizType = bizType;
}
public String getTaskStatus() {
return taskStatus;
}
public void setTaskStatus(String taskStatus) {
this.taskStatus = taskStatus;
}
public Integer getRetryCnt() {
return retryCnt;
}
public void setRetryCnt(Integer retryCnt) {
this.retryCnt = retryCnt;
}
public String getMachineName() {
return machineName;
}
public void setMachineName(String machineName) {
this.machineName = machineName;
}
public String getTaskParam() {
return taskParam;
}
public void setTaskParam(String taskParam) {
this.taskParam = taskParam;
}
public Date getGmtFire() {
return gmtFire;
}
public void setGmtFire(Date gmtFire) {
this.gmtFire = gmtFire;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
public Date getGmtCreate() {
return gmtCreate;
}
public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}
public Date getGmtModified() {
return gmtModified;
}
public void setGmtModified(Date gmtModified) {
this.gmtModified = gmtModified;
}
}
package com.example.demo.task.model;
public class TaskResult {
private boolean success=false;
private boolean needRetry;
private String errorCode;
private String memo;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public boolean isNeedRetry() {
return needRetry;
}
public void setNeedRetry(boolean needRetry) {
this.needRetry = needRetry;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
}
package com.example.demo.task.model;
import org.apache.commons.lang3.StringUtils;
public enum TaskStatusEnum {
INIT("INIT","初始化"),
PROCESSING("PROCESSING","处理中"),
RETRY("RETRY","重试"),
TIMEOUT("TIMEOUT","超时"),
SUCCESS("SUCCESS","成功"),
FAILURE("FAILURE","失败"),
;
private String code;
private String desc;
public static TaskStatusEnum getByCode(String code){
if(StringUtils.isBlank(code)){
return null;
}
for(TaskStatusEnum modeEnum:values()){
if(StringUtils.equals(modeEnum.getCode(),code)){
return modeEnum;
}
}
return null;
}
TaskStatusEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.example.demo.task.model;
import java.util.ArrayList;
import java.util.List;
public class TaskStrategy {
/**
* 任务超时时间 30天
*/
private int timeout=30;
/**
* 任务最大重试次数
*/
private int maxRetryCnt=100;
/**
* 一次捞取数据行数
*/
private int maxRow=100;
/**
* 业务分片
*/
private int partitionSize=1;
/**
* 重试间隔
*/
private int interval=1;
/**
* 任务处理的时间
*/
private int maxProcessTime=60;
/**
* 任务处理的状态
*/
private List<String> taskStatus=new ArrayList<>();
{
taskStatus.add("INIT");
taskStatus.add("RETRY");
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getMaxRetryCnt() {
return maxRetryCnt;
}
public void setMaxRetryCnt(int maxRetryCnt) {
this.maxRetryCnt = maxRetryCnt;
}
public int getMaxRow() {
return maxRow;
}
public void setMaxRow(int maxRow) {
this.maxRow = maxRow;
}
public int getPartitionSize() {
return partitionSize;
}
public void setPartitionSize(int partitionSize) {
this.partitionSize = partitionSize;
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public int getMaxProcessTime() {
return maxProcessTime;
}
public void setMaxProcessTime(int maxProcessTime) {
this.maxProcessTime = maxProcessTime;
}
public List<String> getTaskStatus() {
return taskStatus;
}
public void setTaskStatus(List<String> taskStatus) {
this.taskStatus = taskStatus;
}
}
package com.example.demo.task.impl;
import com.example.demo.task.TaskEngine;
import com.example.demo.task.TaskExecutor;
import com.example.demo.task.TaskHelper;
import com.example.demo.task.TaskRepositiry;
import com.example.demo.task.model.*;
import com.example.demo.transaction.TransactionSynchronizationHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadPoolExecutor;
@Component
public class TaskEngineImpl implements TaskEngine {
@Autowired
private TaskRepositiry taskRepositiry;
private TransactionTemplate transactionTemplate;
@Autowired
private ThreadPoolExecutor taskExecutor;
@Autowired
private List<TaskExecutor> executors;
private String doRegister(TaskContext taskContext){
if(Objects.isNull(taskContext)){
//throw new Exception("");
}
if(Objects.isNull(taskContext.getTask())){
//throw new Exception("");
}
Task task=taskContext.getTask();
TaskResult result=taskContext.getResult();
if(Objects.isNull(result)){
result=new TaskResult();
taskContext.setResult(result);
}
try{
String taskId=transactionTemplate.execute(status->{
task.setBizTaskType(TaskStatusEnum.INIT.getCode());
TaskModel taskModel=generateTaskModel(task);
String newTaskId = taskRepositiry.insertTask(taskModel);
task.setTaskId(newTaskId);
return newTaskId;
});
setSuccessTaskResult(result,"创建任务成功");
return taskId;
}catch (Throwable e){
setFailTaskResult(result,e,true);
throw e;
}
}
private void doTrigger(TaskContext taskContext){
ExecuteModeEnum executeModeEnum=taskContext.getExecuteMode();
if(ExecuteModeEnum.SYNC==executeModeEnum){
doExecute(taskContext);
}else {
taskExecutor.execute(()->{
doExecute(taskContext);
});
}
}
private void doExecute(TaskContext taskContext) {
long start=System.currentTimeMillis();
Task task=taskContext.getTask();
TaskResult result=taskContext.getResult();
if(Objects.isNull(result)){
result=new TaskResult();
taskContext.setResult(result);
}
TaskModel taskModel=null;
try {
taskModel=getTask(task.getTaskId());
if(CollectionUtils.isEmpty(executors)){
//throw new Exception("执行器列表为空");
}
Optional<TaskExecutor> executorOptional = executors.stream().filter(executor -> executor.support(taskContext))
.findFirst();
if(!executorOptional.isPresent()){
//throw new Exception("执行器为空");
}
executorOptional.get().execute(taskContext);
result.setSuccess(true);
}catch (Throwable e){
setFailTaskResult(result,e,true);
}finally {
doAfterExecute(taskContext);
}
}
private void doAfterExecute(TaskContext taskContext) {
String taskId=taskContext.getTask().getTaskId();
transactionTemplate.execute(status->{
TaskModel taskModel=taskRepositiry.lockByTaskId(taskId);
TaskStatusEnum taskStatus = TaskStatusEnum.getByCode(taskModel.getTaskStatus());
if(taskStatus==TaskStatusEnum.FAILURE||taskStatus==TaskStatusEnum.SUCCESS){
return true;
};
TaskResult result=taskContext.getResult();
if(result.isSuccess()){
taskModel.setTaskStatus(TaskStatusEnum.SUCCESS.getCode());
taskRepositiry.updateStatus(taskModel);
}else {
boolean needRetry=result.isNeedRetry();
if(needRetry){
TaskStrategy taskStrategy=new TaskStrategy();
taskModel.setRetryCnt(taskModel.getRetryCnt()+1);
taskModel.setTaskStatus(TaskStatusEnum.RETRY.getCode());
taskModel.setGmtFire(TaskHelper.computeRetryFireTime(taskStrategy));
taskRepositiry.updateStatus(taskModel);
}else {
taskModel.setTaskStatus(TaskStatusEnum.FAILURE.getCode());
taskRepositiry.updateStatus(taskModel);
}
}
return true;
});
}
private TaskModel getTask(String taskId){
return transactionTemplate.execute(status->{
TaskModel taskModel=taskRepositiry.lockByTaskId(taskId);
if(Objects.isNull(taskModel)){
//throw new Exception("");
}
TaskStrategy taskStrategy=new TaskStrategy();
TaskStatusEnum taskStatusEnum=TaskStatusEnum.getByCode(taskModel.getTaskStatus());
if(taskStatusEnum==TaskStatusEnum.PROCESSING){
//throw new Exception("任务正在处理");
}
if(taskStatusEnum==TaskStatusEnum.SUCCESS){
//throw new Exception("任务已经成功了");
}
if(!(taskStatusEnum==TaskStatusEnum.INIT || taskStatusEnum==TaskStatusEnum.RETRY)){
//throw new Exception("任务状态不对不处理");
}
//任务超时执行
if(DateUtils.addDays(taskModel.getGmtCreate(),taskStrategy.getTimeout()).getTime()<System.currentTimeMillis()){
taskModel.setTaskStatus(TaskStatusEnum.TIMEOUT.getCode());
taskRepositiry.updateStatus(taskModel);
//throw new Exception("任务执行超时");
}
taskModel.setTaskStatus(TaskStatusEnum.PROCESSING.getCode());
if(taskRepositiry.updateStatus(taskModel)!=1){
//throw new Exception("任务状态更新失败");
}
return taskModel;
});
}
private void setSuccessTaskResult(TaskResult result,String memo){
result.setSuccess(true);
result.setMemo(memo);
}
private void setFailTaskResult(TaskResult result,Throwable e,boolean needRetry){
result.setNeedRetry(needRetry);
result.setSuccess(false);
result.setMemo(StringUtils.substring(e.getMessage(),0,1024));
}
private TaskModel generateTaskModel(Task task){
TaskModel taskModel=new TaskModel();
taskModel.setTaskId(task.getTaskId());
taskModel.setBizId(task.getBizId());
taskModel.setBizType(task.getBizTaskType());
taskModel.setTaskStatus(task.getBizTaskStatus());
taskModel.setMachineName("");
taskModel.setUniqueId(task.getUniqueId());
taskModel.setTaskParam(task.getTaskParam());
taskModel.setGmtFire(Objects.isNull(task.getGmtFire())?new Date():task.getGmtFire());
taskModel.setRetryCnt(0);
return taskModel;
}
@Override
public String registerAndTrigger(TaskContext taskContext) {
String taskId=doRegister(taskContext);
if(Objects.nonNull(taskContext.getResult())&&taskContext.getResult().isSuccess()){
TransactionSynchronizationHelper.doAfterCommit(()->doRegister(taskContext));
}
return taskId;
}
@Override
public String register(TaskContext taskContext) {
return doRegister(taskContext);
}
@Override
public void trigger(TaskContext taskContext) {
doTrigger(taskContext);
}
private TaskModel buidTaskModel(String taskId){
TaskModel taskModel=taskRepositiry.getTaskById(taskId);
return taskModel;
}
@Override
public void trigger(String taskId, ExecuteModeEnum executeMode) {
TaskModel taskModel=buidTaskModel(taskId);
TaskContext taskContext=new TaskContext();
Task task=new Task();
task.setBizId(taskModel.getBizId());
task.setUniqueId(taskModel.getUniqueId());
task.setBizTaskType(taskModel.getBizType());
task.setTaskId(taskModel.getTaskId());
task.setBizTaskStatus(taskModel.getTaskStatus());
taskContext.setExecuteMode(executeMode);
String jsonParam=taskModel.getTaskParam();
task.setTaskParam(jsonParam);
taskContext.setTask(task);
trigger(taskContext);
}
@Override
public void batchTrigger(List<String> taskIds, ExecuteModeEnum executeModeEnum) {
if(!CollectionUtils.isEmpty(taskIds)){
taskIds.stream().forEach(taskId->{
trigger(taskId,executeModeEnum);
});
}
}
}
package com.example.demo.transaction;
public interface AfterCommitCallBack {
void doAfterCommit();
}
package com.example.demo.transaction;
public interface AfterCompletionCallback {
void doAfterCompletion();
}
package com.example.demo.transaction;
public class TransactionSynchronizationHelper {
public static void doAfterCommit(AfterCommitCallBack commitCallBack){
if(TransactionSynchronizationManager.isActuralTransactionActive()){
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
public void afterCommit(){
commitCallBack.doAfterCommit();;
}
});
}else {
commitCallBack.doAfterCommit();
}
}
public static void doAfterCompletion(AfterCompletionCallback commitCallBack){
if(TransactionSynchronizationManager.isActuralTransactionActive()){
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
public void afterCommit(){
commitCallBack.doAfterCommit();;
}
});
}else {
commitCallBack.doAfterCommit();
}
}
}
public abstract class CommonBizCallBack{
protected abstract CommonLogModel initBizLog();
protected abstract void process();
protected boolean precheck(){
retrun true;
}
}
@service
public class CommonBizProcessTemplate{
@Autwire
private Transactiontemplate transactiontemplate;
@Autwire
priavte CommonLogRepository commonnLogRepository;
@Autwire
private Message message;
@Autwire
private DistributeLock distributeLock;
public void executeWityLog(CommonBizCallBack callback){
if(!callback,precheck()){
return;
}
CommonLogModel logmodel=callback.initBizLog();
if(logmodel==null){
return;
}
boolean locked=false;
String lockKey=logmodel.getLogId()+"_log";
try{
logModel=createInitLog(callback);
locked=distributeLock.lock(lockKey,30);
if(!locked){
throw new BizExeption("加锁失败");
}
callback.process();
logmodel.setStatus("SUCCESS");
commonnLogRepository.update(logmodel);
}catch(BizException e){
if(!e.getNeedRetry()){
logModel.setStatus("FAILED");
}
if(StringUtils.isnotblacn(e.getmessage())){
logModel.setMemo(e.getMessage());
}
commonnLogRepository.update(logmodel);
throw el
}
catch(SysException e){
if(StringUtils.isnotblacn(e.getmessage())){
logModel.setMemo(e.getMessage());
}
commonnLogRepository.update(logmodel);
throw e;
}
catch(Exception e){
if(StringUtils.isnotblacn(e.getmessage())){
logModel.setMemo(e.getMessage());
}
commonnLogRepository.update(logmodel);
throw e;
}finally{
if(locked){
distributeLock.unlock(locked);
}
}
}
}
状态 DOING,SUCCESS,FAILURED
public CommonLogModel createInitLog(CommonBizCallBack callBack){
CommonLogModel model=callBack.initBizLog();
model.setStatus(DOING);
mode.setVersion(new Date().getTime());
一查 二判断 三插入
业务属性查询
CommonLogModel queryLog=commonLogRepository.query(bizType,bizId,BizUnique);
if(queryLog!=null){
checkUdmponent(queryLog);
model.setLogId(queryLog.getLogId);
return model;
}
try{
String logId=commonLogRepository.insert(model);
}catch(Exception ){
//解决再次冲突
model=commonLogRepository.query(bizType,bizId,BizUnique);
checkUdmponent(model);
}
return model;
}
public void checkUdmponent(CommonLogModel model){
if(model==null){
thew new BizException("")
}
if(model.getStats()==SUCCESS){
thew new BizException (IDMPONENT,false);
}
if(model.getStatus==FAILED){
thew new BizException (IDMPONENT,false);
}
}
流水表 common_log
id,uniqueid,bizsource,biz_id,biz_type,bizunique,version,status,extinfo
uk(id)
uk(unqieid,biztype,bizunique)
普通索引(bizid,biztype)
任务表biz_task
id,taskid,uniqueid,bizid,biztype,taskstatus,retrucnt,machinename,taskparam,memo,gmrfire,extinfo,result
uk(taskid)
uk(uniqueid.biztype)