wangwei пре 7 година
родитељ
комит
6e7aa5256d

+ 22 - 4
examcloud-task-base/src/main/java/cn/com/qmth/examcloud/task/base/AbstractTask.java

@@ -1,5 +1,7 @@
 package cn.com.qmth.examcloud.task.base;
 
+import org.quartz.JobExecutionContext;
+
 import cn.com.qmth.examcloud.commons.base.exception.ExamCloudRuntimeException;
 import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLogFactory;
@@ -18,26 +20,42 @@ public abstract class AbstractTask implements Task {
 
 	protected ExamCloudLog debugLog = ExamCloudLogFactory.getLog(this.getClass());
 
+	public abstract TaskTracker getTaskTracker();
+
+	public abstract void run(ScheduleJob scheduleJob) throws Exception;
+
 	@Override
-	public void execute(ScheduleJob scheduleJob) {
+	public void execute(JobExecutionContext context, ScheduleJob scheduleJob, String traceId) {
+		try {
+			getTaskTracker().start(context, scheduleJob, traceId);
+		} catch (Exception e) {
+			taskLog.error("[TASK TRACKER]. start", e);
+		}
 		if (taskLog.isDebugEnabled()) {
 			taskLog.debug("[TASK IN]. detail: " + JsonUtil.toJson(scheduleJob));
 		}
 		try {
 			run(scheduleJob);
 		} catch (Exception e) {
+			try {
+				getTaskTracker().whenException(context, scheduleJob, traceId, e);
+			} catch (Exception ex) {
+				taskLog.error("[TASK TRACKER]. whenException", ex);
+			}
 			if (taskLog.isErrorEnabled()) {
 				taskLog.error("[TASK EXCEPTION]. detail: " + JsonUtil.toJson(scheduleJob), e);
 			}
 			throw new ExamCloudRuntimeException(e);
 		}
-
+		try {
+			getTaskTracker().onEnd(context, scheduleJob, traceId);
+		} catch (Exception e) {
+			taskLog.error("[TASK TRACKER]. onEnd", e);
+		}
 		if (taskLog.isDebugEnabled()) {
 			taskLog.debug("[TASK OUT]. detail: " + JsonUtil.toJson(scheduleJob));
 		}
 
 	}
 
-	public abstract void run(ScheduleJob scheduleJob) throws Exception;
-
 }

+ 9 - 15
examcloud-task-base/src/main/java/cn/com/qmth/examcloud/task/base/DistributionJob.java

@@ -7,9 +7,9 @@ import org.quartz.JobExecutionException;
 import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.base.util.JsonUtil;
+import cn.com.qmth.examcloud.commons.base.util.ThreadLocalUtil;
 import cn.com.qmth.examcloud.commons.web.support.SpringContextHolder;
 
-
 /**
  * 并行任务分发器
  *
@@ -17,31 +17,25 @@ import cn.com.qmth.examcloud.commons.web.support.SpringContextHolder;
  * @date 2018年3月7日
  * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
  */
-public class DistributionJob implements Job
-{
+public class DistributionJob implements Job {
 	private static final ExamCloudLog TASK_LOG = ExamCloudLogFactory.getLog("TASK_LOGGER");
 
 	@Override
-	public void execute(JobExecutionContext context) throws JobExecutionException
-	{
+	public void execute(JobExecutionContext context) throws JobExecutionException {
+		String traceId = ThreadLocalUtil.next();
 		ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
 
-		if (TASK_LOG.isDebugEnabled())
-		{
+		if (TASK_LOG.isDebugEnabled()) {
 			TASK_LOG.debug("distribute job. job detail :" + JsonUtil.toJson(scheduleJob));
 		}
 
-		try
-		{
+		try {
 			Object bean = SpringContextHolder.getBean(scheduleJob.getSpringBean());
 
 			Task task = (Task) bean;
-			task.execute(scheduleJob);
-		}
-		catch (Exception e)
-		{
-			if (TASK_LOG.isErrorEnabled())
-			{
+			task.execute(context, scheduleJob, traceId);
+		} catch (Exception e) {
+			if (TASK_LOG.isErrorEnabled()) {
 				TASK_LOG.error(
 						"fail to distribute job. job detail :" + JsonUtil.toJson(scheduleJob), e);
 			}

+ 38 - 84
examcloud-task-base/src/main/java/cn/com/qmth/examcloud/task/base/QuartzManager.java

@@ -26,7 +26,6 @@ import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLog;
 import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.base.util.JsonUtil;
 
-
 /**
  * Quartz 管理器
  *
@@ -35,8 +34,7 @@ import cn.com.qmth.examcloud.commons.base.util.JsonUtil;
  * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
  */
 @Component
-public class QuartzManager
-{
+public class QuartzManager {
 	private static final ExamCloudLog TASK_LOG = ExamCloudLogFactory.getLog("TASK_LOGGER");
 
 	@Autowired
@@ -48,22 +46,18 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param job
 	 */
-	public void addJob(ScheduleJob job)
-	{
-		if (TASK_LOG.isDebugEnabled())
-		{
+	public void addJob(ScheduleJob job) {
+		if (TASK_LOG.isDebugEnabled()) {
 			TASK_LOG.debug("add a job. job detail: " + JsonUtil.toJson(job));
 		}
 
-		try
-		{
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
 
 			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
 
-			if (null == trigger)
-			{
+			if (null == trigger) {
 				Class<? extends Job> jobClass = job.isStateful()
 						? StatefulDistributionJob.class
 						: DistributionJob.class;
@@ -80,9 +74,7 @@ public class QuartzManager
 						.withSchedule(scheduleBuilder).build();
 
 				scheduler.scheduleJob(jobDetail, trigger);
-			}
-			else
-			{
+			} else {
 				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
 						.cronSchedule(job.getCronExpression());
 
@@ -91,15 +83,12 @@ public class QuartzManager
 
 				scheduler.rescheduleJob(triggerKey, trigger);
 			}
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to add a job. job detail: " + JsonUtil.toJson(job), e);
 			throw new ExamCloudRuntimeException(e);
 		}
 
-		if (TASK_LOG.isDebugEnabled())
-		{
+		if (TASK_LOG.isDebugEnabled()) {
 			TASK_LOG.debug("add a job successfully. job detail: " + JsonUtil.toJson(job));
 		}
 	}
@@ -110,27 +99,21 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @return
 	 */
-	public List<ScheduleJob> getAllJobs()
-	{
-		try
-		{
+	public List<ScheduleJob> getAllJobs() {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
 			Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
 			List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
-			for (JobKey jobKey : jobKeys)
-			{
+			for (JobKey jobKey : jobKeys) {
 				List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
-				for (Trigger trigger : triggers)
-				{
+				for (Trigger trigger : triggers) {
 					ScheduleJob job = new ScheduleJob();
 					job.setJobName(jobKey.getName());
 					job.setJobGroup(jobKey.getGroup());
-					job.setDescription("触发器:" + trigger.getKey());
 					Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
-					job.setJobStatus(triggerState.name());
-					if (trigger instanceof CronTrigger)
-					{
+					job.setTriggerState(triggerState.name());
+					if (trigger instanceof CronTrigger) {
 						CronTrigger cronTrigger = (CronTrigger) trigger;
 						String cronExpression = cronTrigger.getCronExpression();
 						job.setCronExpression(cronExpression);
@@ -139,9 +122,7 @@ public class QuartzManager
 				}
 			}
 			return jobList;
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to get all jobs.", e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -153,26 +134,21 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @return
 	 */
-	public List<ScheduleJob> getRunningJobs()
-	{
-		try
-		{
+	public List<ScheduleJob> getRunningJobs() {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
 			List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
-			for (JobExecutionContext executingJob : executingJobs)
-			{
+			for (JobExecutionContext context : executingJobs) {
 				ScheduleJob job = new ScheduleJob();
-				JobDetail jobDetail = executingJob.getJobDetail();
+				JobDetail jobDetail = context.getJobDetail();
 				JobKey jobKey = jobDetail.getKey();
-				Trigger trigger = executingJob.getTrigger();
+				Trigger trigger = context.getTrigger();
 				job.setJobName(jobKey.getName());
 				job.setJobGroup(jobKey.getGroup());
-				job.setDescription("触发器:" + trigger.getKey());
 				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
-				job.setJobStatus(triggerState.name());
-				if (trigger instanceof CronTrigger)
-				{
+				job.setTriggerState(triggerState.name());
+				if (trigger instanceof CronTrigger) {
 					CronTrigger cronTrigger = (CronTrigger) trigger;
 					String cronExpression = cronTrigger.getCronExpression();
 					job.setCronExpression(cronExpression);
@@ -180,9 +156,7 @@ public class QuartzManager
 				jobList.add(job);
 			}
 			return jobList;
-		}
-		catch (Exception e)
-		{
+		} catch (Exception e) {
 			TASK_LOG.error("Fail to get running jobs.", e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -194,16 +168,12 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param scheduleJob
 	 */
-	public void pauseJob(ScheduleJob scheduleJob)
-	{
-		try
-		{
+	public void pauseJob(ScheduleJob scheduleJob) {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
 			scheduler.pauseJob(jobKey);
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to pause Job. job detail: " + JsonUtil.toJson(scheduleJob), e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -215,16 +185,12 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param scheduleJob
 	 */
-	public void resumeJob(ScheduleJob scheduleJob)
-	{
-		try
-		{
+	public void resumeJob(ScheduleJob scheduleJob) {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
 			scheduler.resumeJob(jobKey);
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to resume job. job detail: " + JsonUtil.toJson(scheduleJob), e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -236,16 +202,12 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param scheduleJob
 	 */
-	public void deleteJob(ScheduleJob scheduleJob)
-	{
-		try
-		{
+	public void deleteJob(ScheduleJob scheduleJob) {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
 			scheduler.deleteJob(jobKey);
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to delete job. job detail: " + JsonUtil.toJson(scheduleJob), e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -258,16 +220,12 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param scheduleJob
 	 */
-	public void runJob(ScheduleJob scheduleJob)
-	{
-		try
-		{
+	public void runJob(ScheduleJob scheduleJob) {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 			JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
 			scheduler.triggerJob(jobKey);
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to run job. job detail: " + JsonUtil.toJson(scheduleJob), e);
 			throw new ExamCloudRuntimeException(e);
 		}
@@ -279,10 +237,8 @@ public class QuartzManager
 	 * @author WANGWEI
 	 * @param scheduleJob
 	 */
-	public void updateJobCronExpression(ScheduleJob scheduleJob)
-	{
-		try
-		{
+	public void updateJobCronExpression(ScheduleJob scheduleJob) {
+		try {
 			Scheduler scheduler = schedulerFactoryBean.getScheduler();
 
 			TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(),
@@ -297,9 +253,7 @@ public class QuartzManager
 					.withSchedule(scheduleBuilder).build();
 
 			scheduler.rescheduleJob(triggerKey, trigger);
-		}
-		catch (SchedulerException e)
-		{
+		} catch (SchedulerException e) {
 			TASK_LOG.error("Fail to update job cron expression. job detail :"
 					+ JsonUtil.toJson(scheduleJob), e);
 			throw new ExamCloudRuntimeException(e);

+ 16 - 6
examcloud-task-base/src/main/java/cn/com/qmth/examcloud/task/base/ScheduleJob.java

@@ -12,6 +12,8 @@ import java.io.Serializable;
 public class ScheduleJob implements Serializable {
 	private static final long serialVersionUID = -1638993747996917970L;
 
+	private Long jobId;
+
 	/**
 	 * 任务名称
 	 */
@@ -23,9 +25,9 @@ public class ScheduleJob implements Serializable {
 	private String jobGroup;
 
 	/**
-	 * 任务状态
+	 * 触发器状态
 	 */
-	private String jobStatus;
+	private String triggerState;
 
 	/**
 	 * cron表达式
@@ -47,6 +49,14 @@ public class ScheduleJob implements Serializable {
 	 */
 	private boolean stateful = true;
 
+	public Long getJobId() {
+		return jobId;
+	}
+
+	public void setJobId(Long jobId) {
+		this.jobId = jobId;
+	}
+
 	public String getJobName() {
 		return jobName;
 	}
@@ -63,12 +73,12 @@ public class ScheduleJob implements Serializable {
 		this.jobGroup = jobGroup;
 	}
 
-	public String getJobStatus() {
-		return jobStatus;
+	public String getTriggerState() {
+		return triggerState;
 	}
 
-	public void setJobStatus(String jobStatus) {
-		this.jobStatus = jobStatus;
+	public void setTriggerState(String triggerState) {
+		this.triggerState = triggerState;
 	}
 
 	public String getCronExpression() {

+ 7 - 3
examcloud-task-base/src/main/java/cn/com/qmth/examcloud/task/base/Task.java

@@ -1,5 +1,7 @@
 package cn.com.qmth.examcloud.task.base;
 
+import org.quartz.JobExecutionContext;
+
 /**
  * 任务接口
  *
@@ -7,12 +9,14 @@ package cn.com.qmth.examcloud.task.base;
  * @date 2018年3月7日
  * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
  */
-public interface Task
-{
+public interface Task {
+
 	/**
 	 * 执行任务
 	 *
 	 * @author WANGWEI
+	 * @param scheduleJob
+	 * @param traceId
 	 */
-	void execute(ScheduleJob scheduleJob);
+	void execute(JobExecutionContext context, ScheduleJob scheduleJob, String traceId);
 }

+ 6 - 4
examcloud-task-dao/src/main/java/cn/com/qmth/examcloud/task/dao/TaskExecutionRepo.java → examcloud-task-dao/src/main/java/cn/com/qmth/examcloud/task/dao/TaskTraceRepo.java

@@ -4,12 +4,14 @@ import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.stereotype.Repository;
 
-import cn.com.qmth.examcloud.task.dao.entity.ScheduleJobEntity;
+import cn.com.qmth.examcloud.task.dao.entity.TaskTraceEntity;
 
 @Repository
-public interface TaskExecutionRepo
+public interface TaskTraceRepo
 		extends
-			JpaRepository<ScheduleJobEntity, Long>,
-			JpaSpecificationExecutor<ScheduleJobEntity> {
+			JpaRepository<TaskTraceEntity, Long>,
+			JpaSpecificationExecutor<TaskTraceEntity> {
+
+	TaskTraceEntity findByTraceId(String traceId);
 
 }

+ 15 - 2
examcloud-task-dao/src/main/java/cn/com/qmth/examcloud/task/dao/entity/TaskExecutionEntity.java → examcloud-task-dao/src/main/java/cn/com/qmth/examcloud/task/dao/entity/TaskTraceEntity.java

@@ -6,6 +6,7 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.Index;
 import javax.persistence.Table;
 
 import cn.com.qmth.examcloud.commons.web.jpa.JpaEntity;
@@ -18,8 +19,9 @@ import cn.com.qmth.examcloud.commons.web.jpa.JpaEntity;
  * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
  */
 @Entity
-@Table(name = "EC_T_TASK_EXECUTION")
-public class TaskExecutionEntity extends JpaEntity {
+@Table(name = "EC_T_TASK_TRACE", indexes = {
+		@Index(name = "IDX_TASK_TRACE_TRACEID", columnList = "traceId")})
+public class TaskTraceEntity extends JpaEntity {
 
 	private static final long serialVersionUID = -1638993747996917970L;
 
@@ -30,6 +32,9 @@ public class TaskExecutionEntity extends JpaEntity {
 	@Column(unique = false, nullable = false)
 	private Long jobId;
 
+	@Column(nullable = false)
+	private String traceId;
+
 	/**
 	 * 任务当前状态
 	 */
@@ -57,6 +62,14 @@ public class TaskExecutionEntity extends JpaEntity {
 		this.jobId = jobId;
 	}
 
+	public String getTraceId() {
+		return traceId;
+	}
+
+	public void setTraceId(String traceId) {
+		this.traceId = traceId;
+	}
+
 	public String getJobStatus() {
 		return jobStatus;
 	}

+ 6 - 0
examcloud-task-service/src/main/java/cn/com/qmth/examcloud/task/service/job/OeCleanExamRecordTask.java

@@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
 import cn.com.qmth.examcloud.core.oe.api.CleanExamRecordService;
 import cn.com.qmth.examcloud.task.base.AbstractTask;
 import cn.com.qmth.examcloud.task.base.ScheduleJob;
+import cn.com.qmth.examcloud.task.base.TaskTracker;
 
 /**
  * 
@@ -26,4 +27,9 @@ public class OeCleanExamRecordTask extends AbstractTask {
 	public void run(ScheduleJob scheduleJob) {
 		cleanExamRecordService.cleanExamExpiredExamRecord();
 	}
+
+	@Override
+	public TaskTracker getTaskTracker() {
+		return null;
+	}
 }

+ 1 - 0
examcloud-task-starter/src/main/java/cn/com/qmth/examcloud/task/starter/config/JobsInitialization.java

@@ -27,6 +27,7 @@ public class JobsInitialization {
 				continue;
 			}
 			ScheduleJob scheduleJob = new ScheduleJob();
+			scheduleJob.setJobId(jobEntity.getId());
 			scheduleJob.setJobName(jobEntity.getJobName());
 			scheduleJob.setJobGroup(jobEntity.getJobGroup());
 			scheduleJob.setSpringBean(jobEntity.getSpringBean());