Using Ktor results in CallNotFoundException due to work on wrong thread
还没有人认领这个 Issue。
评估
调研方向
报告在 withContext(Dispatchers.IO) 中复现了 PlacesApi.placeAutocomplete(...).await(),并在堆栈跟踪中指向 GaePendingResult.await。首先复现 Ktor/App Engine 请求,并跟踪协程调度器如何与库的请求处理进行交互。确认与线程相关的故障,并且 repository 中有受支持的修复或明确记录的兼容性指导后,即可视为完成。
由索引模型根据 Issue 内容生成。
描述
I'm using Ktor, which is based on coroutines. This seems to be conflicting with the thread manager that the Google Maps Platform Java library uses. It keeps giving me an Unexpected exception from com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager error.
Environment details
- Specify the API at the beginning of the title (for example, "Places: ...")
- OS type and version
- Library version and other environment information
Places Autocomplete
Kotlin 1.4
0.11.0
Steps to reproduce
- Make a request to
PlacesApi.placeAutocomplete(context, query, null).await()
Code example
fun Application.placesAutocomplete() {
routing {
get("/v1/places/autocomplete") {
val parameters = call.request.queryParameters
val query: String? = parameters["query"]
val type: String? = parameters["type"]
if (query == null) {
call.respondParameterRequired("query")
return@get
}
if (query.isBlank()) {
call.respond(AutocompleteResponse(emptyList()))
return@get
}
val PLACES_KEY = System.getenv("PLACES_KEY")
val placeAutocompleteTypes = try {
type?.let { PlaceAutocompleteType.valueOf(type) }
} catch (e: IllegalArgumentException) {
call.respond(HttpStatusCode.BadRequest, "Invalid place type")
return@get
}
val context = GeoApiContext.Builder(GaeRequestHandler.Builder()).apiKey(PLACES_KEY).build()
val placeAutocompleteRequest = PlacesApi.placeAutocomplete(context, query, null)
placeAutocompleteTypes?.let { types ->
placeAutocompleteRequest.types(types)
}
try {
val placeAutocompleteResponse = withContext(Dispatchers.IO) { placeAutocompleteRequest.await() }
val places = placeAutocompleteResponse.map {
val formatting = it.structuredFormatting
Place(
placeId = it.placeId, mainText = formatting.mainText
?: "", secondaryText = formatting.secondaryText
?: ""
)
}
val autocompleteResponse = AutocompleteResponse(places)
call.respond(autocompleteResponse)
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, e)
}
}
}
}
Stack trace
com.google.maps.errors.UnknownErrorException: Unexpected exception from com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager
at com.google.maps.internal.GaePendingResult.await(GaePendingResult.java:121)
at com.google.maps.PendingResultBase.await(PendingResultBase.java:58)
at appengine.PlacesAutocompleteKt$placesAutocomplete$1$1$placeAutocompleteResponse$1.invokeSuspend(PlacesAutocomplete.kt:74)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:272)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at appengine.PlacesAutocompleteKt$placesAutocomplete$1$1.invokeSuspend(PlacesAutocomplete.kt:74)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:175)
at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:137)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:108)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:307)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:317)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:249)
at retrofit2.KotlinExtensions$awaitResponse$2$2.onResponse(KotlinExtensions.kt:93)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:129)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
- 主要语言
- Java
- 星标
- 1.8k
- 派生
- 972
- 平均合并
- 5 小时 7 分钟
- 30 天内合并 PR
- 1
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
googlemaps/google-maps-services-java 的其他 Issue
-
PlacesApi.placeDetails(context, placeId).await() interface error可能已有人在做 @madtriceps 于 99 天前认领。 未关闭triage me type: bug
难度 3/5 1-2 天 新手友好度 48/100
-
triage me type: feature request
难度 5/5 一周以上 新手友好度 10/100
-
Bagg hacm未关闭
难度 5/5 一周以上 新手友好度 5/100
googlemaps/google-maps-services-java#1059 · 1 个 reaction ·
-
Issue in java da未关闭
难度 5/5 一周以上 新手友好度 10/100
-
Issue in java da未关闭
难度 5/5 一周以上 新手友好度 10/100
查看 googlemaps/google-maps-services-java 的全部 Issue
相似的 Issue
-
Area-UIUX Issue-Bug Issue-Easy (good first issue)
难度 2/5 1-3 小时 新手友好度 67/100
TeamAmaze/AmazeFileManager#4769 ·
维护者通常 7 天内回复
-
Expose SManga.memo & SChapter.memo fields in GraphQL APIs to support source-specific client features未关闭enhancement
难度 2/5 1-3 小时 新手友好度 72/100
Suwayomi/Suwayomi-Server#2551 ·
维护者通常 9 天内回复
-
CLI: enforce absolute ADB device paths in file and directory commands可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
weaviate/java-client#631 ·
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 2 天内回复