Skip to content

Commit

Permalink
[Feat]: Infra 설계
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeon0976 committed May 9, 2024
1 parent 730efcf commit 5e43b23
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 1 deletion.
6 changes: 5 additions & 1 deletion AVIRO.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
C5BA9DF22BECC8F9004FA06E /* NetworkSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BA9DF12BECC8F9004FA06E /* NetworkSessionManager.swift */; };
C5BA9DF42BECC902004FA06E /* NetworkErrorLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BA9DF32BECC902004FA06E /* NetworkErrorLogger.swift */; };
C5BA9DF62BECCD58004FA06E /* DataTransferError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BA9DF52BECCD58004FA06E /* DataTransferError.swift */; };
C5BA9DFB2BED136A004FA06E /* DataTransferErrorLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BA9DFA2BED136A004FA06E /* DataTransferErrorLogger.swift */; };
C5C20BAC2AD504D500855BBB /* AmplitudeUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C20BAB2AD504D500855BBB /* AmplitudeUtility.swift */; };
C5C290742A85E4EC00ED5DCE /* PlaceSegmentedControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C290732A85E4EC00ED5DCE /* PlaceSegmentedControlView.swift */; };
C5C290772A85E4FF00ED5DCE /* PlaceHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C290762A85E4FF00ED5DCE /* PlaceHomeView.swift */; };
Expand Down Expand Up @@ -493,6 +494,7 @@
C5BA9DF12BECC8F9004FA06E /* NetworkSessionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSessionManager.swift; sourceTree = "<group>"; };
C5BA9DF32BECC902004FA06E /* NetworkErrorLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkErrorLogger.swift; sourceTree = "<group>"; };
C5BA9DF52BECCD58004FA06E /* DataTransferError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTransferError.swift; sourceTree = "<group>"; };
C5BA9DFA2BED136A004FA06E /* DataTransferErrorLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTransferErrorLogger.swift; sourceTree = "<group>"; };
C5C20BAB2AD504D500855BBB /* AmplitudeUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmplitudeUtility.swift; sourceTree = "<group>"; };
C5C290732A85E4EC00ED5DCE /* PlaceSegmentedControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceSegmentedControlView.swift; sourceTree = "<group>"; };
C5C290762A85E4FF00ED5DCE /* PlaceHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceHomeView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1703,7 +1705,6 @@
children = (
C5BA9DD32BE8B39B004FA06E /* RequestTable.swift */,
C5BA9DD12BE8AF80004FA06E /* BodyEncoder.swift */,
C5BA9DD52BE8B884004FA06E /* ResponseDecoder.swift */,
);
path = Response_Request;
sourceTree = "<group>";
Expand All @@ -1724,7 +1725,9 @@
C5BA9DF72BECCDB5004FA06E /* DataTransfer */ = {
isa = PBXGroup;
children = (
C5BA9DD52BE8B884004FA06E /* ResponseDecoder.swift */,
C5BA9DF52BECCD58004FA06E /* DataTransferError.swift */,
C5BA9DFA2BED136A004FA06E /* DataTransferErrorLogger.swift */,
C5BA9DC82BE8AB8F004FA06E /* DataTransferService.swift */,
);
path = DataTransfer;
Expand Down Expand Up @@ -2381,6 +2384,7 @@
C58FBF902AC2B83A00AB6EFC /* AVIROAPIManagerProtocol.swift in Sources */,
C5DCBC9F2B91D9FE003502BA /* MyCommentListViewModel.swift in Sources */,
C50F6AF52A68FD6300E942F5 /* EnrollPlacePresenter.swift in Sources */,
C5BA9DFB2BED136A004FA06E /* DataTransferErrorLogger.swift in Sources */,
C50DB7572A9B8DF80078B501 /* EditLocationAddressTextView.swift in Sources */,
C595ACD12A84A4EB00D35123 /* PlaceSummaryView.swift in Sources */,
C520663A2A808DC40038ECCD /* PlaceListHeaderView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,20 @@
//

import Foundation

protocol DataTransferErrorLoggerProtocol {
func log(error: Error)
}

final class DataTransferErrorLogger: DataTransferErrorLoggerProtocol {
func log(error: Error) {
printIfDebug("------------")
printIfDebug("\(error)")
}
}

private func printIfDebug(_ string: String) {
#if DEBUG
print(string)
#endif
}
163 changes: 163 additions & 0 deletions AVIRO/Infrastructure/Network/DataTransfer/DataTransferService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,166 @@
//

import Foundation

protocol DataTransferDispatchQueue {
func asyncExecute(work: @escaping () -> Void)
}

extension DispatchQueue: DataTransferDispatchQueue {
func asyncExecute(work: @escaping () -> Void) {
async(group: nil, execute: work)
}
}

protocol DataTransferServiceProtocol {
typealias CompletionHandler<T> = (Result<T, DataTransferError>) -> Void

@discardableResult
func request<T: Decodable, E: ResponseRequestable>(
with endpoint: E,
on queue: DataTransferDispatchQueue,
completion: @escaping CompletionHandler<T>
) -> NetworkCancellable? where E.Response == T

@discardableResult
func request<T: Decodable, E: ResponseRequestable>(
with endpoint: E,
completion: @escaping CompletionHandler<T>
) -> NetworkCancellable? where E.Response == T

@discardableResult
func request<E: ResponseRequestable>(
with endpoint: E,
on queue: DataTransferDispatchQueue,
completion: @escaping CompletionHandler<Void>
) -> NetworkCancellable? where E.Response == Void

@discardableResult
func request<E: ResponseRequestable>(
with endpoint: E,
completion: @escaping CompletionHandler<Void>
) -> NetworkCancellable? where E.Response == Void
}

protocol DataTransferErrorResolverProtocol {
func resolve(error: NetworkError) -> Error
}

final class DataTransferService {
private let networkService: NetworkService
private let errorResolver: DataTransferErrorResolverProtocol
private let errorLogger: DataTransferErrorLoggerProtocol

init(
networkService: NetworkService,
errorResolver: DataTransferErrorResolverProtocol,
errorLogger: DataTransferErrorLoggerProtocol
) {
self.networkService = networkService
self.errorResolver = errorResolver
self.errorLogger = errorLogger
}
}

extension DataTransferService: DataTransferServiceProtocol {
func request<T: Decodable, E: ResponseRequestable>(
with endpoint: E,
on queue: any DataTransferDispatchQueue,
completion: @escaping CompletionHandler<T>
) -> NetworkCancellable? where T == E.Response {
networkService.request(endPoint: endpoint) { result in
switch result {
case .success(let data):
let result: Result<T, DataTransferError> = self.decode(
data: data,
decoder: endpoint.responseDecoder
)

queue.asyncExecute {
completion(result)
}

case .failure(let error):
self.errorLogger.log(error: error)

let error = self.resolve(networkError: error)

queue.asyncExecute {
completion(.failure(error))
}
}
}
}

func request<T: Decodable, E: ResponseRequestable>(
with endpoint: E,
completion: @escaping CompletionHandler<T>
) -> NetworkCancellable? where T == E.Response {
request(
with: endpoint,
on: DispatchQueue.main,
completion: completion
)
}

func request<E: ResponseRequestable>(
with endpoint: E,
on queue: any DataTransferDispatchQueue,
completion: @escaping CompletionHandler<Void>
) -> NetworkCancellable? where E.Response == Void {
networkService.request(endPoint: endpoint) { result in
switch result {
case .success:
queue.asyncExecute {
completion(.success(()))
}
case .failure(let error):
self.errorLogger.log(error: error)
let error = self.resolve(networkError: error)

queue.asyncExecute {
completion(.failure(error))
}
}
}
}

func request<E: ResponseRequestable>(
with endpoint: E,
completion: @escaping CompletionHandler<Void>
) -> NetworkCancellable? where E.Response == Void {
request(with: endpoint, on: DispatchQueue.main, completion: completion)
}

private func decode<T: Decodable>(
data: Data?,
decoder: ResponseDecoder
) -> Result<T, DataTransferError> {
do {
guard let data = data else { return .failure(.noResponse) }

let result: T = try decoder.decode(data)

return .success(result)
} catch {
self.errorLogger.log(error: error)

return .failure(.parsing(error))
}
}

private func resolve(
networkError error: NetworkError
) -> DataTransferError {
let resolvedError = self.errorResolver.resolve(error: error)

return resolvedError is NetworkError ?
.networkFailure(error) : .resolveNetworkFailure(resolvedError)
}
}

final class DataTransferErrorResolver: DataTransferErrorResolverProtocol {
func resolve(error: NetworkError) -> any Error {
return error
}
}

0 comments on commit 5e43b23

Please sign in to comment.