
fi.evolver.basics.spring.job.entity.TaskStatus Maven / Gradle / Ivy
package fi.evolver.basics.spring.job.entity;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.zip.GZIPOutputStream;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.evolver.utils.ServerUtils;
import fi.evolver.utils.format.FormatUtils;
import fi.evolver.utils.stream.VoidOutputStream;
import jakarta.persistence.*;
@Entity
@Table(name="task_status")
public class TaskStatus {
private static final Logger LOG = LoggerFactory.getLogger(TaskStatus.class);
public enum TaskState {
RUNNING(false, false),
DONE(true, true),
NOTHING_TO_DO(true, true),
CANCELLED(true, true),
CANCELLING(true, true),
FAILED(true, false);
private final boolean finished;
private final boolean success;
TaskState(boolean finished, boolean success) {
this.finished = finished;
this.success = success;
}
public boolean isFinished() {
return finished;
}
public boolean isSuccess() {
return success;
}
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(name="app_server", nullable=false)
private String appServer;
@Column(name="app_version")
private String appVersion;
@Column(name="group_name", nullable=false)
private String group;
@Column(name="description", nullable=false)
private String description;
@Column(name="start_time", nullable=false)
private LocalDateTime startTime;
@Column(name="message")
private String message;
@Column(name="state", nullable=false)
@Enumerated(EnumType.STRING)
private TaskState state;
@Column(name="duration")
private Long durationMs;
@Column(name="last_updated", nullable=false)
private LocalDateTime lastUpdated;
@OrderBy("key")
@Fetch(value = FetchMode.SUBSELECT)
@OneToMany(mappedBy="taskStatus", fetch=FetchType.EAGER)
private List metadata;
public TaskStatus() {}
public TaskStatus(String group, String description, String message, String appVersion, Map metadata) {
LocalDateTime now = LocalDateTime.now();
this.appServer = ServerUtils.LOCAL_HOST_NAME;
this.appVersion = FormatUtils.truncatePretty(appVersion, 64);
this.metadata = new ArrayList<>();
metadata.forEach(this::addMetadata);
this.group = group;
this.description = FormatUtils.truncatePretty(description, 1024);
this.startTime = now;
this.state = TaskState.RUNNING;
this.lastUpdated = now;
setMessage(message);
}
public long getId() {
return id;
}
public String getAppServer() {
return appServer;
}
public String getAppVersion() {
return appVersion;
}
public String getGroup() {
return group;
}
public String getDescription() {
return description;
}
public LocalDateTime getStartTime() {
return startTime;
}
public Optional getMessage() {
return Optional.ofNullable(message);
}
public void setMessage(String message) {
this.message = FormatUtils.truncatePretty(message, 512);
}
public List getMetadata() {
return metadata;
}
public void addMetadata(String key, Object value) {
if (key != null && value != null) {
String valueString = Objects.toString(value);
if (valueString.length() > 1024)
valueString = digest(valueString);
TaskStatusMetadata metadatum = new TaskStatusMetadata(key, valueString);
metadatum.setTaskStatus(this);
this.metadata.add(metadatum);
}
}
public void setMetadata(List metadata) {
this.metadata = metadata;
}
public TaskState getState() {
return state;
}
public void setState(TaskState newState) {
this.state = newState;
}
public Optional getDurationMs() {
return Optional.ofNullable(durationMs);
}
public LocalDateTime getLastUpdated() {
return lastUpdated;
}
public Optional getMetadata(String key) {
return metadata.stream().filter(m -> key.equals(m.getKey())).findAny().map(TaskStatusMetadata::getValue);
}
@PreUpdate
protected void onUpdate() {
lastUpdated = LocalDateTime.now();
durationMs = ChronoUnit.MILLIS.between(startTime, lastUpdated);
}
private static String digest(String data) {
if (data == null)
return null;
try (OutputStream v = new VoidOutputStream()) {
DigestOutputStream out = new DigestOutputStream(v, MessageDigest.getInstance("MD5"));
try (Writer writer = new OutputStreamWriter(new GZIPOutputStream(out))) {
writer.write(data);
}
return FormatUtils.toHex(out.getMessageDigest().digest());
}
catch (IOException | NoSuchAlgorithmException | RuntimeException e) {
LOG.error("Failed generating digest", e);
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy