Skip to content

Commit

Permalink
Update subscription and accounts cache after the confirmation of purc…
Browse files Browse the repository at this point in the history
…hase completes (#746)

* Update subscription and accounts cache after the confirmation of purchase completes

* Reuse same logic for updating caches

* Add Subscription typealias to avoid clash with Subscrpiton from Combine

* Post subscrption did change when the cache is being updated
  • Loading branch information
miasma13 authored Mar 25, 2024
1 parent 5fb0b91 commit c34a4d0
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 17 deletions.
26 changes: 15 additions & 11 deletions Sources/Subscription/AccountManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public extension Notification.Name {
static let accountDidSignIn = Notification.Name("com.duckduckgo.subscription.AccountDidSignIn")
static let accountDidSignOut = Notification.Name("com.duckduckgo.subscription.AccountDidSignOut")
static let entitlementsDidChange = Notification.Name("com.duckduckgo.subscription.EntitlementsDidChange")
static let subscriptionDidChange = Notification.Name("com.duckduckgo.subscription.SubscriptionDidChange")
}

public protocol AccountManagerKeychainAccessDelegate: AnyObject {
Expand Down Expand Up @@ -245,20 +246,10 @@ public class AccountManager: AccountManaging {
return .failure(EntitlementsError.noAccessToken)
}

let cachedEntitlements: [Entitlement] = entitlementsCache.get() ?? []

switch await AuthService.validateToken(accessToken: accessToken) {
case .success(let response):
let entitlements = response.account.entitlements

if entitlements != cachedEntitlements {
if entitlements.isEmpty {
entitlementsCache.reset()
} else {
entitlementsCache.set(entitlements)
}
NotificationCenter.default.post(name: .entitlementsDidChange, object: self, userInfo: [UserDefaultsCacheKey.subscriptionEntitlements: entitlements])
}
updateCache(with: entitlements)
return .success(entitlements)

case .failure(let error):
Expand All @@ -267,6 +258,19 @@ public class AccountManager: AccountManaging {
}
}

public func updateCache(with entitlements: [Entitlement]) {
let cachedEntitlements: [Entitlement] = entitlementsCache.get() ?? []

if entitlements != cachedEntitlements {
if entitlements.isEmpty {
entitlementsCache.reset()
} else {
entitlementsCache.set(entitlements)
}
NotificationCenter.default.post(name: .entitlementsDidChange, object: self, userInfo: [UserDefaultsCacheKey.subscriptionEntitlements: entitlements])
}
}

public func fetchEntitlements(cachePolicy: CachePolicy = .returnCacheDataElseLoad) async -> Result<[Entitlement], Error> {

switch cachePolicy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,15 @@ public final class AppStorePurchaseFlow {
SubscriptionService.signOut()

os_log(.info, log: .subscription, "[AppStorePurchaseFlow] completeSubscriptionPurchase")
let accountManager = AccountManager(subscriptionAppGroup: subscriptionAppGroup)

guard let accessToken = AccountManager(subscriptionAppGroup: subscriptionAppGroup).accessToken else { return .failure(.missingEntitlements) }
guard let accessToken = accountManager.accessToken else { return .failure(.missingEntitlements) }

let result = await callWithRetries(retry: 5, wait: 2.0) {
switch await SubscriptionService.confirmPurchase(accessToken: accessToken, signature: transactionJWS) {
case .success:
case .success(let confirmation):
SubscriptionService.updateCache(with: confirmation.subscription)
accountManager.updateCache(with: confirmation.entitlements)
return true
case .failure:
return false
Expand Down
4 changes: 3 additions & 1 deletion Sources/Subscription/Services/Model/Subscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import Foundation

public struct Subscription: Codable {
public typealias DDGSubscription = Subscription // to avoid conflicts when Combine is imported

public struct Subscription: Codable, Equatable {
public let productId: String
public let name: String
public let billingPeriod: BillingPeriod
Expand Down
16 changes: 13 additions & 3 deletions Sources/Subscription/Services/SubscriptionService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,25 @@ public final class SubscriptionService: APIService {

switch result {
case .success(let subscriptionResponse):
let defaultExpiryDate = Date().addingTimeInterval(subscriptionCache.settings.defaultExpirationInterval)
let expiryDate = min(defaultExpiryDate, subscriptionResponse.expiresOrRenewsAt)
subscriptionCache.set(subscriptionResponse, expires: expiryDate)
updateCache(with: subscriptionResponse)
return .success(subscriptionResponse)
case .failure(let error):
return .failure(.apiError(error))
}
}

public static func updateCache(with subscription: Subscription) {
let cachedSubscription: Subscription? = subscriptionCache.get()

if subscription != cachedSubscription {
let defaultExpiryDate = Date().addingTimeInterval(subscriptionCache.settings.defaultExpirationInterval)
let expiryDate = min(defaultExpiryDate, subscription.expiresOrRenewsAt)

subscriptionCache.set(subscription, expires: expiryDate)
NotificationCenter.default.post(name: .subscriptionDidChange, object: self, userInfo: [UserDefaultsCacheKey.subscription: subscription])
}
}

public static func getSubscription(accessToken: String, cachePolicy: CachePolicy = .returnCacheDataElseLoad) async -> Result<Subscription, SubscriptionServiceError> {

switch cachePolicy {
Expand Down

0 comments on commit c34a4d0

Please sign in to comment.