Feat: send state of all ongoing jobs

This commit is contained in:
Laurent Clouet
2025-07-28 21:31:29 +02:00
parent 1dfacaee02
commit ccdfc5d3f4
5 changed files with 56 additions and 27 deletions

View File

@@ -45,6 +45,7 @@ dependencies {
implementation 'com.formdev:flatlaf:2.2' // 2.3+ causes illegal reflective access warning on win + adoptium java 11.0.16
implementation 'com.squareup.okhttp3:okhttp:4.12.+'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.12.+'
implementation 'com.squareup.moshi:moshi:1.15.0'
implementation 'org.slf4j:slf4j-simple:2.0.12'
implementation 'commons-io:commons-io:2.11.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.+'

View File

@@ -74,22 +74,16 @@ import com.sheepit.client.os.OS;
import com.sheepit.client.rendering.IncompatibleProcessChecker;
import com.sheepit.client.rendering.Job;
import com.sheepit.client.rendering.State;
import com.sheepit.client.ui.Gui;
import com.sheepit.client.utils.Pair;
import com.sheepit.client.utils.Utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import okhttp3.HttpUrl;
@Data public class Client {
public enum State {
DOWNLOADING,
PREPARING,
RENDERING,
UPLOADING,
UNKNOWN
}
public static final int MIN_JOB_ID = 20; //to distinguish between actual jobs and test frames
private static final Locale LOCALE = Locale.ENGLISH;
private DirectoryManager directoryManager;
@@ -97,7 +91,6 @@ import okhttp3.HttpUrl;
private ServerRequest serverRequest;
private Configuration configuration;
private Log log;
private State state;
private Job renderingJob;
private Job previousJob;
private BlockingQueue<QueuedJob> jobsToValidate;
@@ -121,7 +114,6 @@ import okhttp3.HttpUrl;
this.log = Log.getInstance();
this.gui = gui;
this.directoryManager = new DirectoryManager(this.configuration);
this.state = State.UNKNOWN;
this.renderingJob = null;
this.previousJob = null;
this.jobsToValidate = new ArrayBlockingQueue<>(5);
@@ -722,10 +714,11 @@ import okhttp3.HttpUrl;
public Error.Type work(final Job ajob) {
Error.Type downloadRet;
ajob.setState(State.PREPARING);
gui.setRenderingProjectName(ajob.getName());
try {
this.state = State.DOWNLOADING;
ajob.setState(State.DOWNLOADING);
downloadRet = this.downloadExecutable(ajob);
if (downloadRet != Error.Type.OK) {
gui.setRenderingProjectName("");
@@ -746,7 +739,7 @@ import okhttp3.HttpUrl;
return downloadRet;
}
this.state = State.PREPARING;
ajob.setState(State.PREPARING);
int ret = this.prepareWorkingDirectory(ajob); // decompress renderer and scene archives
if (ret != 0) {
@@ -759,7 +752,7 @@ import okhttp3.HttpUrl;
}
}
catch (SheepItException e) {
this.state = State.UNKNOWN;
ajob.setState(State.ERRORING);
gui.setRenderingProjectName("");
for (String logline : directoryManager.filesystemHealthCheck()) {
log.debug(logline);
@@ -814,7 +807,7 @@ import okhttp3.HttpUrl;
}
};
this.state = State.RENDERING;
ajob.setState(State.RENDERING);
Error.Type err = ajob.render(removeSceneDirectoryOnceRenderHasStartedObserver);
gui.setRenderingProjectName("");
gui.setRemainingTime("");
@@ -853,7 +846,7 @@ import okhttp3.HttpUrl;
}
}
}
this.state = State.UNKNOWN;
ajob.setState(State.UNKNOWN);
return err;
}
@@ -1004,6 +997,7 @@ import okhttp3.HttpUrl;
this.log.debug(checkpoint, "Client::confirmeJob url " + urlReal);
this.log.debug(checkpoint, "path frame " + ajob.getRenderOutput().getFullImagePath());
ajob.setState(State.UPLOADING);
this.isValidatingJob = true;
int maxTries = 3;
int timeToSleep = 22_000;
@@ -1096,7 +1090,7 @@ import okhttp3.HttpUrl;
* @int checkpoint - the checkpoint associated with the job (to add any additional log to the render output)
* @Job job - the job to be validated
*/
@AllArgsConstructor private class QueuedJob {
@AllArgsConstructor @Getter public class QueuedJob {
final private int checkpoint;
final private Job job;
}

View File

@@ -27,13 +27,16 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.net.*;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -55,6 +58,9 @@ import com.sheepit.client.ui.Gui;
import com.sheepit.client.ui.Stats;
import com.sheepit.client.ui.TransferStats;
import com.sheepit.client.utils.Utils;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import lombok.Getter;
import org.simpleframework.xml.core.Persister;
@@ -121,7 +127,7 @@ public class ServerRequest extends Thread {
this.log = Log.getInstance();
this.directoryManager = new DirectoryManager(this.user_config);
this.lastRequestTime = 0;
this.keepmealive_duration = 15 * 60 * 1000; // default 15min
this.keepmealive_duration = 10 * 60 * 1000; // default 10min
// OkHttp performs best when we create a single OkHttpClient instance and reuse it for all of the HTTP calls. This is because each client holds its own
// connection pool and thread pools.Reusing connections and threads reduces latency and saves memory. Conversely, creating a client for each request
@@ -142,18 +148,30 @@ public class ServerRequest extends Thread {
HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(this.getPage("keepmealive"))).newBuilder();
urlBuilder.addQueryParameter("paused", String.valueOf(this.client.isSuspended()));
urlBuilder.addQueryParameter("sleeping", String.valueOf(this.client.nextJobRequest() != null));
urlBuilder.addQueryParameter("state", String.valueOf(this.client.getState()));
if (this.client != null && this.client.getRenderingJob() != null) {
Job job = this.client.getRenderingJob();
urlBuilder.addQueryParameter("frame", job.getRenderSettings().getFrameNumber()).addQueryParameter("job", job.getId());
RenderProcess process = job.getRenderProcess();
if (process != null) {
urlBuilder.addQueryParameter("rendertime", String.valueOf(process.getDuration()))
.addQueryParameter("remainingtime", String.valueOf(process.getRemainingDuration()));
if (this.client != null) {
Map<String, com.sheepit.client.rendering.State> onGoingJob = new HashMap<>();
if (this.client.getRenderingJob() != null) {
Job job = this.client.getRenderingJob();
urlBuilder.addQueryParameter("frame", job.getRenderSettings().getFrameNumber()).addQueryParameter("job", job.getId());
RenderProcess process = job.getRenderProcess();
if (process != null) {
urlBuilder.addQueryParameter("rendertime", String.valueOf(process.getDuration()))
.addQueryParameter("remainingtime", String.valueOf(process.getRemainingDuration()));
}
onGoingJob.put(job.getId(), job.getState());
}
for (Client.QueuedJob queuedJob : this.client.getJobsToValidate()) { // no blocking call
onGoingJob.put(queuedJob.getJob().getId(), queuedJob.getJob().getState());
}
Moshi moshi = new Moshi.Builder().build();
Type type = Types.newParameterizedType(Map.class, String.class, com.sheepit.client.rendering.State.class);
JsonAdapter<Map<String, com.sheepit.client.rendering.State>> adapter = moshi.adapter(type);
urlBuilder.addQueryParameter("ongoing", adapter.toJson(onGoingJob));
}
Response response = this.HTTPRequest(urlBuilder);

View File

@@ -72,6 +72,8 @@ import static com.sheepit.client.rendering.RenderSettings.UPDATE_METHOD_BY_TILE;
public static final int SHOW_BASE_ICON = -1;
private State state;
private DownloadItem projectDownload;
private DownloadItem rendererDownload;
private String id;
@@ -110,6 +112,7 @@ import static com.sheepit.client.rendering.RenderSettings.UPDATE_METHOD_BY_TILE;
renderProcess = new RenderProcess(log_);
renderState = new RenderState();
renderOutput = new RenderOutput();
state = State.INITIALIZING;
}
public void block() {
@@ -158,6 +161,7 @@ import static com.sheepit.client.rendering.RenderSettings.UPDATE_METHOD_BY_TILE;
}
public Error.Type render(Observer renderStarted) {
state = State.RENDERING;
gui.status("Rendering");
RenderProcess process = getRenderProcess();
Timer timerOfMaxRenderTime = null;

View File

@@ -0,0 +1,12 @@
package com.sheepit.client.rendering;
public enum State {
INITIALIZING,
DOWNLOADING,
PREPARING,
RENDERING,
RENDERING_DONE,
UPLOADING,
ERRORING,
UNKNOWN
}