Skip to content

Commit 372a85e

Browse files
authored
release: 2.3.6 (#420)
2 parents 3149c54 + a576baa commit 372a85e

File tree

5 files changed

+92
-22
lines changed

5 files changed

+92
-22
lines changed

src/main/kotlin/org/gitanimals/core/lock/DistributedLock.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ object DistributedLock {
1616
key: String,
1717
leaseMillis: Long = 10.seconds.inWholeMilliseconds,
1818
waitMillis: Long = 3.seconds.inWholeMilliseconds,
19+
whenAcquireFailed : () -> T = throw LockAcquireFailException(message = "Cannot acquire lock"),
1920
action: () -> T,
2021
): T {
2122
return lockService.withLock(
2223
key = key,
2324
leaseMillis = leaseMillis,
2425
waitMillis = waitMillis,
2526
action = action,
27+
whenAcquireFail = whenAcquireFailed,
2628
)
2729
}
2830

@@ -32,6 +34,7 @@ object DistributedLock {
3234
key: String,
3335
leaseMillis: Long = 10.seconds.inWholeMilliseconds,
3436
waitMillis: Long = 3.seconds.inWholeMilliseconds,
37+
whenAcquireFail : () -> T = throw LockAcquireFailException(message = "Cannot acquire lock"),
3538
action: () -> T,
3639
): T
3740
}

src/main/kotlin/org/gitanimals/core/lock/RedisDistributedLockService.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,22 @@ class RedisDistributedLockService(
1818
key: String,
1919
leaseMillis: Long,
2020
waitMillis: Long,
21-
action: () -> T
21+
whenAcquireFail : () -> T,
22+
action: () -> T,
2223
): T {
2324
val lock = redissonClient.getLock(key)
2425
val acquired = lock.tryLock(waitMillis, leaseMillis, TimeUnit.MILLISECONDS)
2526

2627
return if (acquired) {
2728
runCatching {
2829
action.invoke()
29-
}.getOrElse {
30-
throw it
3130
}.also {
3231
lock.unlock()
32+
}.getOrElse {
33+
throw it
3334
}
3435
} else {
35-
throw LockAcquireFailException(message = "Cannot acquire lock")
36+
whenAcquireFail()
3637
}
3738
}
3839
}

