bizz84 / SwiftyStoreKit

Lightweight In App Purchases Swift framework for iOS 8.0+, tvOS 9.0+ and macOS 10.10+ ⛺
MIT License
6.57k stars 796 forks source link

Question about parallelism #713

Open paulocoutinhox opened 4 months ago

paulocoutinhox commented 4 months ago

Question

Hi, thanks for this lib.

I would just like to understand the mechanics behind the lib. Although I use it, I would just like to confirm with you that the transactions that Apple sends us are in a kind of queue in its lib and within the transaction loop this queue is being consumed.

In practice, what I want to validate is actually just a guarantee that this queue will never be processed in parallel or multiple times, but always in the sequence of received transactions.

Example for complete purchases (it run in parallel or only in sequence?):

DispatchQueue.global(qos: .background).async {
    SwiftyStoreKit.completeTransactions(atomically: false) { purchases in
        ItunesSubscriptionSystemService.completePurchases(purchases: purchases, onSuccess: {
            DispatchQueue.global(qos: .background).async {
                var canFinishTransaction = false

                for purchase in purchases {
                    // process transaction
                    canFinishTransaction = false

                    if purchase.transaction.transactionState == .purchased {
                        let receiptData = SwiftyStoreKit.localReceiptData
                        let receiptString = (receiptData != nil ? receiptData!.base64EncodedString(options: []) : "")

                        //[...]
                        //canFinishTransaction = true
                    } else if purchase.transaction.transactionState == .restored {
                        let receiptData = SwiftyStoreKit.localReceiptData
                        let receiptString = (receiptData != nil ? receiptData!.base64EncodedString(options: []) : "")

                        //[...]
                        //canFinishTransaction = true
                    } else if purchase.transaction.transactionState == .failed {
                        //canFinishTransaction = false
                    }

                    sleep(1)

                    if canFinishTransaction, purchase.needsFinishTransaction {
                        SwiftyStoreKit.finishTransaction(purchase.transaction)
                    }
                }
            }
        }, onError: { _ in
            //
        })
    }
}

Example about restore:

DispatchQueue.main.async {
    UIUtil.showAlertLoading()
}

DispatchQueue.global(qos: .background).async {
    SwiftyStoreKit.restorePurchases(atomically: false, applicationUsername: "", completion: { results in
        DispatchQueue.global(qos: .background).async {
            if results.restoreFailedPurchases.count > 0 {
                // [...]
                // exit
            } else if results.restoredPurchases.count > 0 {
                var canFinishTransaction = false

                for (index, purchase) in results.restoredPurchases.enumerated() {
                    // canFinishTransaction = true
                    // [...]
                    // UIUtil.hideAlertLoading()
                }
            } else {
                // UIUtil.hideAlertLoading()
            }
        }
    })
}