mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-09 11:48:35 +00:00
Allow RuntimeExceptions thrown by Jobs to crash.
This commit is contained in:
parent
e8e80e5d05
commit
17400020b7
@ -125,8 +125,59 @@ public abstract class Job {
|
||||
@NonNull T create(@NonNull Parameters parameters, @NonNull Data data);
|
||||
}
|
||||
|
||||
public enum Result {
|
||||
SUCCESS, FAILURE, RETRY
|
||||
public static final class Result {
|
||||
|
||||
private static final Result SUCCESS = new Result(ResultType.SUCCESS, null);
|
||||
private static final Result RETRY = new Result(ResultType.RETRY, null);
|
||||
private static final Result FAILURE = new Result(ResultType.FAILURE, null);
|
||||
|
||||
private final ResultType resultType;
|
||||
private final RuntimeException runtimeException;
|
||||
|
||||
private Result(@NonNull ResultType resultType, @Nullable RuntimeException runtimeException) {
|
||||
this.resultType = resultType;
|
||||
this.runtimeException = runtimeException;
|
||||
}
|
||||
|
||||
/** Job completed successfully. */
|
||||
public static Result success() {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/** Job did not complete successfully, but it can be retried later. */
|
||||
public static Result retry() {
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
/** Job did not complete successfully and should not be tried again. Dependent jobs will also be failed.*/
|
||||
public static Result failure() {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/** Same as {@link #failure()}, except the app should also crash with the provided exception. */
|
||||
public static Result fatalFailure(@NonNull RuntimeException runtimeException) {
|
||||
return new Result(ResultType.FAILURE, runtimeException);
|
||||
}
|
||||
|
||||
boolean isSuccess() {
|
||||
return resultType == ResultType.SUCCESS;
|
||||
}
|
||||
|
||||
boolean isRetry() {
|
||||
return resultType == ResultType.RETRY;
|
||||
}
|
||||
|
||||
boolean isFailure() {
|
||||
return resultType == ResultType.FAILURE;
|
||||
}
|
||||
|
||||
@Nullable RuntimeException getException() {
|
||||
return runtimeException;
|
||||
}
|
||||
|
||||
private enum ResultType {
|
||||
SUCCESS, FAILURE, RETRY
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Parameters {
|
||||
|
@ -12,6 +12,14 @@ import org.thoughtcrime.securesms.util.WakeLockUtil;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A thread that constantly checks for available {@link Job}s owned by the {@link JobController}.
|
||||
* When one is available, this class will execute it and call the appropriate methods on
|
||||
* {@link JobController} based on the result.
|
||||
*
|
||||
* {@link JobRunner} and {@link JobController} were written such that you should be able to have
|
||||
* N concurrent {@link JobRunner}s operating over the same {@link JobController}.
|
||||
*/
|
||||
class JobRunner extends Thread {
|
||||
|
||||
private static final String TAG = JobRunner.class.getSimpleName();
|
||||
@ -32,25 +40,28 @@ class JobRunner extends Thread {
|
||||
|
||||
@Override
|
||||
public synchronized void run() {
|
||||
//noinspection InfiniteLoopStatement
|
||||
while (true) {
|
||||
Job job = jobController.pullNextEligibleJobForExecution();
|
||||
Job.Result result = run(job);
|
||||
|
||||
jobController.onJobFinished(job);
|
||||
|
||||
switch (result) {
|
||||
case SUCCESS:
|
||||
jobController.onSuccess(job);
|
||||
break;
|
||||
case RETRY:
|
||||
jobController.onRetry(job);
|
||||
job.onRetry();
|
||||
break;
|
||||
case FAILURE:
|
||||
List<Job> dependents = jobController.onFailure(job);
|
||||
job.onCanceled();
|
||||
Stream.of(dependents).forEach(Job::onCanceled);
|
||||
break;
|
||||
if (result.isSuccess()) {
|
||||
jobController.onSuccess(job);
|
||||
} else if (result.isRetry()) {
|
||||
jobController.onRetry(job);
|
||||
job.onRetry();
|
||||
} else if (result.isFailure()) {
|
||||
List<Job> dependents = jobController.onFailure(job);
|
||||
job.onCanceled();
|
||||
Stream.of(dependents).forEach(Job::onCanceled);
|
||||
|
||||
if (result.getException() != null) {
|
||||
throw result.getException();
|
||||
}
|
||||
} else {
|
||||
throw new AssertionError("Invalid job result!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,7 +71,7 @@ class JobRunner extends Thread {
|
||||
|
||||
if (isJobExpired(job)) {
|
||||
Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its lifespan."));
|
||||
return Job.Result.FAILURE;
|
||||
return Job.Result.failure();
|
||||
}
|
||||
|
||||
Job.Result result = null;
|
||||
@ -71,7 +82,7 @@ class JobRunner extends Thread {
|
||||
result = job.run();
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing due to an unexpected exception."), e);
|
||||
return Job.Result.FAILURE;
|
||||
return Job.Result.failure();
|
||||
} finally {
|
||||
if (wakeLock != null) {
|
||||
WakeLockUtil.release(wakeLock, job.getId());
|
||||
@ -80,11 +91,12 @@ class JobRunner extends Thread {
|
||||
|
||||
printResult(job, result);
|
||||
|
||||
if (result == Job.Result.RETRY && job.getRunAttempt() + 1 >= job.getParameters().getMaxAttempts() &&
|
||||
if (result.isRetry() &&
|
||||
job.getRunAttempt() + 1 >= job.getParameters().getMaxAttempts() &&
|
||||
job.getParameters().getMaxAttempts() != Job.Parameters.UNLIMITED)
|
||||
{
|
||||
Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its max number of attempts."));
|
||||
return Job.Result.FAILURE;
|
||||
return Job.Result.failure();
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -101,7 +113,9 @@ class JobRunner extends Thread {
|
||||
}
|
||||
|
||||
private void printResult(@NonNull Job job, @NonNull Job.Result result) {
|
||||
if (result == Job.Result.FAILURE) {
|
||||
if (result.getException() != null) {
|
||||
Log.e(TAG, JobLogger.format(job, String.valueOf(id), "Job failed with a fatal exception. Crash imminent."));
|
||||
} else if (result.isFailure()) {
|
||||
Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Job failed."));
|
||||
} else {
|
||||
Log.i(TAG, JobLogger.format(job, String.valueOf(id), "Job finished with result: " + result));
|
||||
|
@ -19,14 +19,17 @@ public abstract class BaseJob extends Job {
|
||||
public @NonNull Result run() {
|
||||
try {
|
||||
onRun();
|
||||
return Result.SUCCESS;
|
||||
return Result.success();
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "Encountered a fatal exception. Crash imminent.", e);
|
||||
return Result.fatalFailure(e);
|
||||
} catch (Exception e) {
|
||||
if (onShouldRetry(e)) {
|
||||
Log.i(TAG, JobLogger.format(this, "Encountered a retryable exception."), e);
|
||||
return Result.RETRY;
|
||||
return Result.retry();
|
||||
} else {
|
||||
Log.w(TAG, JobLogger.format(this, "Encountered a failing exception."), e);
|
||||
return Result.FAILURE;
|
||||
return Result.failure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user