diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java index 59cfae6fa8..024c9ac86f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java @@ -16,13 +16,12 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.util.Debouncer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; /** * Manages the queue of jobs. This is the only class that should write to {@link JobStorage} to @@ -97,6 +96,28 @@ class JobController { notifyAll(); } + @WorkerThread + synchronized void submitJobWithExistingDependencies(@NonNull Job job, @NonNull Collection dependsOn) { + List> chain = Collections.singletonList(Collections.singletonList(job)); + + if (chainExceedsMaximumInstances(chain)) { + jobTracker.onStateChange(job.getId(), JobTracker.JobState.IGNORED); + Log.w(TAG, JobLogger.format(job, "Already at the max instance count of " + job.getParameters().getMaxInstances() + ". Skipping.")); + return; + } + + dependsOn = Stream.of(dependsOn) + .filter(id -> jobStorage.getJobSpec(id) != null) + .toList(); + + FullSpec fullSpec = buildFullSpec(job, dependsOn); + jobStorage.insertJobs(Collections.singletonList(fullSpec)); + + scheduleJobs(Collections.singletonList(job)); + triggerOnSubmit(chain); + notifyAll(); + } + @WorkerThread synchronized void cancelJob(@NonNull String id) { Job runningJob = runningJobs.get(id); @@ -272,20 +293,20 @@ class JobController { @WorkerThread private void insertJobChain(@NonNull List> chain) { List fullSpecs = new LinkedList<>(); - List dependsOn = Collections.emptyList(); + List dependsOn = Collections.emptyList(); for (List jobList : chain) { for (Job job : jobList) { fullSpecs.add(buildFullSpec(job, dependsOn)); } - dependsOn = jobList; + dependsOn = Stream.of(jobList).map(Job::getId).toList(); } jobStorage.insertJobs(fullSpecs); } @WorkerThread - private @NonNull FullSpec buildFullSpec(@NonNull Job job, @NonNull List dependsOn) { + private @NonNull FullSpec buildFullSpec(@NonNull Job job, @NonNull Collection dependsOn) { job.setRunAttempt(0); JobSpec jobSpec = new JobSpec(job.getId(), @@ -306,7 +327,7 @@ class JobController { .toList(); List dependencySpecs = Stream.of(dependsOn) - .map(depends -> new DependencySpec(job.getId(), depends.getId())) + .map(depends -> new DependencySpec(job.getId(), depends)) .toList(); return new FullSpec(jobSpec, constraintSpecs, dependencySpecs); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java index c1b533af3a..9155df7822 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; -import androidx.lifecycle.LiveData; import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory; import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; @@ -16,6 +15,7 @@ import org.thoughtcrime.securesms.util.Debouncer; import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -119,6 +119,18 @@ public class JobManager implements ConstraintObserver.Notifier { new Chain(this, Collections.singletonList(job)).enqueue(); } + /** + * Enqueues a single job that depends on a collection of job ID's. + */ + public void add(@NonNull Job job, @NonNull Collection dependsOn) { + jobTracker.onStateChange(job.getId(), JobTracker.JobState.PENDING); + + executor.execute(() -> { + jobController.submitJobWithExistingDependencies(job, dependsOn); + wakeUp(); + }); + } + /** * Begins the creation of a job chain with a single job. * @see Chain