Skip to content

Commit 792d3b6

Browse files
authored
refactor: Rollback when an exception is thrown in the listener (#116)
* refactor: TransactionHandler가 종료될때, 자동으로 commit, join, rollback event가 발행되도록 수정한다. * refactor: remove unused import and mutablelist to list * refactor: Remove duplicated codes
1 parent 3ff643e commit 792d3b6

File tree

65 files changed

+951
-1114
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+951
-1114
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<br>
88

9-
![version 0.3.6](https://img.shields.io/badge/version-0.3.6-black?labelColor=black&style=flat-square) ![jdk 17](https://img.shields.io/badge/minimum_jdk-17-orange?labelColor=black&style=flat-square) ![load-test](https://img.shields.io/badge/load%20test%2010%2C000%2C000-success-brightgreen?labelColor=black&style=flat-square)
9+
![version 0.3.7](https://img.shields.io/badge/version-0.3.7-black?labelColor=black&style=flat-square) ![jdk 17](https://img.shields.io/badge/minimum_jdk-17-orange?labelColor=black&style=flat-square) ![load-test](https://img.shields.io/badge/load%20test%2010%2C000%2C000-success-brightgreen?labelColor=black&style=flat-square)
1010
![redis--stream](https://img.shields.io/badge/-redis--stream-da2020?style=flat-square&logo=Redis&logoColor=white)
1111

1212
Redis-Stream을 지원하는 Saga frame work 입니다.
@@ -228,8 +228,9 @@ fun exists(param: Any): Mono<Any> {
228228
#### Events-Scenario4. Handle transaction event
229229

230230
다른 분산서버가 (혹은 자기자신이) transactionManager를 통해서 트랜잭션을 시작하거나 트랜잭션 상태를 변경했을때, 트랜잭션 상태에 맞는 핸들러를 호출합니다.
231-
이 핸들러를 구현함으로써, 트랜잭션별 상태를 처리할 수 있습니다. (롤백등)
232-
_롤백은 TransactionRollbackEvent로 전달되는 `undo` 필드를 사용합니다._
231+
이 핸들러를 구현함으로써, 트랜잭션 상태별 로직을 구현할 수 있습니다.
232+
각 핸들러에서 에러가 던져지면, 자동으로 rollback 이 호출됩니다.
233+
233234
> [!WARNING]
234235
> 트랜잭션 핸들러는 반드시 핸들러에 맞는 `TransactionEvent` **하나**만을 파라미터로 받아야 합니다.
235236
@@ -238,27 +239,28 @@ _롤백은 TransactionRollbackEvent로 전달되는 `undo` 필드를 사용합
238239
@TransactionHandler
239240
class TransactionHandler {
240241

241-
@TransactionStartListener(Foo::class) // Receive transaction event when event can be mapped to Foo.class
242+
@TransactionStartListener(event = Foo::class) // Receive transaction event when event can be mapped to Foo.class
242243
fun handleTransactionStartEvent(event: TransactionStartEvent) {
243244
val foo: Foo = event.decodeEvent(Foo::class) // Get event field to Foo.class
244245
// ...
246+
event.setNextEvent(nextFoo) // When this handler terminates and calls the next event or rollback, the event set here is published together.
245247
}
246248

247-
@TransactionJoinHandler // Receive all transaction event when no type is defined.
249+
@TransactionJoinHandler(successWith = SuccessWith.PUBLISH_COMMIT) // Receive all transaction event when no type is defined. And, when terminated this function, publish commit state
248250
fun handleTransactionJoinEvent(event: TransactionJoinEvent) {
249251
// ...
250252
}
251253

252254
@TransactionCommitHandler(
253255
event = Foo::class,
254-
noRetryFor = [IllegalArgumentException::class] // Dont retry when throw IllegalArgumentException. *Retry if throw Throwable or IllegalArgumentException's super type*
256+
noRollbackFor = [IllegalArgumentException::class] // Dont rollback when throw IllegalArgumentException. *Rollback if throw Throwable or IllegalArgumentException's super type*
255257
)
256258
fun handleTransactionCommitEvent(event: TransactionCommitEvent): Mono<String> { // In Webflux framework, publisher must be returned.
257259
throw IllegalArgumentException("Ignore this exception")
258260
// ...
259261
}
260262

261-
@TransactionRollbackHandler
263+
@TransactionRollbackHandler(Foo::class)
262264
fun handleTransactionRollbackEvent(event: TransactionRollbackEvent) { // In Mvc framework, publisher must not returned.
263265
val undo: Foo = event.decodeUndo(Foo::class) // Get event field to Foo.class
264266
}

src/main/kotlin/org/rooftop/netx/api/Exceptions.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package org.rooftop.netx.api
22

3-
import org.rooftop.netx.engine.core.TransactionState
4-
53
class EncodeException(message: String, throwable: Throwable) : RuntimeException(message, throwable)
64

75
class DecodeException(message: String, throwable: Throwable) : RuntimeException(message, throwable)
86

97
open class TransactionException(message: String) : RuntimeException(message)
108

11-
class AlreadyCommittedTransactionException(transactionId: String, state: TransactionState) :
9+
class AlreadyCommittedTransactionException(transactionId: String, state: String) :
1210
TransactionException("Cannot join transaction cause, transaction \"$transactionId\" already \"$state\"")
1311

1412
class NotFoundDispatchFunctionException(message: String) : RuntimeException(message)

src/main/kotlin/org/rooftop/netx/api/Result.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class Result<T : Any> private constructor(
99
private val error: Error? = null,
1010
) {
1111

12+
fun decodeResultOrThrow(typeReference: TypeReference<T>): T = decodeResult(typeReference)
13+
1214
fun decodeResultOrThrow(type: Class<T>): T = decodeResultOrThrow(type.kotlin)
1315

1416
fun decodeResultOrThrow(type: KClass<T>): T {
@@ -18,7 +20,7 @@ class Result<T : Any> private constructor(
1820
return decodeResult(type)
1921
}
2022

21-
fun decodeResult(typeReference: TypeReference<T>): T = result?.let {
23+
fun decodeResult(typeReference: TypeReference<T>): T = result?.let {
2224
codec.decode(it, typeReference)
2325
} ?: throw ResultException("Cannot decode result cause Result is fail state")
2426

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.rooftop.netx.api
2+
3+
enum class SuccessWith {
4+
PUBLISH_JOIN,
5+
PUBLISH_COMMIT,
6+
END,
7+
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package org.rooftop.netx.api
22

3-
class TransactionCommitEvent(
3+
class TransactionCommitEvent internal constructor(
44
transactionId: String,
55
nodeName: String,
66
group: String,
77
event: String?,
88
codec: Codec,
9-
): TransactionEvent(transactionId, nodeName, group, event, codec)
9+
): TransactionEvent(transactionId, nodeName, group, event, codec) {
10+
11+
override fun copy(): TransactionEvent =
12+
TransactionJoinEvent(transactionId, nodeName, group, event, codec)
13+
}

src/main/kotlin/org/rooftop/netx/api/TransactionCommitListener.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ import kotlin.reflect.KClass
66
@Retention(AnnotationRetention.RUNTIME)
77
annotation class TransactionCommitListener(
88
val event: KClass<*> = Any::class,
9-
val noRetryFor: Array<KClass<out Throwable>> = [],
9+
val noRollbackFor: Array<KClass<out Throwable>> = [],
1010
)

src/main/kotlin/org/rooftop/netx/api/TransactionEvent.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,23 @@ sealed class TransactionEvent(
66
val transactionId: String,
77
val nodeName: String,
88
val group: String,
9-
private val event: String?,
10-
private val codec: Codec,
9+
internal val event: String?,
10+
internal val codec: Codec,
11+
internal var nextEvent: Any? = null,
1112
) {
1213

14+
fun <T : Any> setNextEvent(event: T): T {
15+
this.nextEvent = event
16+
return event
17+
}
18+
1319
fun <T : Any> decodeEvent(type: Class<T>): T = decodeEvent(type.kotlin)
1420

1521
fun <T : Any> decodeEvent(type: KClass<T>): T =
1622
codec.decode(
1723
event ?: throw NullPointerException("Cannot decode event cause event is null"),
1824
type
1925
)
26+
27+
internal abstract fun copy(): TransactionEvent
2028
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package org.rooftop.netx.api
22

3-
class TransactionJoinEvent(
3+
class TransactionJoinEvent internal constructor(
44
transactionId: String,
55
nodeName: String,
66
group: String,
77
event: String?,
88
codec: Codec,
9-
): TransactionEvent(transactionId, nodeName, group, event, codec)
9+
) : TransactionEvent(transactionId, nodeName, group, event, codec) {
10+
11+
override fun copy(): TransactionEvent =
12+
TransactionJoinEvent(transactionId, nodeName, group, event, codec)
13+
}

src/main/kotlin/org/rooftop/netx/api/TransactionJoinListener.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import kotlin.reflect.KClass
66
@Retention(AnnotationRetention.RUNTIME)
77
annotation class TransactionJoinListener(
88
val event: KClass<*> = Any::class,
9-
val noRetryFor: Array<KClass<out Throwable>> = [],
9+
val noRollbackFor: Array<KClass<out Throwable>> = [],
10+
val successWith: SuccessWith = SuccessWith.PUBLISH_JOIN,
1011
)

src/main/kotlin/org/rooftop/netx/api/TransactionManager.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import reactor.core.publisher.Mono
44

55
interface TransactionManager {
66

7-
fun <T : Any> start(undo: T): Mono<String>
7+
fun start(): Mono<String>
88

9-
fun <T : Any, S : Any> start(undo: T, event: S): Mono<String>
9+
fun <T : Any> start(event: T): Mono<String>
1010

11-
fun <T : Any> syncStart(undo: T): String
11+
fun syncStart(): String
1212

13-
fun <T : Any, S : Any> syncStart(undo: T, event: S): String
13+
fun <T : Any> syncStart(event: T): String
1414

15-
fun <T : Any> join(transactionId: String, undo: T): Mono<String>
15+
fun join(transactionId: String): Mono<String>
1616

17-
fun <T : Any, S : Any> join(transactionId: String, undo: T, event: S): Mono<String>
17+
fun <T : Any> join(transactionId: String, event: T): Mono<String>
1818

19-
fun <T : Any> syncJoin(transactionId: String, undo: T): String
19+
fun syncJoin(transactionId: String): String
2020

21-
fun <T : Any, S : Any> syncJoin(transactionId: String, undo: T, event: S): String
21+
fun <T : Any> syncJoin(transactionId: String, event: T): String
2222

2323
fun exists(transactionId: String): Mono<String>
2424

0 commit comments

Comments
 (0)