This commit is contained in:
lunaticbum 2026-03-13 17:58:19 +09:00
parent 7fa1c36355
commit c5bc3f9bf0
4 changed files with 56 additions and 9 deletions

View File

@ -20,6 +20,7 @@ dependencies {
implementation(compose.desktop.currentOs)
implementation(compose.material)
implementation(compose.materialIconsExtended)
implementation("io.ktor:ktor-client-okhttp-jvm:2.3.11")
// Ktor (Network)
val ktorVersion = "2.3.11"

View File

@ -149,6 +149,7 @@ fun main() = application {
CoroutineScope(Dispatchers.Default).launch {
AutoTradingManager.startAutoDiscoveryLoop()
KisWebSocketManager.onExecutionReceived = AutoTradingManager.onExecutionReceived
KisWebSocketManager.connect()
}
if (config.modelPath.isNotEmpty()) {

View File

@ -2,7 +2,14 @@ package network
import androidx.compose.runtime.mutableStateOf
import io.ktor.client.*
import io.ktor.client.engine.cio.CIO
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.engine.config
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.websocket.*
import io.ktor.client.engine.cio.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.plugins.*
import io.ktor.http.*
import io.ktor.websocket.*
import kotlinx.coroutines.*
@ -12,21 +19,55 @@ import kotlinx.serialization.json.jsonPrimitive
import model.KisSession
import model.RealTimeTrade
import util.AesCrypto
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
object KisWebSocketManager {
private val client = HttpClient {
val os = System.getProperty("os.name").lowercase()
val arch = System.getProperty("os.arch").lowercase()
val isWin = os.contains("win")
private val client = HttpClient(if(isWin){ OkHttp } else { CIO }) {
install(WebSockets) {
pingInterval = 20_000 // 20초마다 표준 웹소켓 핑 전송 (서버-클라이언트 연결 유지 도움)
pingInterval = 20_000
}
install(HttpTimeout) {
requestTimeoutMillis = 30_000 // 전체 요청 시간
connectTimeoutMillis = 10_000 // 서버 연결 시간
socketTimeoutMillis = 30_000 // 데이터 패킷 간격 시간
}
// 엔진별 상세 설정 (config 대신 해당 엔진 명칭 사용)
if (isWin) {
engine {
// OkHttp 환경 특화: 윈도우 네트워크 유휴 상태 방지
this as OkHttpConfig
config {
retryOnConnectionFailure(true)
connectTimeout(15, TimeUnit.SECONDS)
readTimeout(0, TimeUnit.SECONDS) // 무제한 대기
}
}
} else {
engine {
// CIO 엔진 설정
this as CIOEngineConfig
endpoint {
connectTimeout = 15_000
requestTimeout = 30_000
}
}
}
}
private var session: DefaultClientWebSocketSession? = null
private val isConnected = AtomicBoolean(false)
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private var connectJob: Job? = null
// 콜백 리스너
var onPriceUpdate: ((RealTimeTrade) -> Unit)? = null
var onExecutionReceived: ((String, String, String, String, Boolean) -> Unit)? = null
suspend fun connect() {
@ -72,7 +113,7 @@ object KisWebSocketManager {
}
// private val _currentPrice = mutableStateOf("0")
// private val _currentPrice = mutableStateOf("0")
private val currentPrice = androidx.compose.runtime.mutableStateMapOf<String, String>()
// val currentPrice = _currentPrice

View File

@ -164,15 +164,20 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
scope.launch {
var retryCount = 0
val maxRetries = 3
val retryDelay = 90_000L // 1분 30초
val totalDelaySeconds = 90 // 1분 30초 = 90초
var isAuthCompleted = false
while (retryCount <= maxRetries && !isAuthCompleted) {
// 재시도 시 대기 및 카운트다운 표시
if (retryCount > 0) {
statusMessage = "⏳ 인증 재시도 중... (${retryCount}/${maxRetries}) - 1분 30초 후 재시작"
delay(retryDelay)
for (secondsLeft in totalDelaySeconds downTo 1) {
statusMessage = "⚠️ 인증 실패. ${secondsLeft}초 후 자동으로 다시 시도합니다. (시도 ${retryCount}/${maxRetries})"
delay(1000L) // 1초 대기
}
}
statusMessage = if (retryCount == 0) "⏳ 인증 시도 중..." else "${retryCount}차 재시도 중..."
// 1. 설정값 저장
KisSession.config = config
DatabaseFactory.saveConfig(config)
@ -194,9 +199,8 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
retryCount++
if (retryCount > maxRetries) {
statusMessage = "❌ 인증 실패. 3회 재시도 후 중단되었습니다. 키 정보를 확인하세요."
} else {
statusMessage = "⚠️ 인증 실패. 잠시 후 자동으로 다시 시도합니다. (시도 $retryCount)"
}
// 다음 루프에서 카운트다운 진입
}
}
}