Skip to content

Commit

Permalink
perf: 使用 Okhttp 异步请求方法
Browse files Browse the repository at this point in the history
  • Loading branch information
xz-dev committed Aug 10, 2021
1 parent 3cfdb18 commit 51cbaea
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 61 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ android {
applicationId "net.xzos.upgradeall"
minSdkVersion 21
targetSdkVersion 31
versionCode 84
versionName "0.9.11-rc.1"
versionCode 85
versionName "0.10.0-alpha"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
kapt {
arguments {
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/net/xzos/upgradeall/core/log/LogNotify.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.xzos.upgradeall.core.log

import android.util.Log
import net.xzos.upgradeall.core.utils.coroutines.CoroutinesMutableList
import net.xzos.upgradeall.core.utils.coroutines.CoroutinesMutableMap
import net.xzos.upgradeall.core.utils.oberver.Informer
Expand All @@ -15,6 +16,14 @@ object LogNotify: Informer {

internal fun printLog(logItemData: LogItemData) {
notifyChanged(PRINT_LOG_TAG, logItemData)
when(logItemData.logLevel){
Log.VERBOSE -> Log.v(logItemData.tag, logItemData.msg)
Log.DEBUG -> Log.d(logItemData.tag, logItemData.msg)
Log.INFO -> Log.i(logItemData.tag, logItemData.msg)
Log.WARN -> Log.w(logItemData.tag, logItemData.msg)
Log.ERROR -> Log.e(logItemData.tag, logItemData.msg)
else -> Log.wtf(logItemData.tag, logItemData.msg)
}
}

internal fun logChanged(logMap: CoroutinesMutableMap<ObjectTag, CoroutinesMutableList<LogItemData>>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.IOException
import java.net.SocketTimeoutException
import java.util.concurrent.TimeUnit


object OkHttpApi {

private const val TAG = "OkHttpApi"
private val dispatcher = Dispatcher().apply {
maxRequests = 128
}
private val okHttpClient = OkHttpClient().newBuilder()
.dispatcher(dispatcher)
.callTimeout(15, TimeUnit.SECONDS)
.connectTimeout(15, TimeUnit.SECONDS)
.build()
Expand All @@ -38,9 +41,14 @@ object OkHttpApi {
return callCore(objectTag, url) { post(url, headers, bodyType, bodyText) }
}

fun get(url: String, headers: Map<String, String> = mapOf(), retryNum: Int = 0): Response {
fun get(url: String, headers: Map<String, String> = mapOf(), callback: Callback) {
val request = makeRequest(url, headers)
okHttpClient.newCall(request.build()).enqueue(callback)
}

fun get(url: String, headers: Map<String, String> = mapOf()): Response {
val request = makeRequest(url, headers)
return callRequestWithRetry(request.build(), retryNum)
return callRequest(request.build())
}

fun post(
Expand Down Expand Up @@ -76,19 +84,6 @@ object OkHttpApi {
return callRequest(request.post(body).build())
}

private fun callRequestWithRetry(request: Request, retryNum: Int): Response {
if (retryNum < 0)
throw SocketTimeoutException("$TAG, callRequestWithRetry: no retry")
else return try {
val response = callRequest(request)
if (response.code == 408)
callRequestWithRetry(request, retryNum - 1)
else response
} catch (e: SocketTimeoutException) {
callRequestWithRetry(request, retryNum - 1)
}
}

private fun callRequest(request: Request): Response = okHttpClient.newCall(request).execute()

private fun makeRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import net.xzos.upgradeall.core.data.json.DownloadItem
import net.xzos.upgradeall.core.data.json.ReleaseGson

object ServerApi {
internal val invalidHubUuidList = hashSetOf<String>()

fun getCloudConfig(): String? {
return WebApi.getCloudConfig()
}
Expand All @@ -14,35 +16,35 @@ object ServerApi {
appId: Map<String, String>,
callback: (List<ReleaseGson>?) -> Unit
) {
if (hubUuid in GrpcApi.invalidHubUuidList) {
if (hubUuid in invalidHubUuidList) {
callback(null)
} else {
DataCache.getAppRelease(hubUuid, auth, appId)?.also {
callback(it)
} ?: WebApi.getAppRelease(hubUuid, auth, appId) {
} ?: WebApi.getAppRelease(hubUuid, auth, appId, {
it?.let {
DataCache.cacheAppStatus(hubUuid, auth, appId, it)
}
callback(it)
}
})
}
}

fun getAppReleaseList(
hubUuid: String, auth: Map<String, String>,
appId: Map<String, String>, callback: (List<ReleaseGson>?) -> Unit
) {
if (hubUuid in GrpcApi.invalidHubUuidList) {
if (hubUuid in invalidHubUuidList) {
callback(null)
} else {
DataCache.getAppRelease(hubUuid, auth, appId)?.also {
callback(it)
} ?: WebApi.getAppReleaseList(hubUuid, auth, appId) {
} ?: WebApi.getAppReleaseList(hubUuid, auth, appId, {
it?.let {
DataCache.cacheAppStatus(hubUuid, auth, appId, it)
}
callback(it)
}
})
}
}

Expand Down
124 changes: 87 additions & 37 deletions core/src/main/java/net/xzos/upgradeall/core/module/network/WebApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,84 @@ import com.google.gson.reflect.TypeToken
import net.xzos.upgradeall.core.coreConfig
import net.xzos.upgradeall.core.data.json.DownloadItem
import net.xzos.upgradeall.core.data.json.ReleaseGson
import net.xzos.upgradeall.core.log.Log
import net.xzos.upgradeall.core.log.ObjectTag
import net.xzos.upgradeall.core.log.ObjectTag.Companion.core
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.IOException
import java.net.SocketTimeoutException

internal object WebApi {
private val host = coreConfig.update_server_url
private const val TAG = "WebApi"
private val objectTag = ObjectTag(core, TAG)

private val invalidHubUuidList = hashSetOf<String>()
private val invalidHubUuidList = ServerApi.invalidHubUuidList

fun getCloudConfig(): String? {
val url = "http://$host/v1/rules/download/dev"
return callApiCore {
OkHttpApi.get(url, retryNum = 3)
OkHttpApi.get(url)
}?.body?.string()
}

fun getAppRelease(
hubUuid: String, auth: Map<String, String>,
appId: Map<String, String>, callback: (List<ReleaseGson>?) -> Unit
hubUuid: String, auth: Map<String, String>, appId: Map<String, String>,
callback: (List<ReleaseGson>?) -> Unit, retryNum: Int = 2
) {
if (hubUuid in invalidHubUuidList) callback(null)
if (retryNum < 0 || hubUuid in invalidHubUuidList) callback(null)
val appIdPath = getMapPath(appId)
val authHeader = getAuthHeaderDict(auth)
val url = "http://$host/v1/app/$hubUuid/${appIdPath}/release"
val response = callApiCore { OkHttpApi.get(url, authHeader, retryNum = 3) }
if (response != null) {
when (response.code) {
200 -> {
val responseStr = response.body?.string()
val release = Gson().fromJson(responseStr, ReleaseGson::class.java)
callback(listOf(release))
doOkhttpCall(hubUuid, url, authHeader, {
if (it == null)
callback(null)
else {
when (it.code) {
200 -> {
val responseStr = it.body?.string()
val release = Gson().fromJson(responseStr, ReleaseGson::class.java)
callback(listOf(release))
}
410 -> callback(listOf())
else -> {
Log.e(objectTag, TAG, "getAppRelease: $it")
callback(null)
}
}
410 -> callback(listOf())
400 -> if (response.body?.string() == "no hub: $hubUuid")
invalidHubUuidList.add(hubUuid)
}
}
callback(null)
})
}

fun getAppReleaseList(
hubUuid: String, auth: Map<String, String>,
appId: Map<String, String>, callback: (List<ReleaseGson>?) -> Unit
hubUuid: String, auth: Map<String, String>, appId: Map<String, String>,
callback: (List<ReleaseGson>?) -> Unit, retryNum: Int = 2,
) {
if (hubUuid in invalidHubUuidList) callback(null)
if (retryNum < 0 || hubUuid in invalidHubUuidList) callback(null)
val appIdPath = getMapPath(appId)
val url = "http://$host/v1/app/$hubUuid/${appIdPath}/releases"
val authHeader = getAuthHeaderDict(auth)
val response = callApiCore { OkHttpApi.get(url, authHeader, retryNum = 3) }
if (response != null) {
when (response.code) {
200 -> {
val responseStr = response.body?.string()
val listType = object : TypeToken<ArrayList<ReleaseGson>>() {}.type
val releaseList = Gson().fromJson<List<ReleaseGson>>(responseStr, listType)
callback(releaseList)
doOkhttpCall(hubUuid, url, authHeader, {
if (it == null)
callback(null)
else {
when (it.code) {
200 -> {
val responseStr = it.body?.string()
val listType = object : TypeToken<ArrayList<ReleaseGson>>() {}.type
val releaseList = Gson().fromJson<List<ReleaseGson>>(responseStr, listType)
callback(releaseList)
}
410 -> callback(listOf())
else -> {
Log.e(objectTag, TAG, "getAppReleaseList: $it")
callback(null)
}
}
410 -> callback(listOf())
400 -> if (response.body?.string() == "no hub: $hubUuid")
invalidHubUuidList.add(hubUuid)
}
}
callback(null)
})
}

fun getDownloadInfo(
Expand All @@ -81,20 +93,58 @@ internal object WebApi {
val authHeader = getAuthHeaderDict(auth)
val assetIndexPath = getIntListPath(assetIndex.toList())
val url = "http://$host/v1/app/$hubUuid/${appIdPath}/extra_download/$assetIndexPath"
val response = callApiCore { OkHttpApi.get(url, authHeader, retryNum = 3) }
val response = callApiCore { OkHttpApi.get(url, authHeader) }
val responseStr = response?.body?.string()
val listType = object : TypeToken<ArrayList<DownloadItem>>() {}.type
return Gson().fromJson(responseStr, listType)
}

private fun callApiCore(core: () -> Response): Response? {
return try {
core()
private fun callApiCore(retryNum: Int = 3, core: () -> Response): Response? {
return if (retryNum < 0)
null
else try {
val response = core()
if (response.code == 408) {
Log.w(objectTag, TAG, "callApiCore: Server timeout: $response")
callApiCore(retryNum - 1, core)
} else response
} catch (e: SocketTimeoutException) {
callApiCore(retryNum - 1, core)
} catch (e: Throwable) {
Log.e(objectTag, TAG, "callApiCore: ${e.stackTraceToString()}")
null
}
}

fun doOkhttpCall(
hubUuid: String, url: String, headers: Map<String, String>,
callback: (Response?) -> Unit, retryNum: Int = 2
) {
if (retryNum < 0 || hubUuid in invalidHubUuidList) callback(null)
OkHttpApi.get(url, headers, object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e(
objectTag, TAG,
"doOkhttpCall: url: ${call.request().url}, e: ${e.stackTraceToString()}"
)
callback(null)
}

override fun onResponse(call: Call, response: Response) {
when (response.code) {
408 -> {
Log.w(objectTag, TAG, "doOkhttpCall: Server timeout: $response")
doOkhttpCall(hubUuid, url, headers, callback, retryNum - 1)
return
}
400 -> if (response.body?.string() == "no hub: $hubUuid")
invalidHubUuidList.add(hubUuid)
}
callback(response)
}
})
}

private fun getMapPath(appId: Map<String, String?>): String {
var appIdPath = ""
for ((k, v) in appId) {
Expand Down

0 comments on commit 51cbaea

Please sign in to comment.