From b42fcd596ff4876b03a9f6791495e5147ed06220 Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Fri, 4 Mar 2022 20:07:41 +0300 Subject: [PATCH] refactor: use default server from network service, simplify recoverable requests --- .../DefaultJsonNetworkService.swift | 9 +++- ...DefaultRecoverableJsonNetworkService.swift | 42 ++++++++----------- .../RequestFactory.swift | 31 -------------- .../StaticRequestFactory.swift | 41 ------------------ .../EndpointRequest+Serialization.swift | 6 ++- .../Sources/Request/EndpointRequest.swift | 4 +- 6 files changed, 30 insertions(+), 103 deletions(-) delete mode 100644 TIMoyaNetworking/Sources/RecoverableNetworkService/RequestFactory.swift delete mode 100644 TIMoyaNetworking/Sources/RecoverableNetworkService/StaticRequestFactory.swift diff --git a/TIMoyaNetworking/Sources/NetworkService/DefaultJsonNetworkService.swift b/TIMoyaNetworking/Sources/NetworkService/DefaultJsonNetworkService.swift index 21185532..4fb5ad7c 100644 --- a/TIMoyaNetworking/Sources/NetworkService/DefaultJsonNetworkService.swift +++ b/TIMoyaNetworking/Sources/NetworkService/DefaultJsonNetworkService.swift @@ -35,11 +35,14 @@ open class DefaultJsonNetworkService { public var jsonDecoder: JSONDecoder public var jsonEncoder: JSONEncoder + public var defaultServer: Server + public var plugins: [PluginType] = [] public init(session: Session, jsonDecoder: JSONDecoder, jsonEncoder: JSONEncoder, + defaultServer: Server, serializationQueue: DispatchQueue = .global(qos: .default), callbackQueue: DispatchQueue = .main) { @@ -48,6 +51,7 @@ open class DefaultJsonNetworkService { self.callbackQueue = callbackQueue self.jsonDecoder = jsonDecoder self.jsonEncoder = jsonEncoder + self.defaultServer = defaultServer } open func createProvider() -> MoyaProvider { @@ -101,14 +105,15 @@ open class DefaultJsonNetworkService { mapMoyaError: @escaping Closure, completion: @escaping ParameterClosure) -> Cancellable { - ScopeCancellable { [jsonEncoder, serializationQueue, callbackQueue] scope in + ScopeCancellable { [jsonEncoder, serializationQueue, callbackQueue, defaultServer] scope in let workItem = DispatchWorkItem { guard !scope.isCancelled else { return } do { - let serializedRequest = try request.serialize(using: ApplicationJsonBodySerializer(jsonEncoder: jsonEncoder)) + let serializedRequest = try request.serialize(using: ApplicationJsonBodySerializer(jsonEncoder: jsonEncoder), + defaultServer: defaultServer) scope.add(cancellable: self.process(request: serializedRequest, decodableSuccessStatusCodes: decodableSuccessStatusCodes, diff --git a/TIMoyaNetworking/Sources/RecoverableNetworkService/DefaultRecoverableJsonNetworkService.swift b/TIMoyaNetworking/Sources/RecoverableNetworkService/DefaultRecoverableJsonNetworkService.swift index 8ab44a10..46e84efa 100644 --- a/TIMoyaNetworking/Sources/RecoverableNetworkService/DefaultRecoverableJsonNetworkService.swift +++ b/TIMoyaNetworking/Sources/RecoverableNetworkService/DefaultRecoverableJsonNetworkService.swift @@ -30,41 +30,33 @@ open class DefaultRecoverableJsonNetworkService: De private var defaultErrorHandlers: [ErrorHandler] = [] - public func process(recoverableRequest: RF, - prependErrorHandlers: [ErrorHandler] = [], - appendErrorHandlers: [ErrorHandler] = [], - mapMoyaError: @escaping Closure) async -> Result where RF.Body: Encodable, RF.SuccessResponse: Decodable, RF.CreateFailure == ApiError { + public func process(request: EndpointRequest, + prependErrorHandlers: [ErrorHandler] = [], + appendErrorHandlers: [ErrorHandler] = [], + mapMoyaError: @escaping Closure) async -> Result { - await process(recoverableRequest: recoverableRequest, + await process(request: request, errorHandlers: prependErrorHandlers + defaultErrorHandlers + appendErrorHandlers, mapMoyaError: mapMoyaError) } - public func process(recoverableRequest: RF, - errorHandlers: [ErrorHandler] = [], - mapMoyaError: @escaping Closure) async -> Result where RF.Body: Encodable, RF.SuccessResponse: Decodable, RF.CreateFailure == ApiError { + public func process(request: EndpointRequest, + errorHandlers: [ErrorHandler] = [], + mapMoyaError: @escaping Closure) async -> Result { - switch recoverableRequest.create() { - case let .success(endpointRequest): - let result = await process(request: endpointRequest, mapMoyaError: mapMoyaError) as Result + let result = await process(request: request, mapMoyaError: mapMoyaError) - switch result { - case let .failure(errorResponse): - let chain = AsyncEventHandlingChain(handlers: errorHandlers) + if case let .failure(errorResponse) = result { + let chain = AsyncEventHandlingChain(handlers: errorHandlers) - if await chain.handle(errorResponse) { - return await process(recoverableRequest: recoverableRequest, - errorHandlers: errorHandlers, - mapMoyaError: mapMoyaError) - } else { - return result - } - default: - return result + if await chain.handle(errorResponse) { + return await process(request: request, + errorHandlers: errorHandlers, + mapMoyaError: mapMoyaError) } - case let .failure(error): - return .failure(error) } + + return result } public func register(defaultErrorHandler: ErrorHandler) where ErrorHandler.EventType == ApiError { diff --git a/TIMoyaNetworking/Sources/RecoverableNetworkService/RequestFactory.swift b/TIMoyaNetworking/Sources/RecoverableNetworkService/RequestFactory.swift deleted file mode 100644 index 5a45f78f..00000000 --- a/TIMoyaNetworking/Sources/RecoverableNetworkService/RequestFactory.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2022 Touch Instinct -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the Software), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import TINetworking - -public protocol RequestFactory { - associatedtype Body - associatedtype SuccessResponse - associatedtype CreateFailure: Error - - func create() -> Result, CreateFailure> -} diff --git a/TIMoyaNetworking/Sources/RecoverableNetworkService/StaticRequestFactory.swift b/TIMoyaNetworking/Sources/RecoverableNetworkService/StaticRequestFactory.swift deleted file mode 100644 index e3fe65e8..00000000 --- a/TIMoyaNetworking/Sources/RecoverableNetworkService/StaticRequestFactory.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2022 Touch Instinct -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the Software), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import TINetworking - -public struct StaticRequestFactory: RequestFactory { - let request: EndpointRequest - - public init(request: EndpointRequest) { - self.request = request - } - - public func create() -> Result, CreateFailure> { - .success(request) - } -} - -public extension EndpointRequest { - func staticRequestFactory() -> StaticRequestFactory { - .init(request: self) - } -} diff --git a/TINetworking/Sources/Request/EndpointRequest+Serialization.swift b/TINetworking/Sources/Request/EndpointRequest+Serialization.swift index 6aee9ee5..d3131ee2 100644 --- a/TINetworking/Sources/Request/EndpointRequest+Serialization.swift +++ b/TINetworking/Sources/Request/EndpointRequest+Serialization.swift @@ -24,8 +24,10 @@ import Alamofire import Foundation public extension EndpointRequest { - func serialize(using serializer: Serializer) throws -> SerializedRequest where Serializer.Body == Body { - let baseUrl = try server.url(using: customServerVariables) + func serialize(using serializer: Serializer, + defaultServer: Server) throws -> SerializedRequest where Serializer.Body == Body { + + let baseUrl = try (server ?? defaultServer).url(using: customServerVariables) let path = PathParameterEncoding(templateUrl: templatePath).encode(parameters: pathParameters) let (contentType, bodyData) = try serializer.serialize(body: body) let queryParameters = QueryStringParameterEncoding().encode(parameters: queryParameters) diff --git a/TINetworking/Sources/Request/EndpointRequest.swift b/TINetworking/Sources/Request/EndpointRequest.swift index 2a3b8276..1657bda5 100644 --- a/TINetworking/Sources/Request/EndpointRequest.swift +++ b/TINetworking/Sources/Request/EndpointRequest.swift @@ -31,7 +31,7 @@ public struct EndpointRequest { public var headerParameters: HTTPHeaders? public var cookieParameters: [String: Parameter] public var acceptableStatusCodes: Set - public var server: Server + public var server: Server? public var customServerVariables: [KeyValueTuple] public init(templatePath: String, @@ -42,7 +42,7 @@ public struct EndpointRequest { headerParameters: HTTPHeaders? = nil, cookieParameters: [String: Parameter] = [:], acceptableStatusCodes: Set = HTTPCodes.success.asSet(), - server: Server, + server: Server? = nil, customServerVariables: [KeyValueTuple] = []) { self.templatePath = templatePath