Remove old donation jobs.

This commit is contained in:
Alex Hart
2024-11-14 09:51:23 -04:00
committed by Greyson Parrelli
parent ed1348c20d
commit e82dfea93c
10 changed files with 49 additions and 2152 deletions

View File

@@ -36,7 +36,6 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.errors.Do
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationErrorSource
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.toDonationError
import org.thoughtcrime.securesms.components.settings.app.subscription.manage.DonationRedemptionJobStatus
import org.thoughtcrime.securesms.components.settings.app.subscription.manage.DonationRedemptionJobWatcher
import org.thoughtcrime.securesms.components.settings.app.subscription.manage.NonVerifiedMonthlyDonation
import org.thoughtcrime.securesms.database.DatabaseObserver.InAppPaymentObserver
import org.thoughtcrime.securesms.database.InAppPaymentTable
@@ -522,21 +521,13 @@ object InAppPaymentsRepository {
*/
@WorkerThread
fun hasPendingDonation(): Boolean {
return SignalDatabase.inAppPayments.hasPendingDonation() || DonationRedemptionJobWatcher.hasPendingRedemptionJob()
return SignalDatabase.inAppPayments.hasPendingDonation()
}
/**
* Emits a stream of status updates for donations of the given type. Only One-time donations and recurring donations are currently supported.
*/
fun observeInAppPaymentRedemption(type: InAppPaymentType): Observable<DonationRedemptionJobStatus> {
val jobStatusObservable: Observable<DonationRedemptionJobStatus> = when (type) {
InAppPaymentType.UNKNOWN -> Observable.empty()
InAppPaymentType.ONE_TIME_GIFT -> Observable.empty()
InAppPaymentType.ONE_TIME_DONATION -> DonationRedemptionJobWatcher.watchOneTimeRedemption()
InAppPaymentType.RECURRING_DONATION -> DonationRedemptionJobWatcher.watchSubscriptionRedemption()
InAppPaymentType.RECURRING_BACKUP -> Observable.empty()
}
val fromDatabase: Observable<DonationRedemptionJobStatus> = Observable.create { emitter ->
val observer = InAppPaymentObserver {
val latestInAppPayment = SignalDatabase.inAppPayments.getLatestInAppPaymentByType(type)
@@ -547,7 +538,7 @@ object InAppPaymentsRepository {
AppDependencies.databaseObserver.registerInAppPaymentObserver(observer)
emitter.setCancellable { AppDependencies.databaseObserver.unregisterObserver(observer) }
}.switchMap { inAppPaymentOptional ->
val inAppPayment = inAppPaymentOptional.getOrNull() ?: return@switchMap jobStatusObservable
val inAppPayment = inAppPaymentOptional.getOrNull() ?: return@switchMap Observable.just(DonationRedemptionJobStatus.None)
val value = when (inAppPayment.state) {
InAppPaymentTable.State.CREATED -> error("This should have been filtered out.")
@@ -576,15 +567,7 @@ object InAppPaymentsRepository {
Observable.just(value)
}
return fromDatabase
.switchMap {
if (it == DonationRedemptionJobStatus.None) {
jobStatusObservable
} else {
Observable.just(it)
}
}
.distinctUntilChanged()
return fromDatabase.distinctUntilChanged()
}
fun scheduleSyncForAccountRecordChange() {

View File

@@ -1,141 +0,0 @@
package org.thoughtcrime.securesms.components.settings.app.subscription.manage
import androidx.annotation.WorkerThread
import io.reactivex.rxjava3.core.Observable
import org.thoughtcrime.securesms.badges.Badges
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationSerializationHelper
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationSerializationHelper.toFiatMoney
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.Stripe3DSData
import org.thoughtcrime.securesms.database.model.databaseprotos.PendingOneTimeDonation
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec
import org.thoughtcrime.securesms.jobs.BoostReceiptRequestResponseJob
import org.thoughtcrime.securesms.jobs.DonationReceiptRedemptionJob
import org.thoughtcrime.securesms.jobs.ExternalLaunchDonationJob
import org.thoughtcrime.securesms.jobs.SubscriptionReceiptRequestResponseJob
import org.thoughtcrime.securesms.keyvalue.SignalStore
import java.util.concurrent.TimeUnit
/**
* Allows observer to poll for the status of the latest pending, running, or completed redemption job for subscriptions or one time payments.
*
* @deprecated This object is deprecated and will be removed once we are sure all jobs have drained.
*/
object DonationRedemptionJobWatcher {
enum class RedemptionType {
SUBSCRIPTION,
ONE_TIME
}
@WorkerThread
fun hasPendingRedemptionJob(): Boolean {
return getDonationRedemptionJobStatus(RedemptionType.SUBSCRIPTION).isInProgress() || getDonationRedemptionJobStatus(RedemptionType.ONE_TIME).isInProgress()
}
fun watchSubscriptionRedemption(): Observable<DonationRedemptionJobStatus> = watch(RedemptionType.SUBSCRIPTION)
@JvmStatic
@WorkerThread
fun getSubscriptionRedemptionJobStatus(): DonationRedemptionJobStatus {
return getDonationRedemptionJobStatus(RedemptionType.SUBSCRIPTION)
}
fun watchOneTimeRedemption(): Observable<DonationRedemptionJobStatus> = watch(RedemptionType.ONE_TIME)
private fun watch(redemptionType: RedemptionType): Observable<DonationRedemptionJobStatus> {
return Observable
.interval(0, 5, TimeUnit.SECONDS)
.map {
getDonationRedemptionJobStatus(redemptionType)
}
.distinctUntilChanged()
}
private fun getDonationRedemptionJobStatus(redemptionType: RedemptionType): DonationRedemptionJobStatus {
val queue = when (redemptionType) {
RedemptionType.SUBSCRIPTION -> DonationReceiptRedemptionJob.SUBSCRIPTION_QUEUE
RedemptionType.ONE_TIME -> DonationReceiptRedemptionJob.ONE_TIME_QUEUE
}
val donationJobSpecs = AppDependencies
.jobManager
.find { it.queueKey?.startsWith(queue) == true }
.sortedBy { it.createTime }
val externalLaunchJobSpec: JobSpec? = donationJobSpecs.firstOrNull {
it.factoryKey == ExternalLaunchDonationJob.KEY
}
val receiptRequestJobKey = when (redemptionType) {
RedemptionType.SUBSCRIPTION -> SubscriptionReceiptRequestResponseJob.KEY
RedemptionType.ONE_TIME -> BoostReceiptRequestResponseJob.KEY
}
val receiptJobSpec: JobSpec? = donationJobSpecs.firstOrNull {
it.factoryKey == receiptRequestJobKey
}
val redemptionJobSpec: JobSpec? = donationJobSpecs.firstOrNull {
it.factoryKey == DonationReceiptRedemptionJob.KEY
}
val jobSpec: JobSpec? = externalLaunchJobSpec ?: redemptionJobSpec ?: receiptJobSpec
return if (redemptionType == RedemptionType.SUBSCRIPTION && jobSpec == null && SignalStore.inAppPayments.getSubscriptionRedemptionFailed()) {
DonationRedemptionJobStatus.FailedSubscription
} else {
jobSpec?.toDonationRedemptionStatus(redemptionType) ?: DonationRedemptionJobStatus.None
}
}
private fun JobSpec.toDonationRedemptionStatus(redemptionType: RedemptionType): DonationRedemptionJobStatus {
return when (factoryKey) {
ExternalLaunchDonationJob.KEY -> {
val stripe3DSData = ExternalLaunchDonationJob.Factory.parseSerializedData(serializedData!!)
DonationRedemptionJobStatus.PendingExternalVerification(
pendingOneTimeDonation = pendingOneTimeDonation(redemptionType, stripe3DSData),
nonVerifiedMonthlyDonation = nonVerifiedMonthlyDonation(redemptionType, stripe3DSData)
)
}
SubscriptionReceiptRequestResponseJob.KEY,
BoostReceiptRequestResponseJob.KEY -> DonationRedemptionJobStatus.PendingReceiptRequest
DonationReceiptRedemptionJob.KEY -> DonationRedemptionJobStatus.PendingReceiptRedemption
else -> {
DonationRedemptionJobStatus.None
}
}
}
private fun JobSpec.pendingOneTimeDonation(redemptionType: RedemptionType, stripe3DSData: Stripe3DSData): PendingOneTimeDonation? {
if (redemptionType != RedemptionType.ONE_TIME) {
return null
}
return DonationSerializationHelper.createPendingOneTimeDonationProto(
badge = Badges.fromDatabaseBadge(stripe3DSData.inAppPayment.data.badge!!),
paymentSourceType = stripe3DSData.paymentSourceType,
amount = stripe3DSData.inAppPayment.data.amount!!.toFiatMoney()
).copy(
timestamp = createTime,
pendingVerification = true,
checkedVerification = runAttempt > 0
)
}
private fun JobSpec.nonVerifiedMonthlyDonation(redemptionType: RedemptionType, stripe3DSData: Stripe3DSData): NonVerifiedMonthlyDonation? {
if (redemptionType != RedemptionType.SUBSCRIPTION) {
return null
}
return NonVerifiedMonthlyDonation(
timestamp = createTime,
price = stripe3DSData.inAppPayment.data.amount!!.toFiatMoney(),
level = stripe3DSData.inAppPayment.data.level.toInt(),
checkedVerification = runAttempt > 0
)
}
}