Skip to content

Commit

Permalink
Create DiagnosticsPostOperation (#3795)
Browse files Browse the repository at this point in the history
Add DiagnosticsPostOperation and DiagnosticsAPI
  • Loading branch information
vegaro authored Apr 11, 2024
1 parent 7d046c2 commit f813e32
Show file tree
Hide file tree
Showing 12 changed files with 419 additions and 44 deletions.
78 changes: 38 additions & 40 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,43 +1,41 @@
{
"object": {
"pins": [
{
"package": "CwlCatchException",
"repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git",
"state": {
"branch": null,
"revision": "3b123999de19bf04905bc1dfdb76f817b0f2cc00",
"version": "2.1.2"
}
},
{
"package": "CwlPreconditionTesting",
"repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git",
"state": {
"branch": null,
"revision": "a23ded2c91df9156628a6996ab4f347526f17b6b",
"version": "2.1.2"
}
},
{
"package": "Nimble",
"repositoryURL": "[email protected]:Quick/Nimble.git",
"state": {
"branch": null,
"revision": "1f3bde57bde12f5e7b07909848c071e9b73d6edc",
"version": "10.0.0"
}
},
{
"package": "swift-snapshot-testing",
"repositoryURL": "[email protected]:pointfreeco/swift-snapshot-testing.git",
"state": {
"branch": null,
"revision": "dc46eeb3928a75390651fac6c1ef7f93ad59a73b",
"version": "1.11.1"
}
"pins" : [
{
"identity" : "cwlcatchexception",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattgallagher/CwlCatchException.git",
"state" : {
"revision" : "3b123999de19bf04905bc1dfdb76f817b0f2cc00",
"version" : "2.1.2"
}
]
},
"version": 1
},
{
"identity" : "cwlpreconditiontesting",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattgallagher/CwlPreconditionTesting.git",
"state" : {
"revision" : "a23ded2c91df9156628a6996ab4f347526f17b6b",
"version" : "2.1.2"
}
},
{
"identity" : "nimble",
"kind" : "remoteSourceControl",
"location" : "[email protected]:Quick/Nimble.git",
"state" : {
"revision" : "1f3bde57bde12f5e7b07909848c071e9b73d6edc",
"version" : "10.0.0"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "[email protected]:pointfreeco/swift-snapshot-testing.git",
"state" : {
"revision" : "26ed3a2b4a2df47917ca9b790a57f91285b923fb",
"version" : "1.12.0"
}
}
],
"version" : 2
}
20 changes: 16 additions & 4 deletions RevenueCat.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@
2DEAC2DD26EFE46E006914ED /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DEAC2DC26EFE46E006914ED /* AppDelegate.swift */; };
2DEAC2E626EFE470006914ED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DEAC2E526EFE470006914ED /* Assets.xcassets */; };
2DFF6C56270CA28800ECAFAB /* MockRequestFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351B517926D44FF000BD2BD7 /* MockRequestFetcher.swift */; };
35109DAB2BC6E436001030C8 /* BackendPostDiagnosticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35109DAA2BC6E436001030C8 /* BackendPostDiagnosticsTests.swift */; };
35109DB92BC8143E001030C8 /* DiagnosticsEventsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35109DB82BC8143E001030C8 /* DiagnosticsEventsRequest.swift */; };
351B513D26D4491E00BD2BD7 /* MockDeviceCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351B513C26D4491E00BD2BD7 /* MockDeviceCache.swift */; };
351B513F26D4496000BD2BD7 /* MockIdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351B513E26D4496000BD2BD7 /* MockIdentityManager.swift */; };
351B514126D4498F00BD2BD7 /* MockBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351B514026D4498F00BD2BD7 /* MockBackend.swift */; };
Expand Down Expand Up @@ -186,10 +188,11 @@
35549323269E298B005F9AE9 /* OfferingsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35549322269E298B005F9AE9 /* OfferingsFactory.swift */; };
359E8E3F26DEBEEB00B869F9 /* TrialOrIntroPriceEligibilityChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 359E8E3E26DEBEEB00B869F9 /* TrialOrIntroPriceEligibilityChecker.swift */; };
35AAEB452BBB14D000A12548 /* DiagnosticsFileHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35AAEB442BBB14D000A12548 /* DiagnosticsFileHandler.swift */; };
35AAEB492BBB17B500A12548 /* DiagnosticsEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35AAEB482BBB17B500A12548 /* DiagnosticsEntry.swift */; };
35AAEB492BBB17B500A12548 /* DiagnosticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35AAEB482BBB17B500A12548 /* DiagnosticsEvent.swift */; };
35AAEB4C2BBC39D100A12548 /* DiagnosticsFileHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35AAEB4A2BBC380600A12548 /* DiagnosticsFileHandlerTests.swift */; };
35B745A82711001A00458D46 /* MockManageSubscriptionsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35E840CD2710E2EB00899AE2 /* MockManageSubscriptionsHelper.swift */; };
35D0E5D026A5886C0099EAD8 /* ErrorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D0E5CF26A5886C0099EAD8 /* ErrorUtils.swift */; };
35D159CB2BC4396F004D8061 /* DiagnosticsPostOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D159CA2BC4396F004D8061 /* DiagnosticsPostOperation.swift */; };
35D159D12BC492E4004D8061 /* DiagnosticsHTTPRequestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D159D02BC492E4004D8061 /* DiagnosticsHTTPRequestPath.swift */; };
35D832CD262A5B7500E60AC5 /* ETagManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D832CC262A5B7500E60AC5 /* ETagManager.swift */; };
35D832D2262E56DB00E60AC5 /* HTTPStatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D832D1262E56DB00E60AC5 /* HTTPStatusCode.swift */; };
Expand Down Expand Up @@ -922,6 +925,8 @@
2DEC0CFB24A2A1B100B0E5BB /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
33FFC8744F2BAE7BD8889A4C /* Pods_RevenueCat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RevenueCat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
350A1B84226E3E8700CCA10F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
35109DAA2BC6E436001030C8 /* BackendPostDiagnosticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackendPostDiagnosticsTests.swift; sourceTree = "<group>"; };
35109DB82BC8143E001030C8 /* DiagnosticsEventsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsEventsRequest.swift; sourceTree = "<group>"; };
351B513C26D4491E00BD2BD7 /* MockDeviceCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDeviceCache.swift; sourceTree = "<group>"; };
351B513E26D4496000BD2BD7 /* MockIdentityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockIdentityManager.swift; sourceTree = "<group>"; };
351B514026D4498F00BD2BD7 /* MockBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackend.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -953,9 +958,10 @@
3597021124BF6AAC0010506E /* TransactionsFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsFactoryTests.swift; sourceTree = "<group>"; };
359E8E3E26DEBEEB00B869F9 /* TrialOrIntroPriceEligibilityChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrialOrIntroPriceEligibilityChecker.swift; sourceTree = "<group>"; };
35AAEB442BBB14D000A12548 /* DiagnosticsFileHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsFileHandler.swift; sourceTree = "<group>"; };
35AAEB482BBB17B500A12548 /* DiagnosticsEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsEntry.swift; sourceTree = "<group>"; };
35AAEB482BBB17B500A12548 /* DiagnosticsEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsEvent.swift; sourceTree = "<group>"; };
35AAEB4A2BBC380600A12548 /* DiagnosticsFileHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsFileHandlerTests.swift; sourceTree = "<group>"; };
35D0E5CF26A5886C0099EAD8 /* ErrorUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorUtils.swift; sourceTree = "<group>"; };
35D159CA2BC4396F004D8061 /* DiagnosticsPostOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsPostOperation.swift; sourceTree = "<group>"; };
35D159D02BC492E4004D8061 /* DiagnosticsHTTPRequestPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsHTTPRequestPath.swift; sourceTree = "<group>"; };
35D832CC262A5B7500E60AC5 /* ETagManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ETagManager.swift; sourceTree = "<group>"; };
35D832D1262E56DB00E60AC5 /* HTTPStatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStatusCode.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2179,6 +2185,8 @@
isa = PBXGroup;
children = (
35D159D02BC492E4004D8061 /* DiagnosticsHTTPRequestPath.swift */,
35D159CA2BC4396F004D8061 /* DiagnosticsPostOperation.swift */,
35109DB82BC8143E001030C8 /* DiagnosticsEventsRequest.swift */,
);
path = Networking;
sourceTree = "<group>";
Expand Down Expand Up @@ -2341,7 +2349,7 @@
35D159C72BC438C6004D8061 /* Networking */,
4F2F2EFE2A3CDAA800652B24 /* FileHandler.swift */,
35AAEB442BBB14D000A12548 /* DiagnosticsFileHandler.swift */,
35AAEB482BBB17B500A12548 /* DiagnosticsEntry.swift */,
35AAEB482BBB17B500A12548 /* DiagnosticsEvent.swift */,
);
path = Diagnostics;
sourceTree = "<group>";
Expand Down Expand Up @@ -2632,6 +2640,7 @@
5796A39827D6C1E000653165 /* BackendPostSubscriberAttributesTests.swift */,
57DB164F298C4327008F6707 /* BackendSignatureVerificationTests.swift */,
5796A38027D6B78500653165 /* BaseBackendTest.swift */,
35109DAA2BC6E436001030C8 /* BackendPostDiagnosticsTests.swift */,
);
path = Backend;
sourceTree = "<group>";
Expand Down Expand Up @@ -3465,6 +3474,7 @@
2C0B98CD2797070B00C5874F /* PromotionalOffer.swift in Sources */,
57DC9F4627CC2E4900DA6AF9 /* HTTPRequest.swift in Sources */,
2DC5623024EC63730031F69B /* OperationDispatcher.swift in Sources */,
35D159CB2BC4396F004D8061 /* DiagnosticsPostOperation.swift in Sources */,
575642B62910116900719219 /* EligibilityStrings.swift in Sources */,
4F87610F2A5C9E490006FA14 /* PaywallData.swift in Sources */,
57A0FBF22749CF66009E2FC3 /* SynchronizedUserDefaults.swift in Sources */,
Expand Down Expand Up @@ -3494,6 +3504,7 @@
4F174F472B07EA7E00FE538E /* StorefrontProvider.swift in Sources */,
B3AA6238268B926F00894871 /* SystemInfo.swift in Sources */,
5746508E275949F20053AB09 /* DispatchTimeInterval+Extensions.swift in Sources */,
35109DB92BC8143E001030C8 /* DiagnosticsEventsRequest.swift in Sources */,
2D294E5C26DECFD500B8FE4F /* StoreKit2TransactionListener.swift in Sources */,
57AC4C182770F55C00DDE30F /* SK2StoreProduct.swift in Sources */,
2DDF41B524F6F387005BC22D /* AppleReceiptBuilder.swift in Sources */,
Expand All @@ -3514,7 +3525,7 @@
35D832F4262E606500E60AC5 /* HTTPResponse.swift in Sources */,
352B7D7927BD919B002A47DD /* DangerousSettings.swift in Sources */,
A56F9AB126990E9200AFC48F /* CustomerInfo.swift in Sources */,
35AAEB492BBB17B500A12548 /* DiagnosticsEntry.swift in Sources */,
35AAEB492BBB17B500A12548 /* DiagnosticsEvent.swift in Sources */,
4F6EEBD92A38ED76007FD783 /* FakeSigning.swift in Sources */,
2DDF41AE24F6F37C005BC22D /* InAppPurchase.swift in Sources */,
B32B750126868C1D005647BF /* EntitlementInfo.swift in Sources */,
Expand Down Expand Up @@ -3722,6 +3733,7 @@
5752E8482892DC500069281E /* ErrorUtilsTests.swift in Sources */,
57488BF229CB84D40000EE7E /* BackendOfflineEntitlementsTests.swift in Sources */,
57554C88282AC293009A7E58 /* PurchaseOwnershipTypeTests.swift in Sources */,
35109DAB2BC6E436001030C8 /* BackendPostDiagnosticsTests.swift in Sources */,
57554C84282AC273009A7E58 /* PeriodTypeTests.swift in Sources */,
4FE6FEEA2AA940E300780B45 /* PaywallEventStoreTests.swift in Sources */,
57057FF828B0048900995F21 /* TestLogHandler.swift in Sources */,
Expand Down
File renamed without changes.
71 changes: 71 additions & 0 deletions Sources/Diagnostics/Networking/DiagnosticsEventsRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// 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
//
// DiagnosticsEventsRequest.swift
//
// Created by Cesar de la Vega on 11/4/24.

