diff --git a/healthcheck/healthcheck-rest/build.gradle.kts b/healthcheck/healthcheck-rest/build.gradle.kts new file mode 100644 index 0000000..6ca3a84 --- /dev/null +++ b/healthcheck/healthcheck-rest/build.gradle.kts @@ -0,0 +1,64 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Kotlin application project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.7/userguide/building_java_projects.html in the Gradle documentation. + * This project uses @Incubating APIs which are subject to change. + */ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. + alias(libs.plugins.jvm) + id("org.springframework.boot") version "3.2.2" + id("io.spring.dependency-management") version "1.1.4" + kotlin("plugin.spring") version "1.9.22" + kotlin("plugin.jpa") version "1.9.22" + // Apply the application plugin to add support for building a CLI application in Java. + application +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // This dependency is used by the application. + implementation(libs.guava) + implementation(platform("org.springframework.boot:spring-boot-dependencies:3.2.2")) + implementation("org.springframework.boot:spring-boot-starter") + implementation("org.springframework.boot:spring-boot-starter-web") +// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta") + implementation(project(":healthcheck")) +} + +tasks.withType { + kotlinOptions { + freeCompilerArgs = listOf("-Xjsr305=strict") + jvmTarget = "17" + } +} + +testing { + suites { + // Configure the built-in test suite + val test by getting(JvmTestSuite::class) { + // Use Kotlin Test test framework + useKotlinTest("1.9.22") + } + } +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +application { + // Define the main class for the application. + mainClass = "com.manhinhang.ibgatewaydocker.healthcheck.rest.MainKt" +} diff --git a/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/HttpControllers.kt b/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/HttpControllers.kt new file mode 100644 index 0000000..e295f07 --- /dev/null +++ b/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/HttpControllers.kt @@ -0,0 +1,27 @@ +package com.manhinhang.ibgatewaydocker.healthcheck.rest +import com.manhinhang.ibgatewaydocker.healthcheck.IBGatewayClient +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import kotlinx.coroutines.* + +@RestController +@RequestMapping("/") +class HealthcheckApiController() { + + val ibClient = IBGatewayClient() + + @GetMapping("/ready") + fun ready(): ResponseEntity { + return ResponseEntity.status(HttpStatus.OK).body("OK"); + } + + @GetMapping("/healthcheck") + fun healthcheck(): ResponseEntity { + val result = runBlocking { ibClient.ping() } + if (result.isSuccess) { + return ResponseEntity.status(HttpStatus.OK).body("OK") + } + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Fail") + } +} \ No newline at end of file diff --git a/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/Main.kt b/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/Main.kt new file mode 100644 index 0000000..aa8d4a5 --- /dev/null +++ b/healthcheck/healthcheck-rest/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/rest/Main.kt @@ -0,0 +1,11 @@ +package com.manhinhang.ibgatewaydocker.healthcheck.rest + +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +class RestApplication + +fun main(args: Array) { + runApplication(*args) +} \ No newline at end of file diff --git a/healthcheck/healthcheck/build.gradle.kts b/healthcheck/healthcheck/build.gradle.kts index f1dac74..51956e4 100644 --- a/healthcheck/healthcheck/build.gradle.kts +++ b/healthcheck/healthcheck/build.gradle.kts @@ -22,6 +22,7 @@ repositories { dependencies { // This dependency is used by the application. implementation(libs.guava) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta") } testing { diff --git a/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/App.kt b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/App.kt new file mode 100644 index 0000000..c62edab --- /dev/null +++ b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/App.kt @@ -0,0 +1,12 @@ +/* + * This source file was generated by the Gradle 'init' task + */ +package com.manhinhang.ibgatewaydocker.healthcheck +import kotlinx.coroutines.* + +fun main() = runBlocking { + val client = IBGatewayClient() + val result = client.ping() + result.exceptionOrNull()?.let { throw it } + return@runBlocking +} \ No newline at end of file diff --git a/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/IBGatewayClient.kt b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/IBGatewayClient.kt new file mode 100644 index 0000000..8ab5cca --- /dev/null +++ b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/IBGatewayClient.kt @@ -0,0 +1,49 @@ +package com.manhinhang.ibgatewaydocker.healthcheck + +import com.ib.client.EClientSocket +import com.ib.client.EJavaSignal +import kotlinx.coroutines.* + +class IBGatewayClient { + val client: EClientSocket + companion object { + val clientId = (System.getenv("HEALTHCHECK_CLIENT_ID")?.toIntOrNull() ?: 999) + val port = (System.getenv("IB_GATEWAY_INTERNAL_PORT")?.toIntOrNull() ?: 4001) + val host = "localhost" + } + + init { + client = createIBClient() + } + + private fun createIBClient(): EClientSocket { + val signal = EJavaSignal(); + val client = EClientSocket(Wrapper(), signal) + return client + } + + suspend fun connect():Boolean = withContext(Dispatchers.IO) { + if (!client.isConnected) { + val client = createIBClient() + client.eConnect(host, port, clientId) + } + client.isConnected + } + + fun disconnect() { + client.eDisconnect() + } + + suspend fun ping():Result = coroutineScope { + runCatching { + val isConnected = connect() + if (isConnected) { + println("Ping IB Gateway successful") + client.eDisconnect() + }else { + throw InterruptedException("Can not connect to IB Gateway") + } + } + } + +} \ No newline at end of file diff --git a/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/Wrapper.kt b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/Wrapper.kt similarity index 100% rename from healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/Wrapper.kt rename to healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/Wrapper.kt diff --git a/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/App.kt b/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/App.kt deleted file mode 100644 index ccc4b60..0000000 --- a/healthcheck/healthcheck/src/main/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/App.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This source file was generated by the Gradle 'init' task - */ -package com.manhinhang.ibgatewaydocker.healthcheck -import com.ib.client.*; -import kotlin.system.exitProcess - -fun main() { - - val clientId = (System.getenv("HEALTHCHECK_CLIENT_ID").toIntOrNull() ?: 999) - val port = (System.getenv("IB_GATEWAY_INTERNAL_PORT").toIntOrNull() ?: 4001) - val signal = EJavaSignal(); - val client = EClientSocket(Wrapper(), signal) - client.eConnect("localhost", port, clientId) - val reader = EReader(client, signal) - reader.start() - Thread { - while (client.isConnected) { - client.eDisconnect() - exitProcess(0) - } - exitProcess(-1) - }.start() -} diff --git a/healthcheck/healthcheck/src/test/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/AppTest.kt b/healthcheck/healthcheck/src/test/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/AppTest.kt similarity index 100% rename from healthcheck/healthcheck/src/test/kotlin/com/manhinhang/ibgatewaydocker/heathcheck/AppTest.kt rename to healthcheck/healthcheck/src/test/kotlin/com/manhinhang/ibgatewaydocker/healthcheck/AppTest.kt diff --git a/healthcheck/settings.gradle.kts b/healthcheck/settings.gradle.kts index 0913209..39f410d 100644 --- a/healthcheck/settings.gradle.kts +++ b/healthcheck/settings.gradle.kts @@ -13,3 +13,4 @@ plugins { rootProject.name = "healthcheck" include("healthcheck") +include("healthcheck-rest")