Skip to content

OkHttp optimizations #1

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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
41 changes: 12 additions & 29 deletions src/main/java/com/wseemann/ecp/core/ECPRequest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import com.wseemann.ecp.api.ResponseCallback
import com.wseemann.ecp.logging.Logger.debug
import com.wseemann.ecp.parser.ECPResponseParser
import kotlinx.coroutines.*
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.jdom2.JDOMException
import java.io.IOException
import java.util.concurrent.TimeUnit

internal abstract class ECPRequest<T>(private val url: String) {
internal abstract class ECPRequest<T>(private val url: String,
private val useRequestCache: Boolean = false) {

constructor(url: String): this(url, false)

protected fun getUrl(): String {
return url
Expand All @@ -33,31 +34,13 @@ internal abstract class ECPRequest<T>(private val url: String) {
val request = DiscoveryRequest(url)
return ECPResponse(generateResponseData(request.send().data, getParser()))
} else {
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(6000, TimeUnit.MILLISECONDS)
.readTimeout(6000, TimeUnit.MILLISECONDS)
.build()

val body = if (getMethod() == "POST") "".toRequestBody() else null

val request = Request.Builder()
.addHeader("User-Agent", "Roku-ECP-Wrapper-Kotlin")
.url(url.toHttpUrl())
.method(getMethod(), body)
.build()
val responseBody = HttpManager.getInstance().execute(url, getMethod(), useRequestCache)
if (responseBody == null)
return null

val call = okHttpClient.newCall(request)
val response = call.execute()

val responseBody = response.body

if (responseBody != null) {
val body = responseBody.bytes()
debug("ECP request response: " + String(body))
return ECPResponse(generateResponseData(body, getParser()))
} else {
return null
}
val body = responseBody.bytes()
debug("ECP request response: " + String(body))
return ECPResponse(generateResponseData(body, getParser()))
}
} catch (ex: JDOMException) {
throw IOException(ex)
Expand Down Expand Up @@ -94,4 +77,4 @@ internal abstract class ECPRequest<T>(private val url: String) {
private companion object {
private const val DISCOVERY = "DISCOVERY"
}
}
}
57 changes: 57 additions & 0 deletions src/main/java/com/wseemann/ecp/core/HttpManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.wseemann.ecp.core

import java.util.concurrent.TimeUnit

import okhttp3.OkHttpClient
import okhttp3.ConnectionPool
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.ResponseBody
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody

class HttpManager private constructor() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mark this as internal class please? It shouldn't be exposed as an end user API.


private val okHttpClient = OkHttpClient.Builder()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are extremely low connection and read times. I'd prefer at least two seconds. While these times may work on your internet connection other users may have less than ideal network conditions are setting the values this low would make this SDK unusable.

.connectionPool(ConnectionPool(20, 1, TimeUnit.SECONDS))
.connectTimeout(40, TimeUnit.MILLISECONDS)
.readTimeout(40, TimeUnit.MILLISECONDS)
.build()

private val requestCache = HashMap<String, Request>()

private fun buildRequest(url: String, method: String, useRequestCache: Boolean): Request {
if (useRequestCache) {
val request = requestCache.get(url)
if (request != null)
return request
}
val body = if (method == "POST") "".toRequestBody() else null
val request = Request.Builder()
.addHeader("User-Agent", "Roku-ECP-Wrapper-Kotlin")
.url(url.toHttpUrl())
.method(method, body)
.build()
if (useRequestCache) {
requestCache.put(url, request)
}
return request
}

public fun execute(url: String, method: String, useRequestCache: Boolean): ResponseBody? {
val request = buildRequest(url, method, useRequestCache)
val call = okHttpClient.newCall(request)
val response = call.execute()
return response.body
}

companion object {

// Volatile modifier is necessary to preserve execution order amoung threads
@Volatile private var instance: HttpManager? = null

fun getInstance() =
instance ?: synchronized(this) { // synchronized to avoid concurrency problems
instance ?: HttpManager().also { instance = it }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final public class KeyPressRequest extends ECPRequest<Void> {
private final String key;

public KeyPressRequest(String url, String key) {
super(url);
super(url, true);
this.key = key;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/wseemann/ecp/request/KeydownRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final public class KeydownRequest extends ECPRequest<Void> {
private final String key;

public KeydownRequest(String url, String key) {
super(url);
super(url, true);
this.key = key;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/wseemann/ecp/request/KeyupRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final public class KeyupRequest extends ECPRequest<Void> {
private final String key;

public KeyupRequest(String url, String key) {
super(url);
super(url, true);
this.key = key;
}

Expand Down