From b83080e2d76756d9dd8db9aa60e0d728d91f7c88 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Mon, 28 Aug 2023 23:00:26 -0400 Subject: [PATCH] Fix payments spinning forever. --- .../securesms/database/PaymentTable.java | 10 ++++ .../securesms/jobs/JobManagerFactories.java | 2 + .../messages/DataMessageProcessor.kt | 10 ++-- .../migrations/ApplicationMigrations.java | 7 ++- .../migrations/RecheckPaymentsMigrationJob.kt | 50 +++++++++++++++++++ 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/migrations/RecheckPaymentsMigrationJob.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java index efb8d61134..77494fa7aa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java @@ -417,6 +417,16 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData return payments; } + public @NonNull List getSubmittedIncomingPayments() { + return CursorExtensionsKt.readToList( + SQLiteDatabaseExtensionsKt.select(getReadableDatabase(), PAYMENT_UUID) + .from(TABLE_NAME) + .where(DIRECTION + " = ? AND " + STATE + " = ?", Direction.RECEIVED.serialize(), State.SUBMITTED.serialize()) + .run(), + c -> UuidUtil.parseOrNull(CursorUtil.requireString(c, PAYMENT_UUID)) + ); + } + @AnyThread public @NonNull LiveData> getAllLive() { return LiveDataUtil.mapAsync(changeSignal, change -> getAll()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index 113765bdba..21a34641f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -66,6 +66,7 @@ import org.thoughtcrime.securesms.migrations.PreKeysSyncMigrationJob; import org.thoughtcrime.securesms.migrations.ProfileMigrationJob; import org.thoughtcrime.securesms.migrations.ProfileSharingUpdateMigrationJob; import org.thoughtcrime.securesms.migrations.RebuildMessageSearchIndexMigrationJob; +import org.thoughtcrime.securesms.migrations.RecheckPaymentsMigrationJob; import org.thoughtcrime.securesms.migrations.RecipientSearchMigrationJob; import org.thoughtcrime.securesms.migrations.StickerAdditionMigrationJob; import org.thoughtcrime.securesms.migrations.StickerDayByDayMigrationJob; @@ -250,6 +251,7 @@ public final class JobManagerFactories { put(ProfileMigrationJob.KEY, new ProfileMigrationJob.Factory()); put(ProfileSharingUpdateMigrationJob.KEY, new ProfileSharingUpdateMigrationJob.Factory()); put(RebuildMessageSearchIndexMigrationJob.KEY, new RebuildMessageSearchIndexMigrationJob.Factory()); + put(RecheckPaymentsMigrationJob.KEY, new RecheckPaymentsMigrationJob.Factory()); put(RecipientSearchMigrationJob.KEY, new RecipientSearchMigrationJob.Factory()); put(StickerLaunchMigrationJob.KEY, new StickerLaunchMigrationJob.Factory()); put(StickerAdditionMigrationJob.KEY, new StickerAdditionMigrationJob.Factory()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt index bbb54c461c..af529a469d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt @@ -652,10 +652,12 @@ object DataMessageProcessor { } catch (e: MmsException) { throw StorageFailedException(e, metadata.sourceServiceId.toString(), metadata.sourceDeviceId) } finally { - ApplicationDependencies.getJobManager() - .startChain(PaymentTransactionCheckJob(uuid, queue)) - .then(PaymentLedgerUpdateJob.updateLedger()) - .enqueue() + SignalDatabase.runPostSuccessfulTransaction { + ApplicationDependencies.getJobManager() + .startChain(PaymentTransactionCheckJob(uuid, queue)) + .then(PaymentLedgerUpdateJob.updateLedger()) + .enqueue() + } } return null diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index 80ba8a7419..654cc3f447 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -137,9 +137,10 @@ public class ApplicationMigrations { static final int EMOJI_SEARCH_INDEX_CHECK = 93; static final int IDENTITY_FIX = 94; static final int COPY_USERNAME_TO_SIGNAL_STORE = 95; + static final int RECHECK_PAYMENTS = 96; } - public static final int CURRENT_VERSION = 95; + public static final int CURRENT_VERSION = 96; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -622,6 +623,10 @@ public class ApplicationMigrations { jobs.put(Version.COPY_USERNAME_TO_SIGNAL_STORE, new CopyUsernameToSignalStoreMigrationJob()); } + if (lastSeenVersion < Version.RECHECK_PAYMENTS) { + jobs.put(Version.RECHECK_PAYMENTS, new RecheckPaymentsMigrationJob()); + } + return jobs; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/RecheckPaymentsMigrationJob.kt b/app/src/main/java/org/thoughtcrime/securesms/migrations/RecheckPaymentsMigrationJob.kt new file mode 100644 index 0000000000..64458944eb --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/RecheckPaymentsMigrationJob.kt @@ -0,0 +1,50 @@ +package org.thoughtcrime.securesms.migrations + +import org.signal.core.util.logging.Log +import org.thoughtcrime.securesms.database.SignalDatabase +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import org.thoughtcrime.securesms.jobmanager.Job +import org.thoughtcrime.securesms.jobs.PaymentLedgerUpdateJob +import org.thoughtcrime.securesms.jobs.PaymentTransactionCheckJob + +/** + * Migration to recheck incoming payments that may have been missed due to db race. + */ +internal class RecheckPaymentsMigrationJob( + parameters: Parameters = Parameters.Builder().build() +) : MigrationJob(parameters) { + + companion object { + const val KEY = "RecheckPaymentsMigrationJob" + + val TAG = Log.tag(RecheckPaymentsMigrationJob::class.java) + } + + override fun getFactoryKey(): String = KEY + + override fun isUiBlocking(): Boolean = false + + @Suppress("UsePropertyAccessSyntax") + override fun performMigration() { + val jobs: MutableList = SignalDatabase + .payments + .getSubmittedIncomingPayments() + .filterNotNull() + .map { PaymentTransactionCheckJob(it) } + .toMutableList() + + Log.i(TAG, "Rechecking ${jobs.size} payments") + if (jobs.isNotEmpty()) { + jobs += PaymentLedgerUpdateJob.updateLedger() + } + ApplicationDependencies.getJobManager().addAll(jobs) + } + + override fun shouldRetry(e: Exception): Boolean = false + + class Factory : Job.Factory { + override fun create(parameters: Parameters, serializedData: ByteArray?): RecheckPaymentsMigrationJob { + return RecheckPaymentsMigrationJob(parameters) + } + } +}