Skip to content

Commit

Permalink
Paywalls: created PaywallEventStore
Browse files Browse the repository at this point in the history
- New `PaywallEventStore` using `FileHandler` (#2673)
- `MockFileHandler`
- `PaywallStoredEvent`: this contains the necessary information to store an event: `PaywallEvent` + user ID
- `Created PaywallEventSerializer`
  • Loading branch information
NachoSoto committed Sep 7, 2023
1 parent 54b8780 commit 01cb229
Show file tree
Hide file tree
Showing 8 changed files with 645 additions and 1 deletion.
32 changes: 32 additions & 0 deletions RevenueCat.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
4FA4C9742A16D3AC007D2803 /* MockBackendConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA4C9722A16D3AC007D2803 /* MockBackendConfiguration.swift */; };
4FA4C9752A16D49E007D2803 /* MockOfflineEntitlementsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57488BE929CB83540000EE7E /* MockOfflineEntitlementsManager.swift */; };
4FA696BD2A0020A000D228B1 /* MainThreadMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA696BC2A0020A000D228B1 /* MainThreadMonitor.swift */; };
4FB2B5512AA7DBA40087EDB5 /* MockFileHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FB2B5502AA7DBA40087EDB5 /* MockFileHandler.swift */; };
4FB3FE132A38CB1F004789C6 /* SignatureVerificationIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FB3FE122A38CB1F004789C6 /* SignatureVerificationIntegrationTests.swift */; };
4FB9069F2A69550500BE2735 /* AvailabilityChecks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3BE0263275942D500915B4C /* AvailabilityChecks.swift */; };
4FBBC5682A61E42F0077281F /* NonEmptyStringDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FBBC5672A61E42F0077281F /* NonEmptyStringDecodable.swift */; };
Expand All @@ -296,6 +297,8 @@
4FCEEA5E2A379B80002C2112 /* DebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FCEEA5D2A379B80002C2112 /* DebugViewController.swift */; };
4FD291BE2A1E9A2E0098D1B9 /* StoreKit2TransactionFetcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD291BD2A1E9A2E0098D1B9 /* StoreKit2TransactionFetcherTests.swift */; };
4FD3688B2AA7C12600F63354 /* PaywallEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD3688A2AA7C12600F63354 /* PaywallEvent.swift */; };
4FD368B42AA7CFED00F63354 /* PaywallEventStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD368B32AA7CFED00F63354 /* PaywallEventStore.swift */; };
4FD368B62AA7D09C00F63354 /* PaywallEventSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD368B52AA7D09C00F63354 /* PaywallEventSerializer.swift */; };
4FDA13842A33D9BD00C45CFE /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 4FDA13662A33D13700C45CFE /* PrivacyInfo.xcprivacy */; };
4FDF10E72A725EA6004F3680 /* ExternalPurchasesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDF10E62A725EA6004F3680 /* ExternalPurchasesManager.swift */; };
4FDF10E82A725EA6004F3680 /* ExternalPurchasesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDF10E62A725EA6004F3680 /* ExternalPurchasesManager.swift */; };
Expand All @@ -307,6 +310,9 @@
4FDF10F12A7262D8004F3680 /* SK2ProductFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDF10EF2A7262D8004F3680 /* SK2ProductFetcher.swift */; };
4FE0685F2A5F54C500B8F56C /* PackageTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE0685E2A5F54C500B8F56C /* PackageTypeTests.swift */; };
4FE6669F2A2F95A1004EEAFC /* PaywallExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE6669E2A2F95A1004EEAFC /* PaywallExtensions.swift */; };
4FE6FEE52AA940B800780B45 /* PaywallStoredEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE6FEE42AA940B700780B45 /* PaywallStoredEvent.swift */; };
4FE6FEEA2AA940E300780B45 /* PaywallEventStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE6FEE72AA940E300780B45 /* PaywallEventStoreTests.swift */; };
4FE6FEEB2AA940E300780B45 /* PaywallEventSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE6FEE82AA940E300780B45 /* PaywallEventSerializerTests.swift */; };
4FF8464D2A32554300617F00 /* DiagnosticsStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF8464C2A32554300617F00 /* DiagnosticsStrings.swift */; };
57032ABF28C13CE4004FF47A /* StoreKit2SettingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57032ABE28C13CE4004FF47A /* StoreKit2SettingTests.swift */; };
57045B3829C514A8001A5417 /* ProductEntitlementMappingDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57045B3729C514A8001A5417 /* ProductEntitlementMappingDecodingTests.swift */; };
Expand Down Expand Up @@ -1019,6 +1025,7 @@
4FA4C9722A16D3AC007D2803 /* MockBackendConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackendConfiguration.swift; sourceTree = "<group>"; };
4FA696A329FC43C600D228B1 /* ReceiptParserTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ReceiptParserTests-Info.plist"; sourceTree = "<group>"; };
4FA696BC2A0020A000D228B1 /* MainThreadMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainThreadMonitor.swift; sourceTree = "<group>"; };
4FB2B5502AA7DBA40087EDB5 /* MockFileHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFileHandler.swift; sourceTree = "<group>"; };
4FB3FE122A38CB1F004789C6 /* SignatureVerificationIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignatureVerificationIntegrationTests.swift; sourceTree = "<group>"; };
4FBBC5672A61E42F0077281F /* NonEmptyStringDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonEmptyStringDecodable.swift; sourceTree = "<group>"; };
4FBBD4E32A620539001CBA21 /* PaywallColorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallColorTests.swift; sourceTree = "<group>"; };
Expand All @@ -1033,13 +1040,18 @@
4FCEEA622A37A2E9002C2112 /* ImageSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageSnapshot.swift; sourceTree = "<group>"; };
4FD291BD2A1E9A2E0098D1B9 /* StoreKit2TransactionFetcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKit2TransactionFetcherTests.swift; sourceTree = "<group>"; };
4FD3688A2AA7C12600F63354 /* PaywallEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallEvent.swift; sourceTree = "<group>"; };
4FD368B32AA7CFED00F63354 /* PaywallEventStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallEventStore.swift; sourceTree = "<group>"; };
4FD368B52AA7D09C00F63354 /* PaywallEventSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallEventSerializer.swift; sourceTree = "<group>"; };
4FDA13662A33D13700C45CFE /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
4FDF10E62A725EA6004F3680 /* ExternalPurchasesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalPurchasesManager.swift; sourceTree = "<group>"; };
4FDF10E92A726269004F3680 /* ObserverModeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObserverModeManager.swift; sourceTree = "<group>"; };
4FDF10EC2A726291004F3680 /* SK1ProductFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SK1ProductFetcher.swift; sourceTree = "<group>"; };
4FDF10EF2A7262D8004F3680 /* SK2ProductFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SK2ProductFetcher.swift; sourceTree = "<group>"; };
4FE0685E2A5F54C500B8F56C /* PackageTypeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageTypeTests.swift; sourceTree = "<group>"; };
4FE6669E2A2F95A1004EEAFC /* PaywallExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallExtensions.swift; sourceTree = "<group>"; };
4FE6FEE42AA940B700780B45 /* PaywallStoredEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaywallStoredEvent.swift; sourceTree = "<group>"; };
4FE6FEE72AA940E300780B45 /* PaywallEventStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaywallEventStoreTests.swift; sourceTree = "<group>"; };
4FE6FEE82AA940E300780B45 /* PaywallEventSerializerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaywallEventSerializerTests.swift; sourceTree = "<group>"; };
4FF8464C2A32554300617F00 /* DiagnosticsStrings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsStrings.swift; sourceTree = "<group>"; };
4FFD88BE2A4B56E2008E98AC /* __Snapshots__ */ = {isa = PBXFileReference; lastKnownFileType = folder; path = __Snapshots__; sourceTree = "<group>"; };
57032ABE28C13CE4004FF47A /* StoreKit2SettingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKit2SettingTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1826,6 +1838,7 @@
351B513C26D4491E00BD2BD7 /* MockDeviceCache.swift */,
F584742F278D00C0001B1CE6 /* MockDNSChecker.swift */,
35D83311262FBD4200E60AC5 /* MockETagManager.swift */,
4FB2B5502AA7DBA40087EDB5 /* MockFileHandler.swift */,
5759B41D296DFD4C002472D5 /* MockFileReader.swift */,
351B514C26D44A8600BD2BD7 /* MockHTTPClient.swift */,
B31C8BEB285BD58F001017B7 /* MockIdentityAPI.swift */,
Expand Down Expand Up @@ -2291,6 +2304,7 @@
4FBBD4E22A620516001CBA21 /* Paywalls */ = {
isa = PBXGroup;
children = (
4FE6FEE62AA940E300780B45 /* Events */,
4F6ABC7B2A81673F00250E63 /* PaywallCacheWarmingTests.swift */,
4F05876E2A5DE03F00E9A834 /* PaywallDataTests.swift */,
4FBBD4E32A620539001CBA21 /* PaywallColorTests.swift */,
Expand Down Expand Up @@ -2322,6 +2336,18 @@
isa = PBXGroup;
children = (
4FD3688A2AA7C12600F63354 /* PaywallEvent.swift */,
4FD368B32AA7CFED00F63354 /* PaywallEventStore.swift */,
4FD368B52AA7D09C00F63354 /* PaywallEventSerializer.swift */,
4FE6FEE42AA940B700780B45 /* PaywallStoredEvent.swift */,
);
path = Events;
sourceTree = "<group>";
};
4FE6FEE62AA940E300780B45 /* Events */ = {
isa = PBXGroup;
children = (
4FE6FEE72AA940E300780B45 /* PaywallEventStoreTests.swift */,
4FE6FEE82AA940E300780B45 /* PaywallEventSerializerTests.swift */,
);
path = Events;
sourceTree = "<group>";
Expand Down Expand Up @@ -3426,6 +3452,7 @@
F530E4FF275646EF001AF6BD /* MacDevice.swift in Sources */,
F5714EAC26D7A87B00635477 /* PurchaseOwnershipType+Extensions.swift in Sources */,
57CD86DA291C1E2300768DE1 /* UserDefaults+Extensions.swift in Sources */,
4FD368B62AA7D09C00F63354 /* PaywallEventSerializer.swift in Sources */,
F5BE424026962ACF00254A30 /* ReceiptRefreshPolicy.swift in Sources */,
9A65E0762591977200DE00B0 /* IdentityStrings.swift in Sources */,
4F6ABC782A81595900250E63 /* PaywallCacheWarming.swift in Sources */,
Expand Down Expand Up @@ -3496,6 +3523,7 @@
B34D2AA0269606E400D88C3A /* IntroEligibility.swift in Sources */,
F516BD29282434070083480B /* StoreKit2StorefrontListener.swift in Sources */,
5766AAB0283D8CDC00FA6091 /* CacheFetchPolicy.swift in Sources */,
4FD368B42AA7CFED00F63354 /* PaywallEventStore.swift in Sources */,
B302206E2728B798008F1A0D /* BackendErrorStrings.swift in Sources */,
2D8D03B52799A2B90044C2ED /* DocCDocumentation.docc in Sources */,
576C8A8B27CFCB150058FA6E /* AnyEncodable.swift in Sources */,
Expand Down Expand Up @@ -3535,6 +3563,7 @@
5766C622282DAA700067D886 /* GetIntroEligibilityResponse.swift in Sources */,
35E840CC270FB70D00899AE2 /* ManageSubscriptionsHelper.swift in Sources */,
6E38843A0CAFD551013D0A3F /* StoreProduct.swift in Sources */,
4FE6FEE52AA940B800780B45 /* PaywallStoredEvent.swift in Sources */,
B34605BD279A6E380031CA74 /* CallbackCacheStatus.swift in Sources */,
42F1DF385E3C1F9903A07FBF /* ProductsFetcherSK1.swift in Sources */,
805B60C97993B311CEC93EAF /* ProductsFetcherSK2.swift in Sources */,
Expand Down Expand Up @@ -3566,6 +3595,7 @@
57488BF229CB84D40000EE7E /* BackendOfflineEntitlementsTests.swift in Sources */,
57554C88282AC293009A7E58 /* PurchaseOwnershipTypeTests.swift in Sources */,
57554C84282AC273009A7E58 /* PeriodTypeTests.swift in Sources */,
4FE6FEEA2AA940E300780B45 /* PaywallEventStoreTests.swift in Sources */,
57057FF828B0048900995F21 /* TestLogHandler.swift in Sources */,
57E415F12846997B00EA5460 /* PurchasesAttributionDataTests.swift in Sources */,
2DDF41CF24F6F4C3005BC22D /* ReceiptParsing+TestsWithRealReceipts.swift in Sources */,
Expand All @@ -3587,6 +3617,7 @@
2DDF41CA24F6F4C3005BC22D /* ArraySlice_UInt8+ExtensionsTests.swift in Sources */,
2DDF41E124F6F527005BC22D /* MockReceiptParser.swift in Sources */,
57E415EB2846962500EA5460 /* PurchasesSyncPurchasesTests.swift in Sources */,
4FE6FEEB2AA940E300780B45 /* PaywallEventSerializerTests.swift in Sources */,
5766AAC5283E843300FA6091 /* PurchasesConfiguringTests.swift in Sources */,
351B514D26D44A8600BD2BD7 /* MockHTTPClient.swift in Sources */,
4FBBD4E42A620539001CBA21 /* PaywallColorTests.swift in Sources */,
Expand Down Expand Up @@ -3705,6 +3736,7 @@
351B516226D44BEE00BD2BD7 /* CustomerInfoManagerTests.swift in Sources */,
5748008C29BFC6660032F001 /* SignatureVerificationHTTPClientTests.swift in Sources */,
351B51A326D450BC00BD2BD7 /* DictionaryExtensionsTests.swift in Sources */,
4FB2B5512AA7DBA40087EDB5 /* MockFileHandler.swift in Sources */,
573A10D92800ADCD00F976E5 /* StoreKitErrorTests.swift in Sources */,
5766AABF283E80B500FA6091 /* BasePurchasesTests.swift in Sources */,
351B515826D44B3E00BD2BD7 /* MockOfferingsFactory.swift in Sources */,
Expand Down
24 changes: 23 additions & 1 deletion Sources/Diagnostics/FileHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,29 @@ import Foundation

/// A wrapper that allows basic operations on a file, synchronized as an `actor`.
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *)
actor FileHandler {
protocol FileHandlerType: Sendable {

/// - Note: this loads the entire file in memory
/// For newer versions, consider using `readLines` instead.
func readFile() async throws -> Data

/// 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() async throws -> AsyncLineSequence<FileHandle.AsyncBytes>

/// Adds a line at the end of the file
func append(line: String) async

/// Removes the contents of the file
func emptyFile() async throws

/// Deletes the first N lines from the file, without loading the entire file in memory.
func removeFirstLines(_ count: Int) async throws

}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *)
actor FileHandler: FileHandlerType {

private var fileHandle: FileHandle

Expand Down
34 changes: 34 additions & 0 deletions Sources/Paywalls/Events/PaywallEventSerializer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Copyright RevenueCat Inc. All Rights Reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// PaywallEventSerializer.swift
//
// Created by Nacho Soto on 9/5/23.

import Foundation

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
enum PaywallEventSerializer {

private struct FailedEncodingEventError: Error {}

/// Encodes a `PaywallEvent` in a format suitable to be stored by `PaywallEventStore`.
static func encode(_ event: PaywallStoredEvent) throws -> String {
let data = try JSONEncoder.default.encode(value: event)

return try String(data: data, encoding: .utf8)
.orThrow(FailedEncodingEventError())
}

/// Decodes a `PaywallEvent`.
static func decode(_ event: String) throws -> PaywallStoredEvent {
return try JSONDecoder.default.decode(jsonData: event.asData)
}

}
Loading

0 comments on commit 01cb229

Please sign in to comment.