Armeria 라우터로부터 사용자의 요청을 받을 경우, ServiceRequestContext 를 통해 사용자 요청에 대한 정보를 저장할 수 있다.
비동기 시스템의 경우 하나의 요청에 대해 스레드가 변할 수 있기 때문에 스레드 로컬 기반으로 사용자의 요청 정보를 저장하면 데이터가 유실될 수 있다.
ServiceRequestContext를 통해 사용자의 요청 ID 를 저장할 수 있으며 이를 추적 ID로 사용할 수 있다.
grpc-kotlin 서비스의 suspend function을 사용하는 경우 CoroutineContext는 ServiceRequestContext와 이벤트 루프 CoroutineDispatcher의 조합으로 ServiceRequestContext.current()를 사용하여 suspend 함수에서 ServiceRequestContext에 접근할 수 있다.
class ArmeriaRequestCoroutineContext internal constructor(
private val requestContext: RequestContext,
) : ThreadContextElement<SafeCloseable>, AbstractCoroutineContextElement(Key) {
companion object Key : CoroutineContext.Key<ArmeriaRequestCoroutineContext>
override fun updateThreadContext(context: CoroutineContext): SafeCloseable {
return requestContext.push()
}
override fun restoreThreadContext(
context: CoroutineContext,
oldState: SafeCloseable,
) {
oldState.close()
}
}
코루틴의 withContext를 사용한다면 RequestContext는 전파 가능하며 CoroutineScope와 같이 별도의 독립적인 코루틴을 만든다면 RequestContext는 CoroutineContext로 변환하여 컨텍스트로 함께 추가해주어야 한다.