Skip to content

Commit 598fa80

Browse files
committed
refactor coroutine query count logic
1 parent fa28c4a commit 598fa80

File tree

6 files changed

+45
-26
lines changed

6 files changed

+45
-26
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
}
99

1010
group = "hyeon9mak"
11-
version = "2.2.0-spring-boot-2"
11+
version = "2.3.2-rc1-spring-boot-2"
1212

1313
java {
1414
sourceCompatibility = JavaVersion.VERSION_1_8
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
11
package hyeon9mak.multidatasourcequerycounter
22

33
import kotlinx.coroutines.ThreadContextElement
4-
import org.springframework.web.context.request.RequestAttributes
5-
import org.springframework.web.context.request.RequestContextHolder
64
import kotlin.coroutines.CoroutineContext
75

86
/**
97
* https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/
108
*/
119
class CoroutineQueryCountContextElement(
12-
private val requestAttributes: RequestAttributes = RequestContextHolder.currentRequestAttributes(),
13-
) : ThreadContextElement<RequestAttributes> {
10+
var queryCountPerRequest: QueryCountPerRequest? = null,
11+
) : ThreadContextElement<QueryCountPerRequest?> {
1412

1513
companion object Key : CoroutineContext.Key<CoroutineQueryCountContextElement>
1614

1715
override val key: CoroutineContext.Key<CoroutineQueryCountContextElement>
1816
get() = Key
1917

20-
override fun updateThreadContext(context: CoroutineContext): RequestAttributes {
21-
RequestContextHolder.setRequestAttributes(requestAttributes)
22-
return requestAttributes
18+
override fun updateThreadContext(context: CoroutineContext): QueryCountPerRequest? {
19+
return queryCountPerRequest
2320
}
2421

25-
override fun restoreThreadContext(context: CoroutineContext, oldState: RequestAttributes) {
26-
RequestContextHolder.setRequestAttributes(oldState)
22+
override fun restoreThreadContext(context: CoroutineContext, oldState: QueryCountPerRequest?) {
23+
queryCountPerRequest = oldState
2724
}
2825
}

src/main/java/hyeon9mak/multidatasourcequerycounter/HikariDataSourceQueryCounter.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,19 @@ import org.springframework.web.context.request.ServletRequestAttributes
1111
@Aspect
1212
@Component
1313
class HikariDataSourceQueryCounter(
14-
private val queryCountPerRequest: QueryCountPerRequest,
1514
private val queryCountLogger: QueryCountLogger,
1615
) {
1716
@Around("execution( * com.zaxxer.hikari.HikariDataSource.getConnection())")
1817
fun aroundConnection(joinPoint: ProceedingJoinPoint): Any {
1918
val connection = joinPoint.proceed()
19+
val queryCountPerRequest = QueryCountPerRequestHolder.get() ?: return connection
2020
val connectionQueryMonitor = ConnectionQueryMonitor(queryCountPerRequest, connection)
2121
return connectionQueryMonitor.getProxy()
2222
}
2323

2424
@Around("@annotation(countQueries)")
2525
fun aroundCountQueriesMethod(joinPoint: ProceedingJoinPoint, countQueries: CountQueries): Any {
26-
val result = joinPoint.proceed()
27-
26+
val queryCountPerRequest = QueryCountPerRequest()
2827
val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes?
2928

3029
if (attributes.isInRequestScope) {
@@ -37,8 +36,10 @@ class HikariDataSourceQueryCounter(
3736
queryCountPerRequest.apiUrl = countQueries.prefix + className + "." + methodName
3837
}
3938

39+
QueryCountPerRequestHolder.set(queryCountPerRequest)
40+
val result = joinPoint.proceed()
4041
queryCountLogger.logQueryCount(queryCountPerRequest)
41-
42+
QueryCountPerRequestHolder.remove()
4243
return result
4344
}
4445

src/main/java/hyeon9mak/multidatasourcequerycounter/PreparedStatementQueryMonitor.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package hyeon9mak.multidatasourcequerycounter
22

33
import org.aopalliance.intercept.MethodInterceptor
44
import org.aopalliance.intercept.MethodInvocation
5-
import org.springframework.web.context.request.RequestContextHolder
65
import java.lang.System.*
76

87
class PreparedStatementQueryMonitor(
98
private val queryCountPerRequest: QueryCountPerRequest,
109
) : MethodInterceptor {
1110

1211
override fun invoke(invocation: MethodInvocation): Any? {
13-
if (QUERY_METHODS.contains(invocation.method.name) && isRequestScope()) {
12+
if (QUERY_METHODS.contains(invocation.method.name)) {
1413
val startTime = currentTimeMillis()
1514
val result = invocation.proceed()
1615
val endTime = currentTimeMillis()
@@ -23,8 +22,6 @@ class PreparedStatementQueryMonitor(
2322
return invocation.proceed()
2423
}
2524

26-
private fun isRequestScope(): Boolean = RequestContextHolder.getRequestAttributes() != null
27-
2825
companion object {
2926
private val QUERY_METHODS = listOf("executeQuery", "execute", "executeUpdate")
3027
}
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package hyeon9mak.multidatasourcequerycounter
22

3-
import org.springframework.stereotype.Component
4-
import org.springframework.web.context.annotation.RequestScope
3+
import java.util.concurrent.atomic.AtomicInteger
4+
import java.util.concurrent.atomic.AtomicLong
55

6-
@RequestScope
7-
@Component
86
data class QueryCountPerRequest(
97
var apiUrl: String = "",
10-
var totalQueryCount: Int = 0,
11-
var totalQueryMilliSeconds: Long = 0L,
8+
private var _totalQueryCount: AtomicInteger = AtomicInteger(0),
9+
private var _totalQueryMilliSeconds: AtomicLong = AtomicLong(0L),
1210
) {
11+
val totalQueryCount: Int
12+
get() = _totalQueryCount.get()
13+
14+
val totalQueryMilliSeconds: Long
15+
get() = _totalQueryMilliSeconds.get()
16+
1317
fun incrementQueryCount(executionMilliSeconds: Long) {
14-
totalQueryCount++
15-
totalQueryMilliSeconds += executionMilliSeconds
18+
_totalQueryCount.incrementAndGet()
19+
_totalQueryMilliSeconds.addAndGet(executionMilliSeconds)
1620
}
1721
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package hyeon9mak.multidatasourcequerycounter
2+
3+
object QueryCountPerRequestHolder {
4+
5+
private val queryCountPerRequestHolder = ThreadLocal<QueryCountPerRequest?>()
6+
private val coroutineContextElement = CoroutineQueryCountContextElement()
7+
8+
fun set(queryCountPerRequest: QueryCountPerRequest) {
9+
queryCountPerRequestHolder.set(queryCountPerRequest)
10+
coroutineContextElement.queryCountPerRequest = queryCountPerRequest
11+
}
12+
13+
fun get(): QueryCountPerRequest? = queryCountPerRequestHolder.get()
14+
?: coroutineContextElement.queryCountPerRequest
15+
16+
fun remove() {
17+
queryCountPerRequestHolder.remove()
18+
coroutineContextElement.queryCountPerRequest = null
19+
}
20+
}

0 commit comments

Comments
 (0)