git.iko.soy/opencode-android
on d643c13 help sign in
opencode-android/app/src/main/java/soy/iko/opencode/di/OpencodeConnection.kt
40 lines 1.5 kB history raw
1package soy.iko.opencode.di
3import soy.iko.opencode.data.model.ServerProfile
4import soy.iko.opencode.data.network.EventStreamClient
5import soy.iko.opencode.data.network.HttpClientFactory
6import soy.iko.opencode.data.network.OpencodeApiClient
7import soy.iko.opencode.data.repo.SessionRepository
8import kotlinx.coroutines.CoroutineScope
9import kotlinx.coroutines.Dispatchers
10import kotlinx.coroutines.Job
11import kotlinx.coroutines.SupervisorJob
12import kotlinx.coroutines.cancel
14/**
15 * An active connection to one opencode server. Bundles the Ktor client, REST API,
16 * SSE event stream, and the reducing repository, all sharing a connection-scoped
17 * coroutine scope that is cancelled on [close].
18 */
19class OpencodeConnection(val profile: ServerProfile) {
21 private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
22 private val scopeJob: Job get() = scope.coroutineContext[Job]!!
24 private val client = HttpClientFactory.create(profile)
25 val api = OpencodeApiClient(client)
26 val events = EventStreamClient(client, scope)
27 val repository = SessionRepository(api, events)
29 /**
30 * Cancel the coroutine scope and wait for in-flight work (including the SSE reader)
31 * to wind down before closing the HTTP client. Calling client.close() while the SSE
32 * coroutine is still mid-request produces a spurious "stream error, will retry"
33 * warning during normal teardown.
34 */
35 suspend fun close() {
36 scope.cancel()
37 scopeJob.join()
38 runCatching { client.close() }
39 }