Commit Graph
15 Commits
Author SHA1 Message Date
dd0ee262ea [Customer Center] Initial implementation (#3967)
Alpha of the Customer Center. In this branch, it's been disabled behind
a compilation flag.

---------

Co-authored-by: Will Taylor <wtaylor151@gmail.com>
Co-authored-by: James Borthwick <109382862+jamesrb1@users.noreply.github.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Co-authored-by: JayShortway <29483617+JayShortway@users.noreply.github.com>
Co-authored-by: Toni Rico <toni.rico.diez@revenuecat.com>
Co-authored-by: Toni Rico <antonio.rico.diez@revenuecat.com>
Co-authored-by: Cody Kerns <44073103+codykerns@users.noreply.github.com>
Co-authored-by: Andy Boedo <andresboedo@gmail.com>
2024-08-09 15:26:55 +02:00
NachoSoto d1c6fa23ee Offline Entitlements: added support for fetching ProductEntitlementMappingResponse in OfflineEntitlementsAPI (#2353) 2023-03-23 09:18:51 -07:00
NachoSoto cb3593d9b7 Refactor: reorganized files in new Security and Misc folders (#2326)
Thanks to @aboedo for the suggestion.

### Changes
- Moved signature verification files and tests to new `Security` folder
- Moved `CacheFetchPolicy` inside `Caching`
- Split files inside `Misc` into subfolders
2023-03-13 11:25:36 -07:00
NachoSoto 1234c4ea91 CacheableNetworkOperation: avoid unnecessarily creating operations for cache hits (#2135)
### Changes:
- Created `CacheableNetworkOperationFactory` to abstract operation and
cache key creation
- Instead of always creating an operation, we create a factory first,
which pre-computes the cache key
- This cache key is used to determine if it's a cache hit, as well as
for the subsequently created operation

I'm still investigating a leak (#2105), and I suspect it's coming from
us creating and storing completion blocks, and those staying in memory
beyond the lifetime of the operation.
This refactor and performance improvement helps us avoid get more things
in memory than we need to.

See #2138 for how this is tested.
2022-12-21 08:13:41 -08:00
NachoSoto a94e00d572 CallbackCache: fixed reference (#2143)
This was a conflict between #2136 and #2137.
2022-12-13 09:37:30 -08:00
NachoSoto 4105d66a9e CallbackCache: avoid exposing internal mutable cache (#2136)
Small refactor to avoid users of this `class` change the content of the
cache without using the methods.
2022-12-13 08:25:11 -08:00
NachoSoto 8a84ffb867 CallbackCache: added assertion for tests to ensure we don't leak callbacks (#2137)
See also #2135.
I'm looking into the leak in #2105, and I have a theory that it's due to
callbacks being stored in this cache, but sometimes not being dequeued,
so leaking all references in them.

This assertion will only run in RC tests, and will ensure that this
doesn't happen.
2022-12-13 08:24:55 -08:00
NachoSoto b08fb7dc08 Renamed CallbackCache.add(callback:) (#1970)
This is the Swifty way to avoid the duplication in `cache.add(callback: callback)`.
2022-10-11 12:47:17 -07:00
NachoSoto 43d474d813 GetCustomerInfoAPI: avoid making a request if there's any PostReceiptDataOperation in progress (#1911)
Fixes [CSDK-419].

This is an improvement over the fix in #1292. In there, we avoided
appending on an existing `CustomerInfoOperation` if there were any
`PostReceiptDataOperation`s in progress, because those might come back
with outdated entitlements.
This fix removes that cache key hack, and instead *reuses* the entire
response to that `PostReceiptDataOperation` by "stealing" that request's
cache key.

This is perfectly captured by the existing test
`BackendPostReceiptDataTests.testGetsUpdatedSubscriberInfoAfterPost`,
added in #1292. Amazingly enough, that test still passes with one minor
change: the entire process requires one fewer API call 🎉 🐼

[CSDK-419]:
https://revenuecats.atlassian.net/browse/CSDK-419?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2022-09-21 13:34:43 -07:00
NachoSoto 406522097e CallbackCache: Sendable conformance (#1835)
The change in #1834 made this possible because the type is now immutable.
2022-08-15 15:12:11 -07:00
NachoSoto 0f99e94836 CallbackCache: simplified implementation using Atomic (#1834)
We don't actually need to share a single queue to synchronize all the callback caches.
This new implementation also avoids using the risky `DispatchQueue.sync`.

This also fixes potential issues because `cachedCallbacksByKey` was exposed, and it could have been read without synchronizing access with the queue. This is now impossible.
2022-08-15 15:10:50 -07:00
Joshua Liebowitz 31f611aaa0 Remove create alias (#1695)
* Remove create alias
Resolves [CSDK-152]
2022-06-14 12:39:41 -07:00
NachoSoto 7530a6771d OfferingsManager/OfferingsFactory: using OfferingsResponse (#1435)
This takes full advantage of `Decodable` when decoding and creating `Offerings`.
2022-04-22 11:19:40 -07:00
NachoSoto 23f63c5ef7 HTTPClient now handles response deserialization + Introduced NetworkError and BackendError (#1425)
Closes #695 and finishes [CF-195]. 
Depends on ~~#1431, #1432, #1433, #1437~~.

## Goals:

- [x] Handle all requests / response / deserialization errors in `HTTPClient`. Clients of `HTTPClient` will only have to handle the "happy" path: #1431
- [x] `HTTPClient` shouldn't return `Result.success` with failed responses, forcing clients to verify the response is actually a failure: https://github.com/RevenueCat/purchases-ios/pull/1431
- [x] Abstract error response deserialization / error creation: #1427
- [x] Abstract attribute error parsing: #1427 
- [x] Move response deserialization to `HTTPClient` based on a `ResponseType: Decodable` type, so the completion block will simply return a `Result<HTTPResponse<ResponseType>, Error>`
- [x] `ETagManager` should store response `Data` instead of a deserialized `[String: Any]`
- [x] Improved error types in `HTTPClient` to fix tests: #1437
- [x] Dealt with non-backwards compatible `ETagManager: #1438

## Changes:
- Replaced `HTTPResponse`'s body from `[String: Any]` to a generic `HTTPResponseBody`.
- Created `HTTPResponseBody` to abstract `Decodable` and provide some default implementations for types like `Data,` `[String: Any]` (for backwards compatibility to types that aren't `Decodable` yet), and `Decodable` itself.
- New `HTTPResponse.Result` typealias (`Result<HTTPResponse<HTTPResponseBody>, Error>`) used everywhere. This will allow replacing `Error` with a more specific `Error` so we can forward known typed errors, and make sure that we don't end up with the wrong error type, or with a very complex error hierarchy and the details buried in `underlyingError`.
- Each layer (only a few for now) has its own error type: `NetworkError`, `BackendError`, `OfferingsManager.Error`.
- `HTTPClient` for example has to produce `NetworkError`, operations produce `BackendError`
- The parent `BackendError` can have specific errors like `.missingAppUserID`, but also be simply a child error `case networkError(NetworkError)`
- All of these conform to a `ErrorCodeConvertible`, so there is a single point of code that converts from simple and readable errors (like `BackendError.emptySubscriberAttributes`, `.unexpectedBackendResponse(.loginResponseDecoding)`) into errors with all the context using `ErrorUtils`
- Converted `DNSError` into `NetworkError.dnsError`. Its functionality remains unchanged.
- Removed `Backend.RCSuccessfullySyncedKey` and `ErrorDetails.finishableKey` in favor of tested properties on `NetworkError`

### Leftovers

There's a few things I've decided to not finish for now:
- [ ] `CustomerInfo` still does't conform to `Decodable` (manual deserialization is still supported by the current system): #1496
- `SubscriberAttributeDict` could also be `Codable`
- [x] Replace `OfferingsFactory` with `Decodable`: #1435

[CF-195]: https://revenuecats.atlassian.net/browse/CF-195?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2022-04-12 15:11:22 -07:00
aboedo f5697de730 renamed Purchases folder to Sources (#1416)
* renamed `Purchases` folder to `Sources`

* temporarily enabling installation test jobs

* re-disabling installation test jobs
2022-03-28 11:53:24 -03:00