@@ -17,6 +17,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
1717 private var updateListenerTask : Task < Void , Error > ?
1818 private var productManager : ProductManager ?
1919 private let state = IapState ( )
20+ // Coalesce concurrent init attempts
21+ private var initTask : Task < Bool , Error > ?
2022
2123 private override init ( ) {
2224 super. init ( )
@@ -29,16 +31,20 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
2931
3032 /// Ensure connection is initialized before operations
3133 private func ensureConnection( ) async throws {
32- let ok = await state. isInitialized
34+ var ok = await state. isInitialized
35+ if !ok {
36+ // Coalesce with ongoing initialization
37+ _ = try await initConnection ( )
38+ ok = await state. isInitialized
39+ }
3340 guard ok else {
3441 let error = OpenIapErrorEvent (
3542 code: OpenIapError . E_INIT_CONNECTION,
36- message: " Connection not initialized. Call initConnection() first. "
43+ message: " Connection not initialized "
3744 )
3845 emitPurchaseError ( error)
3946 throw OpenIapError . purchaseFailed ( reason: error. message)
4047 }
41-
4248 guard AppStore . canMakePayments else {
4349 let error = OpenIapErrorEvent (
4450 code: OpenIapError . E_IAP_NOT_AVAILABLE,
@@ -50,7 +56,22 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
5056 }
5157
5258 public func initConnection( ) async throws -> Bool {
53- return try await initConnectionInternal ( )
59+ if let task = initTask {
60+ return try await task. value
61+ }
62+ let task = Task { [ weak self] ( ) -> Bool in
63+ guard let self = self else { return false }
64+ return try await self . initConnectionInternal ( )
65+ }
66+ initTask = task
67+ do {
68+ let result = try await task. value
69+ initTask = nil
70+ return result
71+ } catch {
72+ initTask = nil
73+ throw error
74+ }
5475 }
5576
5677 private func initConnectionInternal( ) async throws -> Bool {
@@ -87,6 +108,9 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
87108 }
88109
89110 private func endConnectionInternal( ) async throws -> Bool {
111+ // Cancel any in-flight initialization
112+ initTask? . cancel ( )
113+ initTask = nil
90114 await cleanupExistingState ( )
91115 return true
92116 }
0 commit comments