From ccdfc5d3f46147f814da736bab64a591c510fa54 Mon Sep 17 00:00:00 2001 From: Laurent Clouet <4409640-laurent.clouet@users.noreply.gitlab.com> Date: Mon, 28 Jul 2025 21:31:29 +0200 Subject: [PATCH] Feat: send state of all ongoing jobs --- build.gradle | 1 + src/main/java/com/sheepit/client/Client.java | 26 +++++------- .../sheepit/client/network/ServerRequest.java | 40 ++++++++++++++----- .../com/sheepit/client/rendering/Job.java | 4 ++ .../com/sheepit/client/rendering/State.java | 12 ++++++ 5 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/sheepit/client/rendering/State.java diff --git a/build.gradle b/build.gradle index 7ec0888..d1a8cd0 100644 --- a/build.gradle +++ b/build.gradle @@ -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.+' diff --git a/src/main/java/com/sheepit/client/Client.java b/src/main/java/com/sheepit/client/Client.java index 1cdc123..84f91ad 100644 --- a/src/main/java/com/sheepit/client/Client.java +++ b/src/main/java/com/sheepit/client/Client.java @@ -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 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; } diff --git a/src/main/java/com/sheepit/client/network/ServerRequest.java b/src/main/java/com/sheepit/client/network/ServerRequest.java index 61213df..e700dc6 100644 --- a/src/main/java/com/sheepit/client/network/ServerRequest.java +++ b/src/main/java/com/sheepit/client/network/ServerRequest.java @@ -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 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> adapter = moshi.adapter(type); + urlBuilder.addQueryParameter("ongoing", adapter.toJson(onGoingJob)); } Response response = this.HTTPRequest(urlBuilder); diff --git a/src/main/java/com/sheepit/client/rendering/Job.java b/src/main/java/com/sheepit/client/rendering/Job.java index 7c20601..b4acc9a 100644 --- a/src/main/java/com/sheepit/client/rendering/Job.java +++ b/src/main/java/com/sheepit/client/rendering/Job.java @@ -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; diff --git a/src/main/java/com/sheepit/client/rendering/State.java b/src/main/java/com/sheepit/client/rendering/State.java new file mode 100644 index 0000000..ea3169c --- /dev/null +++ b/src/main/java/com/sheepit/client/rendering/State.java @@ -0,0 +1,12 @@ +package com.sheepit.client.rendering; + +public enum State { + INITIALIZING, + DOWNLOADING, + PREPARING, + RENDERING, + RENDERING_DONE, + UPLOADING, + ERRORING, + UNKNOWN +}