Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPT-1998 Удаление старого подхода #126

Merged
merged 6 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>()
mrandrewsmith marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading