Skip to content
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
150 changes: 95 additions & 55 deletions Sources/Networking/DataTranserService/NetworkDataTransferService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,17 @@ public protocol NetworkDataTransferService: AnyObject {
@available(iOS 16, *)
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E) async -> TaskType<T> where E.ResponseType == T

@available(macOS 10.15, *)
@available(iOS 16, *)
func request<T: Decodable, E: RequestableEndpoint>(with endpoint: E) async throws -> T where E.ResponseType == T

@available(iOS 16, *)
@available(macOS 10.15, *)
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async -> TaskTypeCollection<T> where E.ResponseType == T

@available(iOS 16, *)
@available(macOS 10.15, *)
func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async throws -> [T] where E.ResponseType == T
}

// MARK: Concrete Implementation
Expand Down Expand Up @@ -68,6 +76,35 @@ public final class DefaultNetworkDataTransferService {
group.leave()
}
}


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

let decoded: T = try decoder.decode(data: data)
return .success(decoded)
} catch {
self.logger.log(error: error)
return .failure(NetworkDataTransferError.parsing(error))
}
}

private func decode<T: Decodable>(data: Data?, decoder: ResponseDecoder) throws -> T {
do {
guard let data = data else {
throw NetworkDataTransferError.noResponse
}

let decoded: T = try decoder.decode(data: data)
return decoded
} catch {
self.logger.log(error: error)
throw NetworkDataTransferError.parsing(error)
}
}
}

extension DefaultNetworkDataTransferService: NetworkDataTransferService {
Expand Down Expand Up @@ -101,6 +138,36 @@ extension DefaultNetworkDataTransferService: NetworkDataTransferService {
return requestCollection
}

public func request<T: Decodable, E: RequestableEndpoint>(
with endpoint: E,
on queue: (any NetworkDataTransferQueue)? = nil,
completion: @escaping (Result<T, NetworkDataTransferError>) -> Void
) -> (any CancellableHttpRequest)? where E.ResponseType == T {

return networkService.request(endpoint: endpoint) { result in
let completionResult: Result<T, NetworkDataTransferError>

defer {
if let queue = queue {
queue.asyncExecute {
completion(completionResult)
}
}
completion(completionResult)
}

switch result {
case .success(let data):
let result: Result<T, NetworkDataTransferError> = self.decode(data: data, decoder: endpoint.responseDecoder)
completionResult = result
case .failure(let error):
self.logger.log(error: error)
completionResult = .failure(.networkFailure(error))
}
}

}

@available(macOS 10.15, *)
@available(iOS 16, *)
public func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async -> TaskTypeCollection<T> where T == E.ResponseType {
Expand Down Expand Up @@ -130,72 +197,45 @@ extension DefaultNetworkDataTransferService: NetworkDataTransferService {

@available(macOS 10.15, *)
@available(iOS 16, *)
public func request<T:Decodable, E: RequestableEndpoint>(with endpoint: E) async -> TaskType<T> where T == E.ResponseType {
let task = Task {
let responseData = try await networkService.request(endpoint: endpoint).value
let decodedData:T = try self.decode(data: responseData, decoder: endpoint.responseDecoder)

return decodedData
}

return task
}

public func request<T: Decodable, E: RequestableEndpoint>(
with endpoint: E,
on queue: (any NetworkDataTransferQueue)? = nil,
completion: @escaping (Result<T, NetworkDataTransferError>) -> Void
) -> (any CancellableHttpRequest)? where E.ResponseType == T {

return networkService.request(endpoint: endpoint) { result in
let completionResult: Result<T, NetworkDataTransferError>

defer {
if let queue = queue {
queue.asyncExecute {
completion(completionResult)
}
public func request<T: Decodable, E: RequestableEndpoint>(with endpoints: [E]) async throws -> [T] where T == E.ResponseType {
let responseData = try await withThrowingTaskGroup(of: T.self, returning: [T].self) { taskGroup in
for endpoint in endpoints {
taskGroup.addTask {
try await self.request(with: endpoint).value
}
completion(completionResult)
}

switch result {
case .success(let data):
let result: Result<T, NetworkDataTransferError> = self.decode(data: data, decoder: endpoint.responseDecoder)
completionResult = result
case .failure(let error):
self.logger.log(error: error)
completionResult = .failure(.networkFailure(error))
var data: [T] = []

for try await item in taskGroup {
data.append(item)
}

return data
}

return responseData
}

private func decode<T: Decodable>(data: Data?, decoder: ResponseDecoder) -> Result<T, NetworkDataTransferError> {
do {
guard let data = data else {
return .failure(NetworkDataTransferError.noResponse)
}
@available(macOS 10.15, *)
@available(iOS 16, *)
public func request<T:Decodable, E: RequestableEndpoint>(with endpoint: E) async -> TaskType<T> where T == E.ResponseType {
let task = Task {
let responseData = try await networkService.request(endpoint: endpoint).value
let decodedData:T = try self.decode(data: responseData, decoder: endpoint.responseDecoder)

let decoded: T = try decoder.decode(data: data)
return .success(decoded)
} catch {
self.logger.log(error: error)
return .failure(NetworkDataTransferError.parsing(error))
return decodedData
}

return task
}

private func decode<T: Decodable>(data: Data?, decoder: ResponseDecoder) throws -> T {
do {
guard let data = data else {
throw NetworkDataTransferError.noResponse
}

let decoded: T = try decoder.decode(data: data)
return decoded
} catch {
self.logger.log(error: error)
throw NetworkDataTransferError.parsing(error)
}
@available(macOS 10.15, *)
@available(iOS 16, *)
public func request<T:Decodable, E: RequestableEndpoint>(with endpoint: E) async throws -> T where T == E.ResponseType {
let responseData = try await networkService.request(endpoint: endpoint).value
let decodedData:T = try self.decode(data: responseData, decoder: endpoint.responseDecoder)

return decodedData
}
}
4 changes: 2 additions & 2 deletions Tests/NetworkingTests/Network+DataTransferTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ final class NetworkingTests: XCTestCase {
let index = 9
let key: KeyPath<ResponseObject, String> = \.name

let task = await networkDataTransferService.request(with: testEndpoints)
let task: Task<[ResponseObject], Error> = await networkDataTransferService.request(with: testEndpoints)

testEndpoints.forEach { endpoint in
print("=======Endpoint \(endpoint.path)=======")
Expand All @@ -152,7 +152,7 @@ final class NetworkingTests: XCTestCase {
@available(iOS 16, *)
func test_async_service_returns_result() async {
let expectedCount = 10
let task = await networkDataTransferService.request(with: endpoint)
let task: Task<[ResponseObject], Error> = await networkDataTransferService.request(with: endpoint)

do {
let items: [ResponseObject] = try await task.value
Expand Down