Skip to content

Commit 6fd0225

Browse files
committed
docs(response): clarify value() unchecked-throw surface and handler nullability; release empty() drain buffer deterministically
1 parent 35a1cab commit 6fd0225

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/response/ParsedResponse.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,12 @@ public class ParsedResponse<out T> internal constructor(
8484
* just [IOException]. Handlers commonly throw **unchecked** exceptions (the Jackson `jsonHandler`
8585
* throws `SerdeException`), so callers should not assume the only escape is [IOException].
8686
*
87-
* @return The parsed value (which may be `null` if the handler produces `null`).
88-
* @throws IOException If the handler failed with an [IOException] — cached and re-thrown.
87+
* @return The parsed value (which may be `null` if the handler is typed `ResponseHandler<T?>`
88+
* and produces `null`).
89+
* @throws IOException If the handler failed with an [IOException] — cached and re-thrown. The
90+
* `@Throws` declaration covers only the checked surface for Java callers; the handler may also
91+
* propagate **unchecked** exceptions (e.g. `SerdeException` from the Jackson `jsonHandler`),
92+
* which are memoized and re-thrown the same way.
8993
*/
9094
@Throws(IOException::class)
9195
public fun value(): T {

sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/response/ResponseHandler.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ import java.nio.charset.StandardCharsets
3838
* Handlers are typically stateless and shared across requests; the built-in factories return
3939
* stateless instances. A stateful handler must guard its own state.
4040
*
41+
* ## Nullability
42+
*
43+
* A handler that may legitimately produce `null` (e.g. an absent-but-valid payload) should be typed
44+
* `ResponseHandler<T?>` so the nullability is visible to Kotlin and Java callers alike; otherwise a
45+
* `null` slips through a non-null `T` as a platform value. [ParsedResponse.value] memoizes a `null`
46+
* result correctly either way.
47+
*
4148
* @param T The typed result this handler produces.
4249
*/
4350
public fun interface ResponseHandler<out T> {
@@ -87,10 +94,13 @@ public fun interface ResponseHandler<out T> {
8794
val body = it.body ?: return@use
8895
val source = body.source()
8996
// Pump into a throwaway scratch buffer (cleared each round) so the connection
90-
// is released without materializing the whole body in memory.
91-
val scratch = Io.provider.buffer()
92-
while (source.read(scratch, DRAIN_CHUNK_BYTES) != -1L) {
93-
scratch.clear()
97+
// is released without materializing the whole body in memory. The buffer is
98+
// closed deterministically so its segments are recycled even if the drain
99+
// throws mid-stream, rather than leaning on the GC.
100+
Io.provider.buffer().use { scratch ->
101+
while (source.read(scratch, DRAIN_CHUNK_BYTES) != -1L) {
102+
scratch.clear()
103+
}
94104
}
95105
}
96106
}

0 commit comments

Comments
 (0)