Files
purchases-ios/Sources/Networking/Operations/CreateAliasOperation.swift
T
NachoSoto 2504b953b8 Simplified HTTPClient.Completion and refactored response handling implementation (#1426)
For #695.

The biggest change is that this code at the beginning of `HTTPClient.handle` is now gone:
```swift
var statusCode: HTTPStatusCode = .networkConnectTimeoutError
var jsonObject: [String: Any]?
var httpResponse: HTTPResponse? = HTTPResponse(statusCode: statusCode, jsonObject: jsonObject)
var receivedJSONError: Error?
```

It was hard to trace which paths modified these default values. The new implementation has a mostly linear path (part of it abstracted in smaller methods now) and doesn’t have mutable values.

This is the new `handle` implementation:
```swift
func handle(urlResponse: URLResponse?,
            request: Request,
            urlRequest: URLRequest,
            data: Data?,
            error networkError: Error?) {
    let (response, shouldRetry) = self.parse(
        urlResponse: urlResponse,
        request: request,
        urlRequest: urlRequest,
        data: data,
        error: networkError
    )

    if shouldRetry {
        Logger.debug(Strings.network.retrying_request(httpMethod: request.method.httpMethod,
                                                      path: request.path))

        self.state.modify {
            $0.queuedRequests.insert(request.retriedRequest(), at: 0)
        }
    } else {
        request.completionHandler?(response)
    }

    self.beginNextRequest()
}
```

## All Changes:

- `HTTPClient.perform` no longer has a bunch of mutable variables with forking paths that make it hard to follow. Most of the response handling is now in a new `parse` method. This will simplify the task of continuing to refactor response deserialization.
- `HTTPClient`’s completion abstracts response into `HTTPResponse`
- `UserInfoAttributeParser` is now an `enum`
- `ETagManager` no longer takes an `Error`. The only thing it did with it is to return the default response.
- `HTTPResponse.jsonObject` is no longer `Optional`
- Moved `defaultJsonEncoder` / `defaultJsonDecoder` to `JSONDecoder+Extensions`. They used by `HTTPClient` and others soon.
2022-04-01 14:22:29 -07:00

82 lines
2.5 KiB
Swift

//
// 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
//
// CreateAliasOperation.swift
//
// Created by Joshua Liebowitz on 11/18/21.
import Foundation
class CreateAliasOperation: CacheableNetworkOperation {
private let aliasCallbackCache: CallbackCache<AliasCallback>
private let createAliasResponseHandler: NoContentResponseHandler
private let newAppUserID: String
private let configuration: UserSpecificConfiguration
init(configuration: UserSpecificConfiguration,
newAppUserID: String,
aliasCallbackCache: CallbackCache<AliasCallback>,
createAliasResponseHandler: NoContentResponseHandler = NoContentResponseHandler()) {
self.createAliasResponseHandler = createAliasResponseHandler
self.aliasCallbackCache = aliasCallbackCache
self.newAppUserID = newAppUserID
self.configuration = configuration
super.init(configuration: configuration, individualizedCacheKeyPart: configuration.appUserID + newAppUserID)
}
override func begin(completion: @escaping () -> Void) {
createAlias(completion: completion)
}
}
private extension CreateAliasOperation {
func createAlias(completion: @escaping () -> Void) {
guard let appUserID = try? configuration.appUserID.escapedOrError() else {
self.aliasCallbackCache.performOnAllItemsAndRemoveFromCache(withCacheable: self) { callback in
callback.completion?(ErrorUtils.missingAppUserIDError())
}
completion()
return
}
Logger.user(Strings.identity.creating_alias)
let request = HTTPRequest(method: .post(Body(newAppUserID: newAppUserID)),
path: .createAlias(appUserID: appUserID))
httpClient.perform(request, authHeaders: self.authHeaders) { response in
self.aliasCallbackCache.performOnAllItemsAndRemoveFromCache(withCacheable: self) { aliasCallback in
guard let completion = aliasCallback.completion else {
return
}
self.createAliasResponseHandler.handle(response, completion: completion)
}
completion()
}
}
}
private extension CreateAliasOperation {
struct Body: Encodable {
let newAppUserID: String
}
}