Skip to content

Commit

Permalink
fixes session management for jaicp loggers and livechat
Browse files Browse the repository at this point in the history
  • Loading branch information
Denire committed Mar 5, 2021
1 parent de7d43c commit ea33a88
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 107 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal data class LiveChatInitRequest(
return LiveChatInitRequest(
request = req,
switchData = reply,
sessionId = SessionManager.getOrCreateSessionId(lc).sessionId
sessionId = SessionManager.get(lc).getOrCreateSessionId().sessionId
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package com.justai.jaicf.channel.jaicp.logging


import com.justai.jaicf.api.BotRequest
import com.justai.jaicf.channel.jaicp.*
import com.justai.jaicf.channel.jaicp.DEFAULT_PROXY_URL
import com.justai.jaicf.channel.jaicp.JaicpPollingConnector
import com.justai.jaicf.channel.jaicp.JaicpWebhookConnector
import com.justai.jaicf.channel.jaicp.dto.JaicpBotRequest
import com.justai.jaicf.channel.jaicp.dto.JaicpLogModel
import com.justai.jaicf.channel.jaicp.http.ChatAdapterConnector
import com.justai.jaicf.channel.jaicp.http.HttpClientFactory
import com.justai.jaicf.channel.jaicp.logging.internal.SessionManager.getOrCreateSessionId
import com.justai.jaicf.channel.jaicp.jaicpRequest
import com.justai.jaicf.channel.jaicp.logging.internal.SessionData
import com.justai.jaicf.channel.jaicp.logging.internal.SessionManager
import com.justai.jaicf.helpers.logging.WithLogger
import com.justai.jaicf.logging.ConversationLogObfuscator
import com.justai.jaicf.logging.ConversationLogger
Expand Down Expand Up @@ -46,7 +49,7 @@ open class JaicpConversationLogger(
override fun doLog(loggingContext: LoggingContext) {
try {
val req = loggingContext.jaicpRequest ?: return
val session = getOrCreateSessionId(loggingContext)
val session = SessionManager.get(loggingContext).getOrCreateSessionId()
launch { doLogAsync(req, loggingContext, session) }
} catch (e: Exception) {
logger.debug("Failed to produce JAICP LogRequest: ", e)
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,33 +1,84 @@
package com.justai.jaicf.channel.jaicp.logging.internal

import com.justai.jaicf.context.BotContext
import com.justai.jaicf.channel.jaicp.JSON
import com.justai.jaicf.channel.jaicp.reactions.reaction.EndSessionReaction
import com.justai.jaicf.channel.jaicp.reactions.reaction.NewSessionReaction
import com.justai.jaicf.logging.LoggingContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import java.util.*

internal object SessionManager {

fun processStartSessionReaction(ctx: BotContext) = SessionStarted.saveToContext(ctx)
internal const val SESSION_MANAGER_KEY = "com/justai/jaicf/jaicp/logging/conversationSession/sessionManager"

fun processEndSessionReaction(ctx: BotContext) = SessionEnded.saveToContext(ctx)
@Serializable
internal data class SessionData(
val sessionId: String,
val isNewSession: Boolean
)

fun getOrCreateSessionId(loggingContext: LoggingContext): SessionData {
val ctx = loggingContext.botContext
val sessionData = SessionDataService.fromContext(ctx)
val sessionEvent = SessionEventService.fromContext(ctx)
SessionEventService.cleanup(ctx)
@Serializable
internal class SessionManager {
private var sessionId: String? = null
private var isNewSession: Boolean = false

if (sessionData == null || loggingContext.requestContext.newSession) {
return SessionData.new(ctx).apply { saveToContext(ctx) }
}
@Transient
private var thisRequestSessionData: SessionData? = null

@Transient
lateinit var loggingContext: LoggingContext

return when (sessionEvent) {
// if session started, create new session and save it for further requests
SessionStarted -> SessionData.new(ctx).apply { saveToContext(ctx) }
// if session ended, delete current session
SessionEnded -> sessionData.also {
SessionDataService.cleanup(ctx)
ctx.cleanSessionData()
fun getOrCreateSessionId(): SessionData = thisRequestSessionData ?: runAndSave {
val sessionData = when {
hasNewSessionReaction() -> SessionData(createSessionId(), true)
hasEndSessionReaction() -> when (sessionId) {
null -> SessionData(createSessionId(), true)
else -> SessionData(requireNotNull(sessionId), false)
}
null -> sessionData
shouldStartNewSession() -> SessionData(createSessionId(), true)
else -> SessionData(requireNotNull(sessionId), false)

}

sessionId = when (hasEndSessionReaction()) {
true -> null
false -> sessionData.sessionId
}
sessionData
}

private fun hasNewSessionReaction() = loggingContext.reactions.any { it is NewSessionReaction }

private fun hasEndSessionReaction() = loggingContext.reactions.any { it is EndSessionReaction }

private fun shouldStartNewSession() = sessionId == null || loggingContext.requestContext.newSession

private fun runAndSave(block: SessionManager.() -> SessionData): SessionData {
val sessionData = block.invoke(this)
thisRequestSessionData = sessionData

loggingContext.botContext.session[SESSION_MANAGER_KEY] = JSON.encodeToString(serializer(), this)
loggingContext.botContext.temp[SESSION_MANAGER_KEY] = this
return sessionData
}

private fun createSessionId() = "${loggingContext.botContext.clientId}-${UUID.randomUUID()}"

override fun toString(): String {
return "SessionManager(sessionId=$sessionId, isNewSession=$isNewSession, thisRequestSessionData=$thisRequestSessionData, loggingContext=$loggingContext)"
}


companion object {
fun get(loggingContext: LoggingContext): SessionManager {
// if any component requested session, we finalize session and use it during all request processing
(loggingContext.botContext.temp[SESSION_MANAGER_KEY] as? SessionManager)?.let { return it }

// this is the first call for sessionData, we try to decode it from BotContext and reuse.
val storedSessionState = loggingContext.botContext.session[SESSION_MANAGER_KEY] as? String
val sessionManager = storedSessionState?.let { JSON.decodeFromString(serializer(), it) } ?: SessionManager()
sessionManager.loggingContext = loggingContext
return sessionManager
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.justai.jaicf.channel.jaicp.reactions

import com.justai.jaicf.channel.jaicp.dto.*
import com.justai.jaicf.channel.jaicp.logging.internal.SessionManager
import com.justai.jaicf.channel.jaicp.reactions.reaction.EndSessionReaction
import com.justai.jaicf.channel.jaicp.reactions.reaction.NewSessionReaction
import com.justai.jaicf.channel.jaicp.toJson
import com.justai.jaicf.context.DialogContext
import com.justai.jaicf.logging.SayReaction
Expand All @@ -13,6 +15,7 @@ val Reactions.jaicp get() = this as? JaicpReactions
open class JaicpReactions : Reactions() {

protected val replies: MutableList<Reply> = mutableListOf()

internal val dialer by lazy { JaicpDialerAPI() }

internal fun getCurrentState() = botContext.dialogContext.currentState
Expand All @@ -32,7 +35,7 @@ open class JaicpReactions : Reactions() {
* */
fun startNewSession() {
botContext.cleanSessionData()
SessionManager.processStartSessionReaction(botContext)
registerReaction(NewSessionReaction(getCurrentState()))
}

/**
Expand All @@ -48,7 +51,7 @@ open class JaicpReactions : Reactions() {
fun endSession() {
botContext.dialogContext.currentState = "/"
botContext.dialogContext.currentContext = "/"
SessionManager.processEndSessionReaction(botContext)
registerReaction(EndSessionReaction(getCurrentState()))
}

fun collect(): JsonObject {
Expand All @@ -67,7 +70,7 @@ open class JaicpReactions : Reactions() {
putJsonArray("replies") {
jsonReplies.forEach { add(it) }
}
put("sessionId", SessionManager.getOrCreateSessionId(loggingContext).sessionId)
put("sessionId", SessionManager.get(loggingContext).getOrCreateSessionId().sessionId)
put("answer", answer)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.justai.jaicf.channel.jaicp.reactions.reaction

import com.justai.jaicf.logging.Reaction

data class EndSessionReaction(
override val fromState: String
) : Reaction(fromState)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.justai.jaicf.channel.jaicp.reactions.reaction

import com.justai.jaicf.logging.Reaction

data class NewSessionReaction(
override val fromState: String
) : Reaction(fromState)

0 comments on commit ea33a88

Please sign in to comment.