Skip to content

Commit 772cd2a

Browse files
cjusticeclaude
andauthored
Preserve SerializableError in CachedError for proper error handling (#77)
* Preserve SerializableError in CachedError for proper error handling Add serializableError field to CachedError to preserve exception type information from cached idempotent requests. This enables consumers to properly handle cached errors based on the original exception type. Breaking change: CachedError constructor signature now requires serializableError parameter. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Fix IdempotencyHandlerTest to use new CachedError constructor Update test assertions to construct CachedError with SerializableError parameter after adding serializableError field to CachedError data class. --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 3095334 commit 772cd2a

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

common/src/main/kotlin/xyz/block/bittycity/common/idempotency/SerializableError.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ data class SerializableError(
55
val type: String
66
) {
77

8-
fun asCachedError(): CachedError = CachedError("[$type] $message")
8+
fun asCachedError(): CachedError = CachedError("[$type] $message", this)
99

1010
companion object {
1111
fun from(t: Throwable): SerializableError = SerializableError(
@@ -15,4 +15,7 @@ data class SerializableError(
1515
}
1616
}
1717

18-
data class CachedError(override val message: String?) : Throwable(message)
18+
data class CachedError(
19+
override val message: String?,
20+
val serializableError: SerializableError
21+
) : Throwable(message)

outie/src/test/kotlin/xyz/block/bittycity/outie/controllers/IdempotencyHandlerTest.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package xyz.block.bittycity.outie.controllers
33
import app.cash.quiver.extensions.success
44
import xyz.block.bittycity.common.idempotency.CachedError
55
import xyz.block.bittycity.common.idempotency.IdempotentResumeInputs
6+
import xyz.block.bittycity.common.idempotency.SerializableError
67
import xyz.block.bittycity.outie.models.Inputs
78
import xyz.block.bittycity.outie.models.ObservedInMempool
89
import xyz.block.bittycity.outie.models.RequirementId
@@ -90,7 +91,11 @@ class IdempotencyHandlerTest : BittyCityTestCase() {
9091

9192
// Second call should return the cached error
9293
val secondResult = idempotencyHandler.handle(withdrawalToken, backCounter, hurdleResponses)
93-
secondResult.shouldBeFailure(CachedError("[java.lang.RuntimeException] Test error"))
94+
val expectedError = SerializableError(
95+
message = "Test error",
96+
type = "java.lang.RuntimeException"
97+
)
98+
secondResult.shouldBeFailure(CachedError("[java.lang.RuntimeException] Test error", expectedError))
9499
}
95100

96101
@Test
@@ -515,7 +520,11 @@ class IdempotencyHandlerTest : BittyCityTestCase() {
515520

516521
// Second call should return the cached error
517522
val secondResult = idempotencyHandler.handleResume(withdrawalToken, resumeResult)
518-
secondResult.shouldBeFailure(CachedError("[java.lang.RuntimeException] Test resume error"))
523+
val expectedResumeError = SerializableError(
524+
message = "Test resume error",
525+
type = "java.lang.RuntimeException"
526+
)
527+
secondResult.shouldBeFailure(CachedError("[java.lang.RuntimeException] Test resume error", expectedResumeError))
519528
}
520529

521530
@Test

0 commit comments

Comments
 (0)