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

[KMP] added a 'timeoutMillis' parameter to ApolloHttpNetworkTransport #2690

Merged
merged 6 commits into from
Nov 6, 2020
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
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 @@ -203,7 +222,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