Skip to content

Commit c8f4967

Browse files
CID-3856: Switching from default heartbeats to manual heartbeats
1 parent d8093e4 commit c8f4967

File tree

4 files changed

+49
-11
lines changed

4 files changed

+49
-11
lines changed

src/main/kotlin/net/leanix/githubagent/config/WebSocketClientConfig.kt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import io.github.resilience4j.retry.annotation.Retry
55
import net.leanix.githubagent.handler.BrokerStompSessionHandler
66
import net.leanix.githubagent.services.LeanIXAuthService
77
import net.leanix.githubagent.shared.GitHubAgentProperties.GITHUB_AGENT_VERSION
8-
import org.springframework.beans.factory.annotation.Value
8+
import org.slf4j.LoggerFactory
99
import org.springframework.context.annotation.Bean
1010
import org.springframework.context.annotation.Configuration
1111
import org.springframework.messaging.converter.MappingJackson2MessageConverter
@@ -17,6 +17,7 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient
1717
import org.springframework.web.socket.messaging.WebSocketStompClient
1818
import org.springframework.web.socket.sockjs.client.SockJsClient
1919
import org.springframework.web.socket.sockjs.client.WebSocketTransport
20+
import java.util.concurrent.ScheduledFuture
2021

2122
@Configuration
2223
class WebSocketClientConfig(
@@ -25,21 +26,49 @@ class WebSocketClientConfig(
2526
private val leanIXAuthService: LeanIXAuthService,
2627
private val leanIXProperties: LeanIXProperties,
2728
private val gitHubEnterpriseProperties: GitHubEnterpriseProperties,
28-
@Value("\${websocket.heartbeat-interval}") private val heartbeatInterval: Long
2929
) {
30+
31+
private var heartbeatTask: ScheduledFuture<*>? = null
32+
private val logger = LoggerFactory.getLogger(WebSocketClientConfig::class.java)
33+
3034
@Retry(name = "ws_init_session")
3135
fun initSession(): StompSession {
3236
val headers = WebSocketHttpHeaders()
3337
val stompHeaders = StompHeaders()
3438
stompHeaders["Authorization"] = "Bearer ${leanIXAuthService.getBearerToken()}"
3539
stompHeaders["GitHub-Enterprise-URL"] = gitHubEnterpriseProperties.baseUrl
3640
stompHeaders["GitHub-Agent-Version"] = GITHUB_AGENT_VERSION
37-
return stompClient().connectAsync(
41+
val session = stompClient().connectAsync(
3842
leanIXProperties.wsBaseUrl,
3943
headers,
4044
stompHeaders,
4145
brokerStompSessionHandler,
4246
).get()
47+
48+
sendHeartbeat(session)
49+
return session
50+
}
51+
52+
fun sendHeartbeat(session: StompSession) {
53+
val scheduler = ThreadPoolTaskScheduler()
54+
scheduler.initialize()
55+
heartbeatTask = scheduler.scheduleAtFixedRate({
56+
kotlin.runCatching {
57+
if (session.isConnected) {
58+
session.send("/app/ghe/heartbeat", "")
59+
logger.debug("Heartbeat sent to /app/heartbeat")
60+
} else {
61+
logger.warn("Session is not connected, stopping heartbeat")
62+
stopHeartbeat()
63+
}
64+
}.onFailure {
65+
logger.error("Failed to send heartbeat: ${it.message}")
66+
}
67+
}, java.time.Duration.ofSeconds(30))
68+
}
69+
70+
fun stopHeartbeat() {
71+
heartbeatTask?.cancel(true)
4372
}
4473

4574
@Bean
@@ -52,7 +81,6 @@ class WebSocketClientConfig(
5281
val sockJsClient = SockJsClient(transports)
5382
val stompClient = WebSocketStompClient(sockJsClient)
5483
stompClient.messageConverter = jsonConverter
55-
stompClient.defaultHeartbeat = longArrayOf(heartbeatInterval, 0)
5684
val scheduler = ThreadPoolTaskScheduler()
5785
scheduler.initialize()
5886
stompClient.taskScheduler = scheduler

src/main/resources/application.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ leanix:
1212
technical-user-token: ${LEANIX_TECHNICAL_USER_TOKEN}
1313
webhookEventService:
1414
waitingTime: 10000
15-
websocket:
16-
heartbeat-interval: 30000
1715

1816
resilience4j.retry:
1917
configs:

src/test/kotlin/net/leanix/githubagent/config/WebSocketClientConfigTests.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package net.leanix.githubagent.config
22

33
import com.fasterxml.jackson.databind.ObjectMapper
44
import io.mockk.coEvery
5+
import io.mockk.every
56
import io.mockk.mockk
7+
import io.mockk.verify
68
import kotlinx.coroutines.runBlocking
79
import net.leanix.githubagent.handler.BrokerStompSessionHandler
810
import net.leanix.githubagent.services.LeanIXAuthService
@@ -14,6 +16,7 @@ import org.springframework.messaging.simp.stomp.StompHeaders
1416
import org.springframework.messaging.simp.stomp.StompSession
1517
import org.springframework.web.socket.WebSocketHttpHeaders
1618
import org.springframework.web.socket.messaging.WebSocketStompClient
19+
import java.util.concurrent.ScheduledFuture
1720

1821
class WebSocketClientConfigTests {
1922
private lateinit var webSocketClientConfig: WebSocketClientConfig
@@ -23,6 +26,7 @@ class WebSocketClientConfigTests {
2326
private lateinit var leanIXProperties: LeanIXProperties
2427
private lateinit var gitHubEnterpriseProperties: GitHubEnterpriseProperties
2528
private lateinit var leanIXAuthService: LeanIXAuthService
29+
private lateinit var scheduledFuture: ScheduledFuture<*>
2630

2731
@BeforeEach
2832
fun setUp() {
@@ -34,15 +38,14 @@ class WebSocketClientConfigTests {
3438
stompSession = mockk()
3539
authService = mockk()
3640
leanIXAuthService = mockk()
37-
val heartbeatInterval = 10000L
41+
scheduledFuture = mockk()
3842

3943
webSocketClientConfig = WebSocketClientConfig(
4044
brokerStompSessionHandler,
4145
objectMapper,
4246
leanIXAuthService,
4347
leanIXProperties,
44-
gitHubEnterpriseProperties,
45-
heartbeatInterval
48+
gitHubEnterpriseProperties
4649
)
4750

4851
GitHubAgentProperties.GITHUB_AGENT_VERSION = "test-version"
@@ -66,4 +69,15 @@ class WebSocketClientConfigTests {
6669

6770
assertEquals(null, session)
6871
}
72+
73+
@Test
74+
fun `should send heartbeat when session is connected`() {
75+
val receiptable = mockk<StompSession.Receiptable>()
76+
every { stompSession.isConnected } returns true
77+
every { stompSession.send(any<String>(), any()) } returns receiptable
78+
79+
webSocketClientConfig.sendHeartbeat(stompSession)
80+
81+
verify { stompSession.send("/app/ghe/heartbeat", "") }
82+
}
6983
}

src/test/resources/application.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,3 @@ leanix:
1212
technical-user-token: ${LEANIX_TECHNICAL_USER_TOKEN:dummy}
1313
webhookEventService:
1414
waitingTime: 100
15-
websocket:
16-
heartbeat-interval: 30000

0 commit comments

Comments
 (0)