Commit Graph
7 Commits
Author SHA1 Message Date
NachoSoto a2fc04c09e SubscriberAttribute: converted into struct (#1648)
### Motivation:

Initially I wanted to make `SubscriberAttribute.asDictionary` work using `Codable`. However, this isn't the right refactor because we need the actual raw types to be encoded inside `UserDefaults`.
At least this refactor provides several improvements:

### Changes:

- `SubscriberAttribute` now has value semantics
- ⚠️  `SubscriberAttribute.isSynced` used to be mutable, with reference semantics, which was dangerous
- `SubscriberAttribute: Equatable` implementation is now automatic
- Cleaned up `SubscriberAttribute.asDictionary` implementation, extracting keys into an `enum`
- Moved `Dictionary` -> `SubscriberAttribute` creation to the type itself
- ⚠️ `SubscriberAttribute.init(dictionary:)` returns an `Optional` instead of using force-unwrap, avoiding potential crashes
- Added more serialization / deserialization tests
- Removed `SubscriberAttributesMarshaller` and moved method into `SubscriberAttribute` extension
- Moved `SubscriberAttributeDict` into `SubscriberAttribute.Dictionary`
2022-06-17 10:00:51 -07:00
Cody Kerns 7ee038f20f New public convenience setter for Firebase app instance ID (#1522)
* Adds Firebase convenience setter
2022-04-21 14:20:52 -04: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
Cody Kerns 152b335a7c Fix non-attribution integrations from trying to collect attribution data (#1491)
* Switch non-attribution convenience methods to `setReservedAttribute` instead of `setAttributionID`
2022-04-12 10:38:49 -04:00
NachoSoto 98e5e8d3f2 SubscriberAttributesManager: fixed potential race condition (#1479)
Fixes https://app.circleci.com/pipelines/github/RevenueCat/purchases-ios/6125/workflows/d418661d-752d-403e-84d5-e7fdc32dad88/jobs/22409/tests

The tests introduced in #1441 exposed a potential race condition in the SDK.
On SDK initialization, `Purchases` calls `updateAllCaches`, which in turn makes `CustomerInfoManager` and `OfferingsManager` update its internal caches. Specifically, `CustomerInfoManager` makes a `getCustomerInfo` request ensuring that the backend knows about the current `appUserID`.

These 2 calls are made in the `OperationDispatcher.workerQueue`, so they're ensured proper ordering.

However, `SubscriberAttributesManager` enqueues the requests to post new attributes synchronously and outside this worker thread. If this happens _before_ `CustomerInfoManager` has had a chance to enqueue the `Backend.getCustomerInfo` request, the backend will fail with `SUBSCRIPTION_NOT_FOUND` errors.
2022-04-08 14:35:17 -07:00
NachoSoto ae365eecf3 Created SubscriberAttributesManagerIntegrationTests (#1441)
I made a lot of changes to how subscriber attributes are synced and the error handling, but we had no test coverage for it other than unit tests. None of the `SubscriberAttributesManager` have completion blocks so we never check if calling `setEmail` etc. actually works in production AFAIK.

This adds coverage for that.
2022-04-05 12:14: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