That fuck shit the fascists are using
1package org.tm.archive.migrations;
2
3import androidx.annotation.NonNull;
4import androidx.annotation.Nullable;
5
6import org.signal.core.util.logging.Log;
7import org.tm.archive.jobmanager.Job;
8import org.tm.archive.jobmanager.JobLogger;
9import org.tm.archive.jobmanager.impl.BackoffUtil;
10import org.tm.archive.util.FeatureFlags;
11
12/**
13 * A base class for jobs that are intended to be used in {@link ApplicationMigrations}. Some
14 * sensible defaults are provided, as well as enforcement that jobs have the correct queue key,
15 * never expire, and have at most one instance (to avoid double-migrating).
16 *
17 * These jobs can never fail, or else the JobManager will skip over them. As a result, if they are
18 * neither successful nor retryable, they will crash the app.
19 */
20abstract class MigrationJob extends Job {
21
22 private static final String TAG = Log.tag(MigrationJob.class);
23
24 MigrationJob(@NonNull Parameters parameters) {
25 super(parameters.toBuilder()
26 .setQueue(Parameters.MIGRATION_QUEUE_KEY)
27 .setMaxInstancesForFactory(1)
28 .setLifespan(Parameters.IMMORTAL)
29 .setMaxAttempts(Parameters.UNLIMITED)
30 .build());
31 }
32
33 @Override
34 public @Nullable byte[] serialize() {
35 return null;
36 }
37
38 @Override
39 public @NonNull Result run() {
40 try {
41 Log.i(TAG, "About to run " + getClass().getSimpleName());
42 performMigration();
43 return Result.success();
44 } catch (RuntimeException e) {
45 Log.w(TAG, JobLogger.format(this, "Encountered a runtime exception."), e);
46 throw new FailedMigrationError(e);
47 } catch (Exception e) {
48 if (shouldRetry(e)) {
49 Log.w(TAG, JobLogger.format(this, "Encountered a retryable exception."), e);
50 return Result.retry(BackoffUtil.exponentialBackoff(getRunAttempt() + 1, FeatureFlags.getDefaultMaxBackoff()));
51 } else {
52 Log.w(TAG, JobLogger.format(this, "Encountered a non-runtime fatal exception."), e);
53 throw new FailedMigrationError(e);
54 }
55 }
56 }
57
58 @Override
59 public void onFailure() {
60 throw new AssertionError("This job should never fail. " + getClass().getSimpleName());
61 }
62
63 /**
64 * @return True if you want the UI to be blocked by a spinner if the user opens the application
65 * during the migration, otherwise false.
66 */
67 abstract boolean isUiBlocking();
68
69 /**
70 * Do the actual work of your migration.
71 */
72 abstract void performMigration() throws Exception;
73
74 /**
75 * @return True if you should retry this job based on the exception type, otherwise false.
76 * Returning false will result in a crash and your job being re-run upon app start.
77 * This could result in a crash loop, but considering that this is for an application
78 * migration, this is likely preferable to skipping it.
79 */
80 abstract boolean shouldRetry(@NonNull Exception e);
81
82 private static class FailedMigrationError extends Error {
83 FailedMigrationError(Throwable t) {
84 super(t);
85 }
86 }
87}