Distrito Telefónica. Hub de Innovación y Talento
Contextos asíncronos
Proyecto Reactor
val key = "someKey"
val helloMono = Mono.just("Hello World! Welcome ")
.flatMap { s -> Mono.deferContextual { context -> Mono.just(s + context[key]) } }
.contextWrite { it.put(key, "user") }
helloMono.block() // Will produce "Hello World! Welcome user"
Corrutinas de Kotlin
data class CurrentUser(
val name: String
) : AbstractCoroutineContextElement(CurrentUser) {
companion object Key : CoroutineContext.Key<CurrentUser>
}
suspend fun entry() {
withContext(CurrentUser("user")) {
println(doStuff()) // Will print "Hello World! Welcome user"
}
}
suspend fun doStuff(): String {
val user = currentCoroutineContext()[CurrentUser.Key]?.name ?: "unknown"
return "Hello World! Welcome $user"
}
Trabajar con código heredado basado en hilos
object ReactorContextHolder {
@JvmStatic
private val holder = ThreadLocal<ContextView>()
fun preserve(context: ContextView?) {
holder.set(context)
}
fun get(): ContextView? = holder.get()
fun clear() {
holder.remove()
}
fun asCoroutinesHook() = ReactorContextPropagator()
class ReactorContextPropagator : ThreadContextElement<ContextView?> {
companion object Key : CoroutineContext.Key<ReactorContextPropagator>
override val key = Key
override fun updateThreadContext(context: CoroutineContext): ContextView? =
holder.get().also {
runCatching {
val currentContext = context[ReactorContext]?.context?.readOnly()
preserve(currentContext)
}
}
override fun restoreThreadContext(context: CoroutineContext, oldState: ContextView?) {
runCatching {
preserve(oldState)
}
}
}
}
override fun handle(request: ServerRequest): Mono<ServerResponse> {
return mono(Dispatchers.Unconfined) { // From kotlinx-coroutines-reactor
withContext(reactorContextHolder.asCoroutinesHook()) { // Installs our hook
// Suspend code here
}
}
}
Integración de terceros: Log4J2
ThreadContext.put("request", request.context.requestId.toString())
class ReactorBackedThreadContextMap : ThreadContextMap {
// Other methods removed for brevity
override fun get(key: String?): String? {
return storage()[key]
}
override fun put(key: String, value: String?) {
storage()[key] = value
}
private fun storage(): ConcurrentMap<String, String?> {
return ReactorContextHolder.get().get("threadContextMap")
}
}
Integración de terceros: Retrofit