All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fi.evolver.basics.spring.job.JobStatusService Maven / Gradle / Ivy

package fi.evolver.basics.spring.job;

import java.time.Instant;
import java.time.LocalDateTime;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import fi.evolver.basics.spring.job.entity.JobStatus;
import fi.evolver.basics.spring.job.entity.TaskStatus.TaskState;


@Service
public class JobStatusService {
	private static final Logger LOG = LoggerFactory.getLogger(JobStatusService.class);

	private static final int TOTAL_WEIGHT = 10;


	private final JobStatusRepository jobStatusRepository;


	@Autowired
	public JobStatusService(JobStatusRepository jobStatusRepository) {
		this.jobStatusRepository = jobStatusRepository;
	}


	public Job start(Class clazz) {
		return start(clazz.getSimpleName());
	}

	public Job start(String jobName) {
		return new Job(this, jobName);
	}


	public void recordRun(Job job) {
		synchronized (job.getName()) {
			try {
				LocalDateTime now = LocalDateTime.now();
				JobStatus status = getStatus(job.getName());
				ResultState state = job.getResultState();
				long durationMs = job.getDurationMs();

				if (state.getState().isSuccess()) {
					status.setLastSuccessStart(now);
					status.setLastSuccessDurationMs(durationMs);
					if (status.getSuccessDurationHt() == 0.0)
						status.setSuccessDurationHt(durationMs);
					else
						status.setSuccessDurationHt(calculateWeightedAverage(status.getSuccessDurationHt(), durationMs));
				}
				else {
					status.setLastFailureStart(now);
					status.setLastFailureDurationMs(durationMs);
					if (status.getFailureDurationHt() == 0.0)
						status.setFailureDurationHt(durationMs);
					else
						status.setFailureDurationHt(calculateWeightedAverage(status.getFailureDurationHt(), durationMs));
				}

				status.setSuccessRate(calculateWeightedAverage(status.getSuccessRate(), state.getState().isSuccess() ? 1.0 : 0.0));

				if (state.getState() == TaskState.DONE)
					status.setLastActualActivity(now);

				if (state.getState().isSuccess())
					status.setSuccessMessage(state.getMessage());
				else
					status.setErrorMessage(state.getMessage());

				jobStatusRepository.save(status);
			}
			catch (RuntimeException e) {
				LOG.error("JOB STATUS update FAILED", e);
			}
		}
	}


	private static double calculateWeightedAverage(double oldValue, double newValue) {
		return (oldValue * (TOTAL_WEIGHT - 1) + newValue) / TOTAL_WEIGHT;
	}


	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void updateStatus(JobStatus jobStatus) {
		jobStatusRepository.save(jobStatus);
	}


	private JobStatus getStatus(String jobName) {
	    JobStatus status = jobStatusRepository.findByName(jobName);
	    if (status == null) {
	        status = new JobStatus(jobName);
	        jobStatusRepository.save(status);
	    }
		return status;
	}


	public static class Job implements AutoCloseable {
		private static final ResultState DEFAULT_STATE = new ResultState(TaskState.FAILED, "Result state not set");

		private final JobStatusService jobStatusService;
		private final String name;
		private final Instant startTime;
		private ResultState resultState = DEFAULT_STATE;


		public Job(JobStatusService jobStatusUpdater, String jobName) {
			this.jobStatusService = jobStatusUpdater;
			this.name = jobName.intern();
			this.startTime = Instant.now();
		}


		public String getName() {
			return name;
		}

		public int getDurationMs() {
			return (int)(Instant.now().toEpochMilli() - startTime.toEpochMilli());
		}

		public void setResultState(ResultState resultState) {
			if (resultState != null && resultState.getState().isFinished())
				this.resultState = resultState;
		}

		public ResultState getResultState() {
			return resultState;
		}


		@Override
		public void close() {
			jobStatusService.recordRun(this);
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy