diff --git a/src/main/java/sirius/biz/jobs/batch/BatchProcessTaskExecutor.java b/src/main/java/sirius/biz/jobs/batch/BatchProcessTaskExecutor.java index 383a32f2f..16a43837c 100644 --- a/src/main/java/sirius/biz/jobs/batch/BatchProcessTaskExecutor.java +++ b/src/main/java/sirius/biz/jobs/batch/BatchProcessTaskExecutor.java @@ -61,6 +61,7 @@ protected boolean shouldExecutePartially() { } protected void executeInProcess(String factoryId, ProcessContext process) { + process.markRunning(); process.log(ProcessLog.info().withNLSKey("BatchProcessTaskExecutor.started")); try { jobs.findFactory(factoryId, BatchProcessJobFactory.class).executeTask(process); @@ -76,6 +77,7 @@ protected void executeInProcess(String factoryId, ProcessContext process) { } protected void partiallyExecuteInProcess(String factoryId, ProcessContext process) { + process.markRunning(); process.log(ProcessLog.info().withNLSKey("BatchProcessTaskExecutor.started")); Watch watch = Watch.start(); try { diff --git a/src/main/java/sirius/biz/process/Process.java b/src/main/java/sirius/biz/process/Process.java index 290b2ad08..253dea595 100644 --- a/src/main/java/sirius/biz/process/Process.java +++ b/src/main/java/sirius/biz/process/Process.java @@ -197,6 +197,15 @@ public class Process extends SearchableEntity { public static final Mapping ADMIN_TIMINGS = Mapping.named("adminTimings"); private final StringIntMap adminTimings = new StringIntMap(); + /** + * Contains the timestamp when the process was created / initialized. + *
+ * Note, for standby processes, this contains the timestamp of the last invocation. + */ + public static final Mapping CREATED = Mapping.named("created"); + @NullAllowed + private LocalDateTime created; + /** * Contains the timestamp when the process was started. *
@@ -220,6 +229,15 @@ public class Process extends SearchableEntity { @NullAllowed private LocalDateTime completed; + /** + * Contains the waiting time in seconds. + *
+ * This is the time between the creation of the process and the actual start of the process. + */ + public static final Mapping WAITING_TIME = Mapping.named("waitingTime"); + @NullAllowed + private int waitingTime; + /** * Contains the estimated computation time performed in this process in seconds. *
@@ -387,7 +405,7 @@ public boolean shouldAutorefresh() { */ public String getStateColor() { return switch (state) { - case RUNNING -> "blue"; + case WAITING, RUNNING -> "blue"; case STANDBY -> "violet-light"; case TERMINATED -> "green"; case CANCELED -> "yellow"; @@ -589,6 +607,15 @@ public StringIntMap getAdminTimings() { return adminTimings; } + public LocalDateTime getCreated() { + return created; + } + + public Process setCreated(LocalDateTime created) { + this.created = created; + return this; + } + public LocalDateTime getStarted() { return started; } @@ -689,6 +716,15 @@ public void setWarnings(boolean warnings) { this.warnings = warnings; } + public int getWaitingTime() { + return waitingTime; + } + + public Process setWaitingTime(int waitingTime) { + this.waitingTime = waitingTime; + return this; + } + public int getComputationTime() { return computationTime; } diff --git a/src/main/java/sirius/biz/process/ProcessContext.java b/src/main/java/sirius/biz/process/ProcessContext.java index 30436b62b..b6561d1ee 100644 --- a/src/main/java/sirius/biz/process/ProcessContext.java +++ b/src/main/java/sirius/biz/process/ProcessContext.java @@ -159,6 +159,11 @@ public interface ProcessContext extends TaskContextAdapter { */ boolean isErroneous(); + /** + * Marks the process as running. + */ + void markRunning(); + /** * Marks the process as completed. *
diff --git a/src/main/java/sirius/biz/process/ProcessEnvironment.java b/src/main/java/sirius/biz/process/ProcessEnvironment.java index 3c8b8c395..ef2af5eb3 100644 --- a/src/main/java/sirius/biz/process/ProcessEnvironment.java +++ b/src/main/java/sirius/biz/process/ProcessEnvironment.java @@ -269,6 +269,11 @@ public boolean isErroneous() { return processes.fetchProcess(processId).map(Process::isErrorneous).orElse(true); } + @Override + public void markRunning() { + processes.markRunning(processId); + } + @Override public void markCompleted(int computationTimeInSeconds) { processes.reportLimitedMessages(processId, messageCountsPerType, limitsPerType); @@ -325,7 +330,9 @@ public void cancel() { @Override public boolean isActive() { return processes.fetchProcess(processId) - .map(proc -> proc.getState() == ProcessState.RUNNING || proc.getState() == ProcessState.STANDBY) + .map(process -> process.getState() == ProcessState.WAITING + || process.getState() == ProcessState.RUNNING + || process.getState() == ProcessState.STANDBY) .orElse(false) && tasks.isRunning(); } diff --git a/src/main/java/sirius/biz/process/ProcessState.java b/src/main/java/sirius/biz/process/ProcessState.java index be0cd9c55..d8ab8b1a5 100644 --- a/src/main/java/sirius/biz/process/ProcessState.java +++ b/src/main/java/sirius/biz/process/ProcessState.java @@ -20,6 +20,13 @@ public enum ProcessState { */ STANDBY, + /** + * Represents a process which is waiting for the execution to start. + *
+ * This may be the case when the number of parallel processes is limited and the process is waiting for a slot. + */ + WAITING, + /** * Represents a process which is actively running. */ diff --git a/src/main/java/sirius/biz/process/Processes.java b/src/main/java/sirius/biz/process/Processes.java index 1b02478e2..f780dc2a7 100644 --- a/src/main/java/sirius/biz/process/Processes.java +++ b/src/main/java/sirius/biz/process/Processes.java @@ -163,9 +163,9 @@ public String createProcess(@Nullable String type, process.setUserName(user.getUserName()); process.setTenantId(user.getTenantId()); process.setTenantName(user.getTenantName()); - process.setState(ProcessState.RUNNING); + process.setState(ProcessState.WAITING); process.setProcessType(type); - process.setStarted(LocalDateTime.now()); + process.setCreated(LocalDateTime.now()); process.setPersistencePeriod(persistencePeriod); process.getContext().modify().putAll(context); @@ -399,6 +399,7 @@ private Process createStandbyProcessInLock(String type, String title, String ten process.setTenantId(tenantId); process.setTenantName(tenantName); process.setState(ProcessState.STANDBY); + process.setCreated(LocalDateTime.now()); process.setStarted(LocalDateTime.now()); elastic.update(process); @@ -503,6 +504,20 @@ protected boolean updateState(String processId, ProcessState newState) { return modify(processId, null, process -> process.setState(newState)); } + /** + * Marks a process as running. + * + * @param processId the process to update + * @return true if the process was successfully modified, false otherwise + */ + protected boolean markRunning(String processId) { + return modify(processId, process -> process.getState() == ProcessState.WAITING, process -> { + process.setStarted(LocalDateTime.now()); + process.setWaitingTime((int) Duration.between(process.getCreated(), process.getStarted()).getSeconds()); + process.setState(ProcessState.RUNNING); + }); + } + /** * Marks a process as canceled. *
@@ -512,7 +527,9 @@ protected boolean updateState(String processId, ProcessState newState) {
* @return true if the process was successfully modified, false otherwise
*/
protected boolean markCanceled(String processId) {
- return modify(processId, process -> process.getState() == ProcessState.RUNNING, process -> {
+ return modify(processId, process -> {
+ return process.getState() == ProcessState.WAITING || process.getState() == ProcessState.RUNNING;
+ }, process -> {
process.setErrorneous(true);
process.setCanceled(LocalDateTime.now());
process.setState(ProcessState.CANCELED);
@@ -557,7 +574,8 @@ protected boolean markWarnings(String processId) {
*/
protected boolean changeDebugging(String processId, boolean debuggingEnabled) {
return modify(processId,
- process -> process.getState() == ProcessState.RUNNING
+ process -> process.getState() == ProcessState.WAITING
+ || process.getState() == ProcessState.RUNNING
|| process.getState() == ProcessState.STANDBY,
process -> process.setDebugging(debuggingEnabled));
}
@@ -1003,7 +1021,11 @@ public void execute(String processId, Consumer