https://kotlinlang.org logo
#http4k
Title
# http4k
d

DanielZ

09/25/2023, 7:10 AM
Hey, I've a service which is calling multiple other ones. For logging and tracing we utilize zipkin. Now we would like to make the calls to the other services in parallel - is there a way to do that? With coroutines I lose the information stored in ThreadLocal - any ideas/suggestions?
s

s4nchez

09/25/2023, 7:13 AM
We’ve done that kind of thing with ThreadPoolExecutor services
👍 2
btw, you still need to copy the initial tracing data from the main thread to the sub-threads, but that can be easily done with
ZipkinTracesStorage.THREAD_LOCAL.forCurrentThread()
and
ZipkinTracesStorage.THREAD_LOCAL.setForCurrentThread(initialTraces)
As this is not the first time people ask about this, I've put a small recipe in the docs.
❤️ 2
d

DanielZ

09/26/2023, 8:34 AM
Thanks a lot for your awesome support http4k
🙏 1
d

dave

09/26/2023, 5:56 PM
@DanielZ FYI - we've internalised the messy ThreadLocal calls from the example into a wrapper for an ExecutorService - there's now just a handy extension function
ExecutorService.withRequestTracing()
which should make things a lot neater! We've updated the example and have released this extension function as a part of http4k v5.8.2.0. 🙂
d

DanielZ

09/26/2023, 7:58 PM
Nice, I'll adjust our service 💯 💪
f

fredrik.nordin

09/27/2023, 8:01 AM
Ooh, very nice 👍
d

DanielZ

09/27/2023, 8:03 AM
Yeah, it's supercool. The first thing I did this morning integrate it into my service and deploy 😃 it's such a fun working with http4k
❤️ 3
n

Nicola

09/29/2023, 12:11 PM
I've done the same thing with RunBlocking and coroutines .. what's wrong with this approach?
s

s4nchez

09/29/2023, 12:24 PM
@Nicola do you have an example? I'd be curious to compare the example above with the equivalent using coroutines. My first thought is that there's nothing inherently wrong, but I expect people would be looking for specific benefits if they're adding a new dependency for something that Java supports out of the box.
n

Nicola

09/29/2023, 12:26 PM
The core lines are something like these:
Copy code
requestsChunks.forEach {
    apiResponses
        .add(CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>)
            .async {
                mavService.send(it)
            })
}

runBlocking {
    apiResponses
        .awaitAll()
        .flatMap {
            it.toList()
        }
}
Inside "mavService.send" there is an ok http client which calls an external service
The idea is that the client agrees to wait until all responses are ready
d

DanielZ

10/01/2023, 10:04 AM
@Nicola if I understood the idea by @s4nchez and @dave correctly is to keep the dependencies as small as possible - so no extra dependency for coroutines. Regarding your suggested solution, I don’t understand how you preserve zipkin traces to keep traceability? I thought I have to provide these information as additional context element and then set it anyways in each single coroutine?
n

Nicola

10/02/2023, 7:04 AM
@DanielZ I have no zipkin traces .. (to be honest I don't know what they are..) and I don't care about the coroutine dependencies too. I thought coroutines are better than jvm threads so I always prefer them ...
d

DanielZ

10/02/2023, 7:22 AM
Okay, I understand. In this case it doesn’t solve my problem, since I have to trace all requests. Thank you for your input 😊
👍 1
2 Views