Expose rest API with non blocking call.
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / commons / rest-lib / src / main / kotlin / org / onap / ccsdk / cds / blueprintsprocessor / rest / service / RestLoggerService.kt
index 969de83..846a94a 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
 
-import kotlinx.coroutines.*
+import kotlinx.coroutines.AbstractCoroutine
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.InternalCoroutinesApi
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.handleCoroutineException
+import kotlinx.coroutines.newCoroutineContext
 import kotlinx.coroutines.reactor.ReactorContext
 import kotlinx.coroutines.reactor.asCoroutineContext
+import kotlinx.coroutines.withContext
 import org.apache.http.message.BasicHeader
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_INVOCATION_ID
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_PARTNER_NAME
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.ONAP_REQUEST_ID
@@ -37,7 +46,7 @@ import java.net.InetAddress
 import java.time.ZoneOffset
 import java.time.ZonedDateTime
 import java.time.format.DateTimeFormatter
-import java.util.*
+import java.util.UUID
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
 
@@ -51,8 +60,7 @@ class RestLoggerService {
         fun httpInvoking(headers: Array<BasicHeader>) {
             headers.plusElement(BasicHeader(ONAP_REQUEST_ID, MDC.get("InvocationID").defaultToUUID()))
             headers.plusElement(BasicHeader(ONAP_INVOCATION_ID, UUID.randomUUID().toString()))
-            val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor"
-            headers.plusElement(BasicHeader(ONAP_PARTNER_NAME, partnerName))
+            headers.plusElement(BasicHeader(ONAP_PARTNER_NAME, BluePrintConstants.APP_NAME))
         }
     }
 
@@ -79,8 +87,7 @@ class RestLoggerService {
             val resHeaders = response.headers
             resHeaders[ONAP_REQUEST_ID] = MDC.get("RequestID")
             resHeaders[ONAP_INVOCATION_ID] = MDC.get("InvocationID")
-            val partnerName = System.getProperty("APPNAME") ?: "BlueprintsProcessor"
-            resHeaders[ONAP_PARTNER_NAME] = partnerName
+            resHeaders[ONAP_PARTNER_NAME] = BluePrintConstants.APP_NAME
         } catch (e: Exception) {
             log.warn("couldn't set response headers", e)
         } finally {
@@ -89,17 +96,45 @@ class RestLoggerService {
     }
 }
 
+/** Used in Rest controller API methods to populate MDC context to nested coroutines from reactor web filter context. */
+suspend fun <T> mdcWebCoroutineScope(
+    block: suspend CoroutineScope.() -> T
+) = coroutineScope {
+    val reactorContext = this.coroutineContext[ReactorContext]
+    /** Populate MDC context only if present in Reactor Context */
+    val newContext = if (reactorContext != null &&
+        !reactorContext.context.isEmpty &&
+        reactorContext.context.hasKey(MDCContext)
+    ) {
+        val mdcContext = reactorContext.context.get<MDCContext>(MDCContext)
+        if (mdcContext != null)
+            newCoroutineContext(this.coroutineContext + reactorContext + mdcContext)
+        else
+            newCoroutineContext(this.coroutineContext + reactorContext)
+    } else this.coroutineContext
+    // Execute the block with new and old context
+    withContext(newContext) {
+        block()
+    }
+}
 
+@Deprecated(
+    message = "Now CDS supports Coruoutin rest controller",
+    replaceWith = ReplaceWith("mdcWebCoroutineScope")
+)
 /** Used in Rest controller API methods to populate MDC context to nested coroutines from reactor web filter context. */
 @UseExperimental(InternalCoroutinesApi::class)
-fun <T> monoMdc(context: CoroutineContext = EmptyCoroutineContext,
-                block: suspend CoroutineScope.() -> T?): Mono<T> = Mono.create { sink ->
+fun <T> monoMdc(
+    context: CoroutineContext = EmptyCoroutineContext,
+    block: suspend CoroutineScope.() -> T?
+): Mono<T> = Mono.create { sink ->
 
     val reactorContext = (context[ReactorContext]?.context?.putAll(sink.currentContext())
-            ?: sink.currentContext()).asCoroutineContext()
+        ?: sink.currentContext()).asCoroutineContext()
     /** Populate MDC context only if present in Reactor Context */
-    val newContext = if (!reactorContext.context.isEmpty
-            && reactorContext.context.hasKey(MDCContext)) {
+    val newContext = if (!reactorContext.context.isEmpty &&
+        reactorContext.context.hasKey(MDCContext)
+    ) {
         val mdcContext = reactorContext.context.get<MDCContext>(MDCContext)
         GlobalScope.newCoroutineContext(context + reactorContext + mdcContext)
     } else GlobalScope.newCoroutineContext(context + reactorContext)
@@ -111,9 +146,10 @@ fun <T> monoMdc(context: CoroutineContext = EmptyCoroutineContext,
 
 @InternalCoroutinesApi
 class MonoMDCCoroutine<in T>(
-        parentContext: CoroutineContext,
-        private val sink: MonoSink<T>
+    parentContext: CoroutineContext,
+    private val sink: MonoSink<T>
 ) : AbstractCoroutine<T>(parentContext, true), Disposable {
+
     private var disposed = false
 
     override fun onCompleted(value: T) {