Dennis Schröder
04/20/2020, 3:40 PMkotlinx.coroutins.reactor
package to bridge both worlds (reactive -> Coroutines).
Now we want to build an custom ReactiveHealthIndicator
. Therefore we inherit this interface ReactiveHealthIndicator
from package org.springframework.boot.actuate.health
which expects to implement an method with the signature of fun health(): Mono<Health>
.
So far, so good. The problem is that we need to call an suspending function Inside the health()
method. Here is a little snippet, which should explain the problem a bit further:
@Component
class ClientHealthIndicator(private val client: SomeClient) : ReactiveHealthIndicator {
private val logger = KotlinLogging.logger { }
override fun health(): Mono<Health> =
try {
client.getPage("home") // THIS IS THE SUSPEND FUNCTION
Health.up().build().let { Mono.just(it) }
} catch (e: Exception) {
logger.error(e) { "ContentClient health check failed" }
Health.down(e).build().let { Mono.just(it) }
}
}
We tried to use the MonoCoroutine Builder function from kotlinx.coroutins.reactor
to build an scope which returns a Mono.
@Component
class ContentClientHealthIndicator(private val contentJsonClient: ContentJsonClient) : ReactiveHealthIndicator {
private val logger = KotlinLogging.logger { }
override fun health(): Mono<Health> = mono {
try {
contentJsonClient.getPage(it)
Health.up().build()
} catch (e: Exception) {
logger.error(e) { "ContentClient health check failed" }
Health.down(e).build()
}
}
}
This does look good, but fails as fullfiling solution because the only thing that get´s catched is this:
kotlinx.coroutines.JobCancellationException: MonoCoroutine was cancelled
I am a bit helpless here and would appreciate any help.
Thanks in advance
Dennisnicholasnet
04/22/2020, 11:18 AMDennis Schröder
04/22/2020, 1:01 PMoverride suspend fun getPage(slug: String): Page =
try {
s3Client
.getObject(bucketName = bucketName, fileName = "$slug.json")
.mapToObject(mapper)
} catch (e: NoSuchBucketException) {
throw BucketNotFoundException("No matching bucket found.", bucketName)
} catch (e: NoSuchKeyException) {
throw PageNotFoundException("Page with slug: \"$slug\" not found.", slug)
Dennis Schröder
04/22/2020, 1:02 PMsuspend fun getObject(bucketName: String, fileName: String): ByteArray {
val request = GetObjectRequest.builder().bucket(bucketName).key(fileName).build()
return client.getObject(request, AsyncResponseTransformer.toBytes()).await()?.asByteArray()
?: throw IllegalStateException("S3 GetObjectRequest is null without exception")
}
alex
04/24/2020, 9:42 PMAnsh Tyagi
02/03/2024, 3:48 PM