Skip to content

Commit f8717ad

Browse files
authored
More details about the channel was closed exception (#7412)
When the channel is closed by the server currently there is not much the developer can tell why its closed. This PR adds more details about why the channel was closed.
1 parent 9b9b8f8 commit f8717ad

File tree

4 files changed

+12
-6
lines changed

4 files changed

+12
-6
lines changed

firebase-ai/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Unreleased
22

33
- [changed] **Breaking Change**: Removed the `candidateCount` option from `LiveGenerationConfig`
4+
- [changed] Added better error messages to `ServiceConnectionHandshakeFailedException`
45

56
# 17.3.0
67

firebase-ai/src/main/kotlin/com/google/firebase/ai/LiveGenerativeModel.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.google.firebase.ai.type.Tool
3232
import com.google.firebase.annotations.concurrent.Blocking
3333
import com.google.firebase.appcheck.interop.InteropAppCheckTokenProvider
3434
import com.google.firebase.auth.internal.InternalAuthProvider
35+
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
3536
import io.ktor.websocket.Frame
3637
import io.ktor.websocket.close
3738
import io.ktor.websocket.readBytes
@@ -114,8 +115,9 @@ internal constructor(
114115
)
115116
.toInternal()
116117
val data: String = Json.encodeToString(clientMessage)
118+
var webSession: DefaultClientWebSocketSession? = null
117119
try {
118-
val webSession = controller.getWebSocketSession(location)
120+
webSession = controller.getWebSocketSession(location)
119121
webSession.send(Frame.Text(data))
120122
val receivedJsonStr = webSession.incoming.receive().readBytes().toString(Charsets.UTF_8)
121123
val receivedJson = JSON.parseToJsonElement(receivedJsonStr)
@@ -131,7 +133,10 @@ internal constructor(
131133
throw ServiceConnectionHandshakeFailedException("Unable to connect to the server")
132134
}
133135
} catch (e: ClosedReceiveChannelException) {
134-
throw ServiceConnectionHandshakeFailedException("Channel was closed by the server", e)
136+
val reason = webSession?.closeReason?.await()
137+
val message =
138+
"Channel was closed by the server.${if(reason!=null) " Details: ${reason.message}" else "" }"
139+
throw ServiceConnectionHandshakeFailedException(message, e)
135140
}
136141
}
137142

firebase-ai/src/main/kotlin/com/google/firebase/ai/common/APIController.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import io.ktor.client.engine.HttpClientEngine
3838
import io.ktor.client.engine.okhttp.OkHttp
3939
import io.ktor.client.plugins.HttpTimeout
4040
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
41-
import io.ktor.client.plugins.websocket.ClientWebSocketSession
41+
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
4242
import io.ktor.client.plugins.websocket.WebSockets
4343
import io.ktor.client.plugins.websocket.webSocketSession
4444
import io.ktor.client.request.HttpRequestBuilder
@@ -174,7 +174,7 @@ internal constructor(
174174
"wss://firebasevertexai.googleapis.com/ws/google.firebase.vertexai.v1beta.GenerativeService/BidiGenerateContent?key=$key"
175175
}
176176

177-
suspend fun getWebSocketSession(location: String): ClientWebSocketSession =
177+
suspend fun getWebSocketSession(location: String): DefaultClientWebSocketSession =
178178
client.webSocketSession(getBidiEndpoint(location)) { applyCommonHeaders() }
179179

180180
fun generateContentStream(

firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import com.google.firebase.ai.common.util.CancelledCoroutineScope
2929
import com.google.firebase.ai.common.util.accumulateUntil
3030
import com.google.firebase.ai.common.util.childJob
3131
import com.google.firebase.annotations.concurrent.Blocking
32-
import io.ktor.client.plugins.websocket.ClientWebSocketSession
32+
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
3333
import io.ktor.websocket.Frame
3434
import io.ktor.websocket.close
3535
import io.ktor.websocket.readBytes
@@ -59,7 +59,7 @@ import kotlinx.serialization.json.Json
5959
@OptIn(ExperimentalSerializationApi::class)
6060
public class LiveSession
6161
internal constructor(
62-
private val session: ClientWebSocketSession,
62+
private val session: DefaultClientWebSocketSession,
6363
@Blocking private val blockingDispatcher: CoroutineContext,
6464
private var audioHelper: AudioHelper? = null,
6565
private val firebaseApp: FirebaseApp,

0 commit comments

Comments
 (0)