Skip to content

Commit

Permalink
Merge pull request #126 from surfstudio/SPT-1998-unit-tests-legacy-re…
Browse files Browse the repository at this point in the history
…move

SPT-1998 Удаление старого подхода
  • Loading branch information
mrandrewsmith authored Apr 24, 2024
2 parents ba0a840 + 66df030 commit 915d6f0
Show file tree
Hide file tree
Showing 104 changed files with 147 additions and 4,256 deletions.
195 changes: 34 additions & 161 deletions NodeKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

19 changes: 0 additions & 19 deletions NodeKit/CacheNode/ETag/UrlETagReaderNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,6 @@ open class UrlETagReaderNode: AsyncNode {
self.etagHeaderKey = etagHeaderKey
}

/// Пытается прочесть eTag-токен из хранилища и добавить его к запросу.
/// В случае, если прочесть токен не удалось, то управление просто передается дальше.
open func processLegacy(_ data: TransportUrlRequest) -> Observer<Json> {
guard let tag = UserDefaults.etagStorage?.value(forKey: data.url.absoluteString) as? String else {
return next.processLegacy(data)
}

var headers = data.headers
headers[self.etagHeaderKey] = tag

let params = TransportUrlParameters(method: data.method,
url: data.url,
headers: headers)

let newData = TransportUrlRequest(with: params, raw: data.raw)

return next.processLegacy(newData)
}

