Fix BackupSubscriptionCheckJob tests.

This commit is contained in:
Alex Hart
2025-10-03 15:43:25 -03:00
committed by Michelle Tang
parent 1d403d3dee
commit 14cc0f12a6
9 changed files with 194 additions and 100 deletions

View File

@@ -1938,7 +1938,7 @@ object BackupRepository {
suspend fun getPaidType(): NetworkResult<MessageBackupsType.Paid> {
val productPrice: FiatMoney? = if (SignalStore.backup.backupTierInternalOverride == MessageBackupTier.PAID) {
Log.d(TAG, "Accessing price via mock subscription.")
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).getOrNull()?.activeSubscription?.let {
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).successOrNull()?.activeSubscription?.let {
FiatMoney.fromSignalNetworkAmount(it.amount, Currency.getInstance(it.currency))
}
} else if (AppDependencies.billingApi.getApiAvailability().isSuccess) {

View File

@@ -181,7 +181,7 @@ class MessageBackupsFlowViewModel(
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
}
activeSubscription.onSuccess { subscription ->
activeSubscription.runIfSuccessful { subscription ->
if (subscription.willCancelAtPeriodEnd()) {
Log.d(TAG, "Active subscription is cancelled. Clearing tier.")
internalStateFlow.update {

View File

@@ -269,8 +269,27 @@ class BackupStateObserver(
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] hasActiveGooglePlayBillingSubscription: $hasActiveGooglePlayBillingSubscription")
val activeSubscription = withContext(Dispatchers.IO) {
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).getOrNull()
val activeSubscriptionResult = withContext(Dispatchers.IO) {
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
}
val activeSubscription: ActiveSubscription? = when (activeSubscriptionResult) {
is NetworkResult.ApplicationError<ActiveSubscription> -> {
Log.w(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to an application error.", activeSubscriptionResult.getCause(), true)
return getStateOnError()
}
is NetworkResult.NetworkError<ActiveSubscription> -> {
Log.w(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to a network error.", activeSubscriptionResult.getCause(), true)
return getStateOnError()
}
is NetworkResult.StatusCodeError<ActiveSubscription> -> {
Log.i(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to a status code error.", activeSubscriptionResult.getCause(), true)
null
}
is NetworkResult.Success<ActiveSubscription> -> {
Log.i(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Successfully loaded active subscription.", true)
activeSubscriptionResult.result
}
}
val hasActiveSignalSubscription = activeSubscription?.isActive == true
@@ -358,10 +377,10 @@ class BackupStateObserver(
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
}
return if (activeSubscription.isSuccess) {
return if (activeSubscription is NetworkResult.Success) {
Log.d(TAG, "[getPaidBackupState] Retrieved subscription details.")
val subscription = activeSubscription.getOrThrow().activeSubscription
val subscription = activeSubscription.successOrThrow().activeSubscription
if (subscription != null) {
Log.d(TAG, "[getPaidBackupState] Subscription found. Updating UI state with subscription details. Status: ${subscription.status}")

View File

@@ -11,6 +11,10 @@ import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import org.thoughtcrime.securesms.badges.Badges
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository.requireSubscriberType
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository.toPaymentSourceType
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository.cancelActiveSubscriptionIfNecessarySync
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository.cancelActiveSubscriptionSync
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository.getActiveSubscriptionSync
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository.rotateSubscriberIdSync
import org.thoughtcrime.securesms.database.InAppPaymentTable
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
@@ -25,6 +29,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.subscription.LevelUpdate
import org.thoughtcrime.securesms.subscription.LevelUpdateOperation
import org.thoughtcrime.securesms.subscription.Subscription
import org.whispersystems.signalservice.api.NetworkResult
import org.whispersystems.signalservice.api.storage.IAPSubscriptionId
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
import org.whispersystems.signalservice.api.subscriptions.IdempotencyKey
@@ -51,7 +56,7 @@ object RecurringInAppPaymentRepository {
@CheckResult
fun getActiveSubscription(type: InAppPaymentSubscriberRecord.Type): Single<ActiveSubscription> {
return Single.fromCallable {
getActiveSubscriptionSync(type).getOrThrow()
getActiveSubscriptionSync(type).successOrThrow()
}.subscribeOn(Schedulers.io())
}
@@ -77,26 +82,23 @@ object RecurringInAppPaymentRepository {
* Gets the active subscription if it exists for the given [InAppPaymentSubscriberRecord.Type]
*/
@WorkerThread
fun getActiveSubscriptionSync(type: InAppPaymentSubscriberRecord.Type): Result<ActiveSubscription> {
fun getActiveSubscriptionSync(type: InAppPaymentSubscriberRecord.Type): NetworkResult<ActiveSubscription> {
if (type == InAppPaymentSubscriberRecord.Type.BACKUP && SignalStore.backup.backupTierInternalOverride == MessageBackupTier.PAID) {
Log.d(TAG, "Returning mock paid subscription.")
return Result.success(MOCK_PAID_SUBSCRIPTION)
return NetworkResult.Success(MOCK_PAID_SUBSCRIPTION)
}
val response = InAppPaymentsRepository.getSubscriber(type)?.let {
donationsService.getSubscription(it.subscriberId)
} ?: return Result.success(ActiveSubscription.EMPTY)
} ?: return NetworkResult.Success(ActiveSubscription.EMPTY)
return try {
val result = response.resultOrThrow
response.result.ifPresent { result ->
if (result.isActive && result.activeSubscription.endOfCurrentPeriod > SignalStore.inAppPayments.getLastEndOfPeriod()) {
InAppPaymentKeepAliveJob.enqueueAndTrackTime(System.currentTimeMillis().milliseconds)
}
Result.success(result)
} catch (e: Exception) {
Result.failure(e)
}
return response.toNetworkResult()
}
/**

View File

@@ -141,7 +141,22 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
return Result.success()
}
val activeSubscription = RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).getOrNull()
val activeSubscriptionResult = RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
val activeSubscription: ActiveSubscription? = when (activeSubscriptionResult) {
is NetworkResult.ApplicationError<ActiveSubscription>, is NetworkResult.NetworkError<ActiveSubscription> -> {
Log.w(TAG, "Encountered an app-level or network-level error. Failing.", activeSubscriptionResult.getCause(), true)
return Result.failure()
}
is NetworkResult.StatusCodeError<ActiveSubscription> -> {
Log.w(TAG, "Encountered a status-code error.", activeSubscriptionResult.getCause(), true)
null
}
is NetworkResult.Success<ActiveSubscription> -> {
Log.i(TAG, "Successfully retrieved the user's active subscription object.", true)
activeSubscriptionResult.result
}
}
val hasActiveSignalSubscription = activeSubscription?.isActive == true
checkForFailedOrCanceledSubscriptionState(activeSubscription)
@@ -234,7 +249,7 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
* the "download your data" notifier sheet.
*/
private fun checkForFailedOrCanceledSubscriptionState(activeSubscription: ActiveSubscription?) {
if (activeSubscription?.willCancelAtPeriodEnd() == true && activeSubscription?.activeSubscription != null) {
if (activeSubscription?.willCancelAtPeriodEnd() == true && activeSubscription.activeSubscription != null) {
Log.i(TAG, "Subscription either has a payment failure or has been canceled.")
val response = SignalNetwork.account.whoAmI()

View File

@@ -92,7 +92,7 @@ class PostRegistrationBackupRedemptionJob : CoroutineJob {
}
info("Attempting to grab price information for records...")
val subscription = RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).getOrNull()?.activeSubscription
val subscription = RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP).successOrNull()?.activeSubscription
val emptyPrice = FiatMoney(BigDecimal.ZERO, Currency.getInstance(Locale.getDefault()))
val price: FiatMoney = if (subscription != null) {