-
Notifications
You must be signed in to change notification settings - Fork 316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Paywalls
: events unit and integration tests
#3169
Changes from all commits
85cf679
ee5bc06
2644c52
46cc777
1aaf48e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,8 @@ actor FileHandler: FileHandlerType { | |
/// - Note: this loads the entire file in memory | ||
/// For newer versions, consider using `readLines` instead. | ||
func readFile() throws -> Data { | ||
RCTestAssertNotMainThread() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performance check. |
||
|
||
try self.moveToBeginningOfFile() | ||
|
||
return self.fileHandle.availableData | ||
|
@@ -64,13 +66,17 @@ actor FileHandler: FileHandlerType { | |
/// Returns an async sequence for every line in the file | ||
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) | ||
func readLines() throws -> AsyncLineSequence<FileHandle.AsyncBytes> { | ||
RCTestAssertNotMainThread() | ||
|
||
try self.moveToBeginningOfFile() | ||
|
||
return self.fileHandle.bytes.lines | ||
} | ||
|
||
/// Adds a line at the end of the file | ||
func append(line: String) { | ||
RCTestAssertNotMainThread() | ||
|
||
self.fileHandle.seekToEndOfFile() | ||
self.fileHandle.write(line.asData) | ||
self.fileHandle.write(Self.lineBreakData) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,11 +85,14 @@ internal actor PaywallEventStore: PaywallEventStoreType { | |
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) | ||
extension PaywallEventStore { | ||
|
||
static func createDefault() throws -> PaywallEventStore { | ||
let url = try Self.documentsDirectory | ||
static func createDefault(documentsDirectory: URL?) throws -> PaywallEventStore { | ||
let documentsDirectory = try documentsDirectory ?? Self.documentsDirectory | ||
let url = documentsDirectory | ||
.appendingPathComponent("revenuecat") | ||
.appendingPathComponent("paywall_event_store") | ||
|
||
Logger.verbose(PaywallEventStoreStrings.initializing(url)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Helps us make sure this is stored in a reasonable directory. |
||
|
||
return try .init(handler: FileHandler(url)) | ||
} | ||
|
||
|
@@ -116,6 +119,8 @@ extension PaywallEventStore { | |
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) | ||
private enum PaywallEventStoreStrings { | ||
|
||
case initializing(URL) | ||
|
||
case storing_event(PaywallEvent) | ||
|
||
case error_storing_event(Error) | ||
|
@@ -131,6 +136,9 @@ extension PaywallEventStoreStrings: LogMessage { | |
|
||
var description: String { | ||
switch self { | ||
case let .initializing(directory): | ||
return "Initializing PaywallEventStore: \(directory.absoluteString)" | ||
|
||
case let .storing_event(event): | ||
return "Storing event: \(event.debugDescription)" | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,8 +18,10 @@ | |
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) | ||
func track(paywallEvent: PaywallEvent) async | ||
|
||
/// - Throws: if posting events fails | ||
/// - Returns: the number of events posted | ||
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) | ||
func flushEvents(count: Int) async | ||
func flushEvents(count: Int) async throws -> Int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new API makes it easier to assert (especially on integration tests) that things worked as expected. |
||
|
||
} | ||
|
||
|
@@ -46,10 +48,10 @@ | |
await self.store.store(.init(event: paywallEvent, userID: self.userProvider.currentAppUserID)) | ||
} | ||
|
||
func flushEvents(count: Int) async { | ||
func flushEvents(count: Int) async throws -> Int { | ||
guard !self.flushInProgress else { | ||
Logger.debug(Strings.paywalls.event_flush_already_in_progress) | ||
return | ||
return 0 | ||
} | ||
self.flushInProgress = true | ||
defer { self.flushInProgress = false } | ||
|
@@ -58,21 +60,26 @@ | |
|
||
guard !events.isEmpty else { | ||
Logger.verbose(Strings.paywalls.event_flush_with_empty_store) | ||
return | ||
return 0 | ||
} | ||
|
||
Logger.verbose(Strings.paywalls.event_flush_starting(count: events.count)) | ||
|
||
let error = await self.internalAPI.postPaywallEvents(events: events) | ||
do { | ||
try await self.internalAPI.postPaywallEvents(events: events) | ||
|
||
if let error { | ||
await self.store.clear(count) | ||
|
||
return events.count | ||
} catch { | ||
Logger.error(Strings.paywalls.event_flush_failed(error)) | ||
|
||
if error.successfullySynced { | ||
if let backendError = error as? BackendError, | ||
backendError.successfullySynced { | ||
await self.store.clear(count) | ||
} | ||
} else { | ||
await self.store.clear(count) | ||
|
||
throw error | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -260,6 +260,7 @@ | |
convenience init(apiKey: String, | ||
appUserID: String?, | ||
userDefaults: UserDefaults? = nil, | ||
documentsDirectory: URL? = nil, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional for integration tests, similar to |
||
observerMode: Bool = false, | ||
platformInfo: PlatformInfo? = Purchases.platformInfo, | ||
responseVerificationMode: Signing.ResponseVerificationMode, | ||
|
@@ -359,7 +360,7 @@ | |
paywallEventsManager = PaywallEventsManager( | ||
internalAPI: backend.internalAPI, | ||
userProvider: identityManager, | ||
store: try PaywallEventStore.createDefault() | ||
store: try PaywallEventStore.createDefault(documentsDirectory: documentsDirectory) | ||
) | ||
Logger.verbose(Strings.paywalls.event_manager_initialized) | ||
} else { | ||
|
@@ -1266,6 +1267,7 @@ | |
appUserID: String?, | ||
observerMode: Bool, | ||
userDefaults: UserDefaults?, | ||
documentsDirectory: URL? = nil, | ||
platformInfo: PlatformInfo?, | ||
responseVerificationMode: Signing.ResponseVerificationMode, | ||
storeKit2Setting: StoreKit2Setting, | ||
|
@@ -1277,6 +1279,7 @@ | |
.init(apiKey: apiKey, | ||
appUserID: appUserID, | ||
userDefaults: userDefaults, | ||
documentsDirectory: documentsDirectory, | ||
observerMode: observerMode, | ||
platformInfo: platformInfo, | ||
responseVerificationMode: responseVerificationMode, | ||
|
@@ -1531,6 +1534,13 @@ | |
self.offeringsManager.invalidateCachedOfferings(appUserID: self.appUserID) | ||
} | ||
|
||
/// - Throws: if posting events fails | ||
/// - Returns: the number of events posted | ||
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) | ||
func flushPaywallEvents(count: Int) async throws -> Int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Visible for tests. |
||
return try await self.paywallEventsManager?.flushEvents(count: count) ?? 0 | ||
} | ||
|
||
} | ||
|
||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're going to be running these on iOS 17 soon. This simplifies some of the new code, since we never run them on iOS 15 anyway.