import Foundation

/// The content of a request to the events endpoints.
struct DiagnosticsEventsRequest {

var entries: [Event]

init(events: [Event]) {
self.entries = events
}

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
init(events: [DiagnosticsEvent]) {
self.init(events: events.map { .init(event: $0) })
}

}

extension DiagnosticsEventsRequest {

struct Event {

let version: Int
let name: String
let properties: [String: AnyEncodable]
let timestamp: String

}

}

extension DiagnosticsEventsRequest.Event {

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
init(event: DiagnosticsEvent) {
self.init(
version: event.version,
name: event.name,
properties: event.properties,
timestamp: event.timestamp.ISO8601Format()
)
}

}

// MARK: - Codable

extension DiagnosticsEventsRequest.Event: Encodable {

enum CodingKeys: String, CodingKey {

case version, name, properties, timestamp

}

}

extension DiagnosticsEventsRequest: HTTPRequestBody {}
46 changes: 46 additions & 0 deletions Sources/Diagnostics/Networking/DiagnosticsPostOperation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// 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
//
// DiagnosticsPostOperation.swift
//
// Created by Cesar de la Vega on 8/4/24.

import Foundation

final class DiagnosticsPostOperation: NetworkOperation {

private let configuration: Configuration
private let request: DiagnosticsEventsRequest
private let responseHandler: CustomerAPI.SimpleResponseHandler?

init(
configuration: Configuration,
request: DiagnosticsEventsRequest,
responseHandler: CustomerAPI.SimpleResponseHandler?
) {
self.configuration = configuration
self.request = request
self.responseHandler = responseHandler

super.init(configuration: configuration)
}

override func begin(completion: @escaping () -> Void) {
let request = HTTPRequest(method: .post(self.request), path: .postDiagnostics)

self.httpClient.perform(request) { (response: VerifiedHTTPResponse<HTTPEmptyResponseBody>.Result) in
defer {
completion()
}

self.responseHandler?(response.error.map(BackendError.networkError))
}
}

}
14 changes: 14 additions & 0 deletions Sources/Networking/InternalAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ class InternalAPI {
self.backendConfig.operationQueue.addOperation(operation)
}

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
func postDiagnosticsEvents(events: [DiagnosticsEvent], completion: @escaping ResponseHandler) {
guard !events.isEmpty else {
completion(nil)
return
}

let operation = DiagnosticsPostOperation(configuration: .init(httpClient: self.backendConfig.httpClient),
request: .init(events: events),
responseHandler: completion)

self.backendConfig.addDiagnosticsOperation(operation, delay: .long)
}

}

extension InternalAPI {
Expand Down
4 changes: 4 additions & 0 deletions Tests/UnitTests/Mocks/MockHTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ class MockHTTPClient: HTTPClient {
self.mock(path: requestPath, response: response)
}

func mock(requestPath: HTTPRequest.DiagnosticsPath, response: Response) {
self.mock(path: requestPath, response: response)
}

private func mock(path: HTTPRequestPath, response: Response) {
self.mocks[path.url!] = response
}
Expand Down
Loading

0 comments on commit f813e32

Please sign in to comment.