/// Пытается прочесть eTag-токен из хранилища и добавить его к запросу.
/// В случае, если прочесть токен не удалось, то управление просто передается дальше.
open func process(
Expand Down
15 changes: 0 additions & 15 deletions NodeKit/CacheNode/ETag/UrlETagSaverNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,6 @@ open class UrlETagSaverNode: AsyncNode {
self.eTagHeaderKey = eTagHeaderKey
}

/// Пытается получить eTag-токен по ключу.
/// В любом случае передает управление дальше.
open func processLegacy(_ data: UrlProcessedResponse) -> Observer<Void> {
guard let tag = data.response.allHeaderFields[self.eTagHeaderKey] as? String,
let url = data.request.url,
let urlAsKey = url.withOrderedQuery()
else {
return next?.processLegacy(data) ?? .emit(data: ())
}

UserDefaults.etagStorage?.set(tag, forKey: urlAsKey)

return next?.processLegacy(data) ?? .emit(data: ())
}

/// Пытается получить eTag-токен по ключу.
/// В любом случае передает управление дальше.
open func process(
Expand Down
20 changes: 0 additions & 20 deletions NodeKit/CacheNode/FirstCachePolicyNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,6 @@ open class FirstCachePolicyNode: AsyncStreamNode {
}

// MARK: - Node

/// Пытается получить `URLRequest` и если удается, то обращается в кэш
/// а затем, передает управление следующему узлу.
/// В случае, если получить `URLRequest` не удалось,
/// то управление просто передается следующему узлу
open func processLegacy(_ data: RawUrlRequest) -> Observer<Json> {
let result = Context<Json>()

if let request = data.toUrlRequest() {
cacheReaderNode.processLegacy(request)
.onCompleted { result.emit(data: $0) }
.onError { result.emit(error: $0)}
}

next.processLegacy(data)
.onCompleted { result.emit(data: $0)}
.onError { result.emit(error: $0) }

return result
}

/// Пытается получить `URLRequest` и если удается, то обращается в кэш
/// а затем, передает управление следующему узлу.
Expand Down
20 changes: 0 additions & 20 deletions NodeKit/CacheNode/IfServerFailsFromCacheNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@ open class IfConnectionFailedFromCacheNode: AsyncNode {
self.cacheReaderNode = cacheReaderNode
}

/// Проверяет, произошла ли ошибка связи в ответ на запрос.
/// Если ошибка произошла, то возвращает успешный ответ из кэша.
/// В противном случае передает управление следующему узлу.
open func processLegacy(_ data: URLRequest) -> Observer<Json> {

return self.next.processLegacy(data).mapError { error -> Observer<Json> in
var logMessage = self.logViewObjectName
logMessage += "Catching \(error)" + .lineTabDeilimeter
let request = UrlNetworkRequest(urlRequest: data)
if error is BaseTechnicalError {
logMessage += "Start read cache" + .lineTabDeilimeter
return self.cacheReaderNode.processLegacy(request)
}
logMessage += "Error is \(type(of: error))"
logMessage += "and request = \(String(describing: request))" + .lineTabDeilimeter
logMessage += "-> throw error"
return .emit(error: error)
}
}

/// Проверяет, произошла ли ошибка связи в ответ на запрос.
/// Если ошибка произошла, то возвращает успешный ответ из кэша.
/// В противном случае передает управление следующему узлу.
Expand Down
27 changes: 1 addition & 26 deletions NodeKit/CacheNode/UrlCacheReaderNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,7 @@ public enum BaseUrlCacheReaderError: Error {
/// Сам по себе узел является листом и не может быть встроен в сквозную цепочку.
open class UrlCacheReaderNode: AsyncNode {

public var needsToThrowError: Bool

public init(needsToThrowError: Bool) {
self.needsToThrowError = needsToThrowError
}

/// Посылает запрос в кэш и пытается сериализовать данные в JSON.
open func processLegacy(_ data: UrlNetworkRequest) -> Observer<Json> {

guard let cachedResponse = self.extractCachedUrlResponse(data.urlRequest) else {
return self.needsToThrowError ? .emit(error: BaseUrlCacheReaderError.cantLoadDataFromCache) : Context<Json>()
}

guard let jsonObjsect = try? JSONSerialization.jsonObject(with: cachedResponse.data, options: .allowFragments) else {
return self.needsToThrowError ? .emit(error: BaseUrlCacheReaderError.cantSerializeJson) : Context<Json>()
}

guard let json = jsonObjsect as? Json else {
guard let json = jsonObjsect as? [Json] else {
return self.needsToThrowError ? .emit(error: BaseUrlCacheReaderError.cantCastToJson) : Context<Json>()
}
return .emit(data: [MappingUtils.arrayJsonKey: json])
}

return .emit(data: json)
}
public init() { }

/// Посылает запрос в кэш и пытается сериализовать данные в JSON.
open func process(
Expand Down
8 changes: 0 additions & 8 deletions NodeKit/CacheNode/UrlCacheWriterNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ import Foundation
/// Подразумечается, что этот узел не входит в цепочку, а является листом одного из узлов.
open class UrlCacheWriterNode: AsyncNode {

/// Формирует `CachedURLResponse` с политикой `.allowed`, сохраняет его в кэш,
/// а затем возвращает сообщение об успешной операции.
open func processLegacy(_ data: UrlProcessedResponse) -> Observer<Void> {
let cahced = CachedURLResponse(response: data.response, data: data.data, storagePolicy: .allowed)
URLCache.shared.storeCachedResponse(cahced, for: data.request)
return Context<Void>().emit(data: ())
}

/// Формирует `CachedURLResponse` с политикой `.allowed`, сохраняет его в кэш,
/// а затем возвращает сообщение об успешной операции.
open func process(
Expand Down
10 changes: 0 additions & 10 deletions NodeKit/CacheNode/UrlNotModifiedTriggerNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ open class UrlNotModifiedTriggerNode: AsyncNode {

// MARK: - Node

/// Проверяет http status-code. Если код соовуетствует NotModified, то возвращает запрос из кэша.
/// В протвином случае передает управление дальше.
open func processLegacy(_ data: UrlDataResponse) -> Observer<Json> {
guard data.response.statusCode == 304 else {
let log = makeErrorLog(code: data.response.statusCode)
return next.processLegacy(data).log(log)
}
return cacheReader.processLegacy(UrlNetworkRequest(urlRequest: data.request))
}

/// Проверяет http status-code. Если код соовуетствует NotModified, то возвращает запрос из кэша.
/// В протвином случае передает управление дальше.
open func process(
Expand Down
40 changes: 14 additions & 26 deletions NodeKit/Chains/UrlChainsBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
/// Массив с ID логов, которые нужно исключить из выдачи.
public var logFilter: [String]

/// Очередь, на которой response вашего запроса должен будет быть обработан. По дефолту `Global` с приоритетом `.userInitiated`
public var responseDispatchQueue: DispatchQueue = DispatchQueue.global(qos: .userInitiated)

// MARK: - Init

/// Инициаллизирует объект.
Expand Down Expand Up @@ -123,11 +120,6 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
return self
}

open func setResponseQueue(_ queue: DispatchQueue) -> Self {
self.responseDispatchQueue = queue
return self
}

// MARK: - Infrastructure Config

open func log(exclude: [String]) -> Self {
Expand All @@ -141,7 +133,10 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
///
/// - Parameter config: Конфигурация для запроса
open func requestBuildingChain() -> some AsyncNode<Json, Json> {
let transportChain = self.serviceChain.requestTrasportChain(providers: self.headersProviders, responseQueue: responseDispatchQueue, session: session)
let transportChain = self.serviceChain.requestTrasportChain(
providers: self.headersProviders,
session: session
)

let urlRequestEncodingNode = UrlJsonRequestEncodingNode(next: transportChain)
let urlRequestTrasformatorNode = UrlRequestTrasformatorNode(next: urlRequestEncodingNode, method: self.method)
Expand Down Expand Up @@ -184,16 +179,14 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
where Input: DTOEncodable, Output: DTODecodable,
Input.DTO.Raw == Json, Output.DTO.Raw == Json {
let input: some AsyncNode<Input, Output> = self.supportNodes()
let config = ChainConfiguratorNode<Input, Output>(next: input)
return LoggerNode(next: config, filters: self.logFilter)
return LoggerNode(next: input, filters: self.logFilter)
}

/// Создает обычную цепочку, только в качестве входных данных принимает `Void`
open func build<Output>() -> some AsyncNode<Void, Output>
where Output: DTODecodable, Output.DTO.Raw == Json {
let input: some AsyncNode<Json, Output> = self.supportNodes()
let configNode = ChainConfiguratorNode<Json, Output>(next: input)
let voidNode = VoidInputNode(next: configNode)
let voidNode = VoidInputNode(next: input)
return LoggerNode(next: voidNode, filters: self.logFilter)
}

Expand All @@ -202,17 +195,15 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
where Input: DTOEncodable, Input.DTO.Raw == Json {
let input = self.requestBuildingChain()
let indicator = LoadIndicatableNode(next: input)
let configNode = ChainConfiguratorNode(next: indicator)
let voidOutput = VoidOutputNode<Input>(next: configNode)
let voidOutput = VoidOutputNode<Input>(next: indicator)
return LoggerNode(next: voidOutput, filters: self.logFilter)
}

/// Создает обычную цепочку, только в качестве входных и вызодных данных имеет `Void`
open func build() -> some AsyncNode<Void, Void> {
let input = self.requestBuildingChain()
let indicator = LoadIndicatableNode(next: input)
let configNode = ChainConfiguratorNode(next: indicator)
let voidOutput = VoidIONode(next: configNode)
let voidOutput = VoidIONode(next: indicator)
return LoggerNode(next: voidOutput, filters: self.logFilter)
}

Expand All @@ -224,7 +215,7 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {

let reponseProcessor = self.serviceChain.urlResponseProcessingLayerChain()

let requestSenderNode = RequestSenderNode(rawResponseProcessor: reponseProcessor, responseQueue: responseDispatchQueue, manager: session)
let requestSenderNode = RequestSenderNode(rawResponseProcessor: reponseProcessor, manager: session)

let creator = MultipartRequestCreatorNode(next: requestSenderNode)

Expand All @@ -239,9 +230,8 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
let dtoEncoder = ModelInputNode<I, O>(next: rawEncoder)

let indicator = LoadIndicatableNode(next: dtoEncoder)
let configNode = ChainConfiguratorNode(next: indicator)

return LoggerNode(next: configNode, filters: self.logFilter)
return LoggerNode(next: indicator, filters: self.logFilter)
}

/// Позволяет загрузить бинарные данные (файл) с сервера без отправки какой-то модели на сервер.
Expand All @@ -250,7 +240,7 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
let loaderParser = DataLoadingResponseProcessor()
let errorProcessor = ResponseHttpErrorProcessorNode(next: loaderParser)
let responseProcessor = ResponseProcessorNode(next: errorProcessor)
let sender = RequestSenderNode(rawResponseProcessor: responseProcessor, responseQueue: responseDispatchQueue, manager: session)
let sender = RequestSenderNode(rawResponseProcessor: responseProcessor, manager: session)

let creator = RequestCreatorNode(next: sender, providers: headersProviders)

Expand All @@ -264,9 +254,8 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
let connector = MetadataConnectorNode(next: router, metadata: self.metadata)

let indicator = LoadIndicatableNode(next: connector)
let configNode = ChainConfiguratorNode(next: indicator)

let voidInput = VoidInputNode(next: configNode)
let voidInput = VoidInputNode(next: indicator)

return LoggerNode(next: voidInput, filters: self.logFilter)
}
Expand All @@ -278,7 +267,7 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
let loaderParser = DataLoadingResponseProcessor()
let errorProcessor = ResponseHttpErrorProcessorNode(next: loaderParser)
let responseProcessor = ResponseProcessorNode(next: errorProcessor)
let sender = RequestSenderNode(rawResponseProcessor: responseProcessor, responseQueue: responseDispatchQueue, manager: session)
let sender = RequestSenderNode(rawResponseProcessor: responseProcessor, manager: session)

let creator = RequestCreatorNode(next: sender, providers: headersProviders)

Expand All @@ -295,9 +284,8 @@ open class UrlChainsBuilder<Route: UrlRouteProvider> {
let dtoEncoder = DTOEncoderNode<Input, Data>(rawEncodable: rawEncoder)

let indicator = LoadIndicatableNode(next: dtoEncoder)
let configNode = ChainConfiguratorNode(next: indicator)

return LoggerNode(next: configNode, filters: self.logFilter)
return LoggerNode(next: indicator, filters: self.logFilter)
}

}
9 changes: 5 additions & 4 deletions NodeKit/Chains/UrlServiceChainBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ open class UrlServiceChainBuilder {
}

/// Создает цепочку узлов, описывающих транспортный слой обработки.
open func requestTrasportChain(providers: [MetadataProvider], responseQueue: DispatchQueue, session: URLSession?) -> any TransportLayerNode {
let requestSenderNode = RequestSenderNode(rawResponseProcessor: self.urlResponseProcessingLayerChain(),
responseQueue: responseQueue,
manager: session)
open func requestTrasportChain(providers: [MetadataProvider], session: URLSession?) -> any TransportLayerNode {
let requestSenderNode = RequestSenderNode(
rawResponseProcessor: self.urlResponseProcessingLayerChain(),
manager: session
)
let technicalErrorMapperNode = TechnicaErrorMapperNode(next: requestSenderNode)
return RequestCreatorNode(next: technicalErrorMapperNode, providers: providers)
}
Expand Down
11 changes: 0 additions & 11 deletions NodeKit/Core/Convertion/Multipart/MultipartModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,3 @@ open class MultipartModel<T> {
self.init(payloadModel: payloadModel, files: [String: MultipartFileProvider]())
}
}


public extension MultipartModel where T == StubEmptyModel<[String: Data]> {

/// Дополнительный конструктор. Позволяет инициаллизировать модель только одними файлами.
///
/// - Parameter files: Набор файлов для запроса.
convenience init(files: [String: MultipartFileProvider]) {
self.init(payloadModel: StubEmptyModel<[String: Data]>(), files: files)
}
}
38 changes: 0 additions & 38 deletions NodeKit/Core/Convertion/Multipart/StubEmptyModel.swift

This file was deleted.

2 changes: 2 additions & 0 deletions NodeKit/Core/Node/Async/AsyncNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Foundation
/// Протокол, наследованный от Node, добавляющий подход преобразования входных данных в результат с помощью SwiftConcurrency.
/// Применим для узлов, которые возвращают один результат.
public protocol AsyncNode<Input, Output>: Node {
associatedtype Input
associatedtype Output

/// Ассинхронный метод, который содержит логику для обработки данных
///
Expand Down
2 changes: 2 additions & 0 deletions NodeKit/Core/Node/Async/AsyncStreamNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Foundation
/// Протокол, наследованный от Node, добавляющий подход преобразования входных данных в поток результатов с помощью SwiftConcurrency
/// Применим для узлов, которые могут вернуть несколько результатов
public protocol AsyncStreamNode<Input, Output>: Node {
associatedtype Input
associatedtype Output

/// Ассинхронный метод, который содержит логику для обработки данных
///
Expand Down
4 changes: 0 additions & 4 deletions NodeKit/Core/Node/Combine/AsyncCombineNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,4 @@ public struct AsyncCombineNode<Input, Output>: CombineNode {
.receive(on: scheduler)
.eraseToAnyPublisher()
}

public func processLegacy(_ data: Input) -> Observer<Output> {
return node.processLegacy(data)
}
}
Loading

0 comments on commit 915d6f0

Please sign in to comment.