1
- # 🖥️ Kotlin Coroutine 환경 QueryCountPerRequest 사용 가이드
1
+ # 🖥️ Kotlin Coroutine 환경 QueryCountPerRequest 동작 원리 가이드
2
2
3
3
** 한국어** | [ English] ( README-kotlin-coroutine-environments-EN.md )
4
4
@@ -9,7 +9,7 @@ Multi-Datasource-Query-Counter 라이브러리는 API 요청별 DB 쿼리 수를
9
9
그러나 Kotlin Coroutine 환경에서는 Coroutine 이 스레드를 자유롭게 이동(` suspension ` , ` resumption ` )할 수 있기 때문에,
10
10
` RequestContextHolder ` 의 컨텍스트가 유지되지 않는 문제가 발생할 수 있습니다.
11
11
12
- 이 가이드는 Coroutine 환경에서 ` QueryCountPerRequest ` 를 올바르게 사용하는 방법을 설명합니다.
12
+ 이 가이드는 Coroutine 환경에서 ` QueryCountPerRequest ` 를 올바르게 측정할 수 있는 원리를 설명합니다.
13
13
14
14
<br >
15
15
@@ -29,32 +29,58 @@ Coroutine 은 다음과 같은 특성을 갖습니다.
29
29
30
30
### 1. CoroutineQueryCountContextElement 활용
31
31
32
- ` CoroutineQueryCountContextElement ` 는 [ ` ThreadContextElement ` 인터페이스] ( https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/ ) 를 구현하여 분화되는 Coroutine 컨텍스트에 ` RequestAttributes ` 를 전파합니다.
32
+ ` CoroutineQueryCountContextElement ` 는 [ ` ThreadContextElement ` 인터페이스] ( https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/ ) 를 구현하여 전파되는 컨텍스트 요소입니다.
33
+ 분화되는 Coroutine 컨텍스트에 ` QueryCountPerRequest ` 지닌 상태로 전파됩니다.
33
34
34
35
``` kotlin
35
36
class CoroutineQueryCountContextElement (
36
- private val requestAttributes : RequestAttributes = RequestContextHolder .currentRequestAttributes() ,
37
- ) : ThreadContextElement<RequestAttributes > {
37
+ var queryCountPerRequest : QueryCountPerRequest ? = null ,
38
+ ) : ThreadContextElement<QueryCountPerRequest? > {
38
39
39
40
companion object Key : CoroutineContext.Key<CoroutineQueryCountContextElement>
40
41
41
42
override val key: CoroutineContext .Key <CoroutineQueryCountContextElement >
42
43
get() = Key
43
44
44
- override fun updateThreadContext (context : CoroutineContext ): RequestAttributes {
45
- RequestContextHolder .setRequestAttributes(requestAttributes)
46
- return requestAttributes
45
+ override fun updateThreadContext (context : CoroutineContext ): QueryCountPerRequest ? {
46
+ return queryCountPerRequest
47
47
}
48
48
49
- override fun restoreThreadContext (context : CoroutineContext , oldState : RequestAttributes ) {
50
- RequestContextHolder .setRequestAttributes( oldState)
49
+ override fun restoreThreadContext (context : CoroutineContext , oldState : QueryCountPerRequest ? ) {
50
+ queryCountPerRequest = oldState
51
51
}
52
52
}
53
53
```
54
54
55
- 실제 구현체는 라이브러리에 포함되어 있으므로, 곧바로 사용할 수 있습니다.
55
+ ### 2. CoroutineQueryCountContextElement 로 부터 QueryCountPerRequest 획득
56
56
57
- ### 2. 사용 예제
57
+ ` QueryCountPerRequestHolder ` 를 통해 ` CoroutineQueryCountContextElement ` 를 호출하여 ` QueryCountPerRequest ` 를 획득합니다.
58
+
59
+ ``` kotlin
60
+ object QueryCountPerRequestHolder {
61
+
62
+ private val queryCountPerRequestHolder = ThreadLocal <QueryCountPerRequest ?>()
63
+ private val coroutineContextElement = CoroutineQueryCountContextElement ()
64
+
65
+ fun set (queryCountPerRequest : QueryCountPerRequest ) {
66
+ queryCountPerRequestHolder.set(queryCountPerRequest)
67
+ coroutineContextElement.queryCountPerRequest = queryCountPerRequest
68
+ }
69
+
70
+ fun get (): QueryCountPerRequest ? = queryCountPerRequestHolder.get()
71
+ ? : coroutineContextElement.queryCountPerRequest
72
+
73
+ fun remove () {
74
+ queryCountPerRequestHolder.remove()
75
+ coroutineContextElement.queryCountPerRequest = null
76
+ }
77
+ }
78
+
79
+ ```
80
+
81
+ ### 3. 사용 예제
82
+
83
+ 자신의 Coroutine 컨텍스트에서 ` QueryCountPerRequest ` 를 자연스럽게 획득하므로, 별도의 코드 수정이 필요 없습니다.
58
84
59
85
``` kotlin
60
86
@RestController
@@ -64,10 +90,7 @@ class UserController(
64
90
@CountQueries
65
91
@GetMapping(" /users/coroutine" )
66
92
fun getUsers () {
67
- // 이제 이 Coroutine 과 분화되는 Coroutine 들은 서로 같은 RequestAttributes 를 유지함
68
- val element = CoroutineQueryCountContextElement ()
69
- val threadPool = ForkJoinPool (2 )
70
- return runBlocking(threadPool.asCoroutineDispatcher() + element) {
93
+ return runBlocking {
71
94
val usersDeferred = async {
72
95
userRepository.findAllUsers() // 쿼리 카운트 지점.
73
96
}
0 commit comments