src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import org.gitanimals.core.UpdateUserOrchestrator
55
import org.gitanimals.core.auth.UserEntryPoint
66
import org.gitanimals.core.filter.MDCFilter.Companion.TRACE_ID
77
import org.gitanimals.core.lock.DistributedLock
8+
import org.gitanimals.core.lock.LOCK_KEY_PREFIX
89
import org.gitanimals.core.lock.LOCK_KEY_PREFIX.CREATE_NEW_USER
9-
import org.gitanimals.core.lock.LOCK_KEY_PREFIX.SET_AUTH
1010
import org.gitanimals.render.domain.EntryPoint
1111
import org.gitanimals.render.domain.User
1212
import org.gitanimals.render.domain.UserService
@@ -34,7 +34,9 @@ class AnimationFacade(
3434
fun getFarmAnimation(username: String): String {
3535
return when (userService.existsByName(username)) {
3636
true -> {
37-
setUserAuthInfoIfNotSet(username)
37+
DistributedLock.withLock(key = "${LOCK_KEY_PREFIX.SET_AUTH}:$username") {
38+
setUserAuthInfoIfNotSet(username)
39+
}
3840

3941
val svgAnimation = userService.getFarmAnimationByUsername(username)
4042
eventPublisher.publishEvent(Visited(username, MDC.get(TRACE_ID)))
@@ -51,7 +53,9 @@ class AnimationFacade(
5153
fun getLineAnimation(username: String, personaId: Long, mode: Mode): String {
5254
return when (userService.existsByName(username)) {
5355
true -> {
54-
setUserAuthInfoIfNotSet(username)
56+
DistributedLock.withLock(key = "${LOCK_KEY_PREFIX.SET_AUTH}:$username") {
57+
setUserAuthInfoIfNotSet(username)
58+
}
5559

5660
val svgAnimation = userService.getLineAnimationByUsername(username, personaId, mode)
5761
eventPublisher.publishEvent(Visited(username, MDC.get(TRACE_ID)))
@@ -89,7 +93,10 @@ class AnimationFacade(
8993
}
9094

9195
private fun createNewUser(username: String): User {
92-
return DistributedLock.withLock(key = "$CREATE_NEW_USER:$username") {
96+
return DistributedLock.withLock(
97+
key = "$CREATE_NEW_USER:$username",
98+
whenAcquireFailed = { userService.getUserByName(username) }
99+
) {
93100
runCatching {
94101
val contributionYears = contributionApi.getAllContributionYears(username)
95102
val contributionCountPerYear =
@@ -110,21 +117,19 @@ class AnimationFacade(
110117
}
111118

112119
private fun setUserAuthInfoIfNotSet(username: String) {
113-
DistributedLock.withLock(key = "$SET_AUTH:$username") {
114-
runCatching {
115-
val user = userService.getUserByName(username)
116-
117-
if (user.isAuthInfoSet().not()) {
118-
val githubUserAuthInfo = githubRestApi.getGithubUser(user.getName())
119-
userService.setAuthInfo(
120-
name = user.getName(),
121-
entryPoint = EntryPoint.GITHUB,
122-
authenticationId = githubUserAuthInfo.id,
123-
)
124-
}
125-
}.onFailure {
126-
logger.info("Fail to update userAuthInfo cause: ${it.message}", it)
120+
runCatching {
121+
val user = userService.getUserByName(username)
122+
123+
if (user.isAuthInfoSet().not()) {
124+
val githubUserAuthInfo = githubRestApi.getGithubUser(user.getName())
125+
userService.setAuthInfo(
126+
name = user.getName(),
127+
entryPoint = EntryPoint.GITHUB,
128+
authenticationId = githubUserAuthInfo.id,
129+
)
127130
}
131+
}.onFailure {
132+
logger.info("Fail to update userAuthInfo cause: ${it.message}", it)
128133
}
129134
}
130135
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.gitanimals.core.lock
2+
3+
import com.ninjasquad.springmockk.MockkBean
4+
import io.kotest.core.annotation.DisplayName
5+
import io.kotest.core.spec.style.StringSpec
6+
import io.kotest.matchers.shouldBe
7+
import io.mockk.every
8+
import io.mockk.mockk
9+
import org.redisson.api.RLock
10+
import org.redisson.api.RedissonClient
11+
import org.springframework.test.context.ContextConfiguration
12+
13+
@ContextConfiguration(
14+
classes = [
15+
RedisDistributedLockService::class
16+
]
17+
)
18+
@DisplayName("DistributedLock 클래스의")
19+
class DistributedLockTest(
20+
private val redisDistributedLockService: RedisDistributedLockService,
21+
@MockkBean(relaxed = true) private val redissonClient: RedissonClient,
22+
) : StringSpec({
23+
24+
"Redis 구현채는 Lock획득에 실패했을때, whenAcquireFail 구문을 실행한다"() {
25+
// given
26+
val rLock = mockk<RLock>()
27+
every { redissonClient.getLock(any<String>()) } returns rLock
28+
every { rLock.tryLock(any(), any(), any()) } returns false
29+
30+
// when
31+
val result = redisDistributedLockService.withLock(
32+
key = "test",
33+
whenAcquireFail = { "whenAcquireFail" },
34+
) { "success" }
35+
36+
// then
37+
result shouldBe "whenAcquireFail"
38+
}
39+
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.gitanimals.play
2+
3+
import io.kotest.assertions.throwables.shouldThrow
4+
import io.kotest.core.spec.style.StringSpec
5+
import io.kotest.matchers.shouldBe
6+
7+
class PlayGround : StringSpec({
8+
"runCatching의 also구문은 runCatching에서 예외가 던져져도 동작한다"() {
9+
var isRunAlso = false
10+
shouldThrow<IllegalArgumentException> {
11+
runCatching {
12+
throw IllegalArgumentException("hello?")
13+
}.also {
14+
isRunAlso = true
15+
}.getOrElse {
16+
throw it
17+
}
18+
}
19+
20+
isRunAlso shouldBe true
21+
}
22+
})

0 commit comments

Comments
 (0)