Skip to content

Commit

Permalink
[KMP] added a 'timeoutMillis' parameter to ApolloHttpNetworkTransport (
Browse files Browse the repository at this point in the history
…#2690)

* added a 'timeoutMillis' parameter to ApolloHttpNetworkTransport

* fix doc

* use setTimeoutInterval()

* fix tests

* use timeoutIntervalForRequest

* fix tests
  • Loading branch information
martinbonnin authored Nov 6, 2020
1 parent a7de353 commit 55b422a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,19 @@ import com.apollographql.apollo.network.NetworkTransport
expect class ApolloHttpNetworkTransport constructor(
serverUrl: String,
headers: Map<String, String>,
httpMethod: HttpMethod = HttpMethod.Post
httpMethod: HttpMethod = HttpMethod.Post,
/**
* The timeout interval to use when connecting
*
* - on iOS, it is used to set [NSMutableURLRequest.timeoutInterval]
* - on Android, it is used to set [OkHttpClient.connectTimeout]
*/
connectTimeoutMillis: Long = 60_000,
/**
* The timeout interval to use when waiting for additional data.
*
* - on iOS, it is used to set [NSURLSessionConfiguration.timeoutIntervalForRequest]
* - on Android, it is used to set [OkHttpClient.readTimeout]
*/
readTimeoutMillis: Long = 60_000,
) : NetworkTransport
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import platform.Foundation.NSURLRequest
import platform.Foundation.NSURLRequestReloadIgnoringCacheData
import platform.Foundation.NSURLResponse
import platform.Foundation.NSURLSession
import platform.Foundation.NSURLSessionConfiguration
import platform.Foundation.NSURLSessionDataTask
import platform.Foundation.dataTaskWithRequest
import platform.Foundation.setHTTPBody
Expand All @@ -50,30 +51,45 @@ import kotlin.coroutines.resumeWithException
import kotlin.native.concurrent.freeze

typealias UrlSessionDataTaskCompletionHandler = (NSData?, NSURLResponse?, NSError?) -> Unit
typealias UrlSessionDataTaskFactory = (NSURLRequest, UrlSessionDataTaskCompletionHandler) -> NSURLSessionDataTask

fun interface DataTaskFactory {
fun dataTask(request: NSURLRequest, completionHandler: UrlSessionDataTaskCompletionHandler): NSURLSessionDataTask
}

@ApolloExperimental
@ExperimentalCoroutinesApi
actual class ApolloHttpNetworkTransport(
private val serverUrl: NSURL,
private val headers: Map<String, String>,
private val httpMethod: HttpMethod,
private val dataTaskFactory: UrlSessionDataTaskFactory
private val dataTaskFactory: DataTaskFactory,
private val connectTimeoutMillis: Long = 60_000,
) : NetworkTransport {

actual constructor(
serverUrl: String,
headers: Map<String, String>,
httpMethod: HttpMethod
httpMethod: HttpMethod,
connectTimeoutMillis: Long,
readTimeoutMillis: Long,
) : this(
serverUrl = NSURL(string = serverUrl),
headers = headers,
httpMethod = httpMethod,
dataTaskFactory = { request, completionHandler ->
NSURLSession.sharedSession.dataTaskWithRequest(request, completionHandler)
}
dataTaskFactory = DefaultDataTaskFactory(readTimeoutMillis),
connectTimeoutMillis = connectTimeoutMillis,
)

private class DefaultDataTaskFactory(readTimeoutMillis: Long) : DataTaskFactory {
private val nsurlSession = NSURLSession.sessionWithConfiguration(NSURLSessionConfiguration().apply {
timeoutIntervalForRequest = readTimeoutMillis.toDouble()/1000
})

override fun dataTask(request: NSURLRequest, completionHandler: UrlSessionDataTaskCompletionHandler): NSURLSessionDataTask {
return nsurlSession.dataTaskWithRequest(request, completionHandler)
}

}
@Suppress("UNCHECKED_CAST")
override fun <D : Operation.Data> execute(request: ApolloRequest<D>, executionContext: ExecutionContext): Flow<ApolloResponse<D>> {
return flow {
Expand Down Expand Up @@ -106,7 +122,7 @@ actual class ApolloHttpNetworkTransport(
return@suspendCancellableCoroutine
}

dataTaskFactory(httpRequest.freeze(), delegate.freeze())
dataTaskFactory.dataTask(httpRequest.freeze(), delegate.freeze())
.also { task ->
continuation.invokeOnCancellation {
task.cancel()
Expand Down Expand Up @@ -138,8 +154,11 @@ actual class ApolloHttpNetworkTransport(
if (variables.isNotEmpty()) NSURLQueryItem(name = "variables", value = variables) else null
}
)
return NSMutableURLRequest.requestWithURL(urlComponents.URL!!).apply {
return NSMutableURLRequest.requestWithURL(
URL = urlComponents.URL!!
).apply {
setHTTPMethod("GET")
setTimeoutInterval(connectTimeoutMillis.toDouble() / 1000)
headers
.plus(httpExecutionContext?.headers ?: emptyMap())
.forEach { (key, value) -> setValue(value, forHTTPHeaderField = key) }
Expand Down Expand Up @@ -204,7 +223,7 @@ actual class ApolloHttpNetworkTransport(
scalarTypeAdapters = request.scalarTypeAdapters
)
Result.Success(
ApolloResponse(
ApolloResponse<D>(
requestUuid = request.requestUuid,
response = response,
executionContext = request.executionContext + HttpExecutionContext.Response(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ class ApolloHttpNetworkTransportTest {
}
}

private fun mockApolloHttpNetworkTransport(dataTaskFactory: UrlSessionDataTaskFactory): ApolloHttpNetworkTransport {
private fun mockApolloHttpNetworkTransport(dataTaskFactory: DataTaskFactory): ApolloHttpNetworkTransport {
return ApolloHttpNetworkTransport(
serverUrl = NSURL(string = "https://apollo.com"),
headers = emptyMap(),
httpMethod = HttpMethod.Post,
dataTaskFactory = dataTaskFactory
dataTaskFactory = dataTaskFactory,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.internal.closeQuietly
import java.io.IOException
import java.time.Duration
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

Expand All @@ -41,18 +42,23 @@ actual class ApolloHttpNetworkTransport(
private val serverUrl: HttpUrl,
private val headers: Headers,
private val httpCallFactory: Call.Factory,
private val httpMethod: HttpMethod
private val httpMethod: HttpMethod,
) : NetworkTransport {

actual constructor(
serverUrl: String,
headers: Map<String, String>,
httpMethod: HttpMethod
httpMethod: HttpMethod,
connectTimeoutMillis: Long,
readTimeoutMillis: Long
) : this(
serverUrl = serverUrl.toHttpUrl(),
headers = headers.toHeaders(),
httpCallFactory = OkHttpClient(),
httpMethod = httpMethod
httpCallFactory = OkHttpClient.Builder()
.connectTimeout(Duration.ofMillis(connectTimeoutMillis))
.readTimeout(Duration.ofMillis(readTimeoutMillis))
.build(),
httpMethod = httpMethod,
)

override fun <D : Operation.Data> execute(request: ApolloRequest<D>, executionContext: ExecutionContext): Flow<ApolloResponse<D>> {
Expand Down

0 comments on commit 55b422a

Please sign in to comment.