Skip to content

Commit 493f232

Browse files
committed
refactor: remove the two-lambda CursorPaginationStrategy constructor
The single-pass (Response) -> CursorResult extractor is now the only way to construct the strategy. The two-lambda form drained the single-use response body twice per page and only existed for back-compat; drop it outright rather than deprecate.
1 parent 10d4dda commit 493f232

3 files changed

Lines changed: 0 additions & 92 deletions

File tree

sdk-core/api/sdk-core.api

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,9 +1963,6 @@ public final class org/dexpace/sdk/core/pagination/CursorPaginationStrategy : or
19631963
public fun <init> (Lkotlin/jvm/functions/Function1;)V
19641964
public fun <init> (Lkotlin/jvm/functions/Function1;Ljava/lang/String;)V
19651965
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1966-
public fun <init> (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
1967-
public fun <init> (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;)V
1968-
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
19691966
public fun parse (Lorg/dexpace/sdk/core/http/response/Response;Lorg/dexpace/sdk/core/http/request/Request;)Lorg/dexpace/sdk/core/pagination/Page;
19701967
}
19711968

sdk-core/src/main/kotlin/org/dexpace/sdk/core/pagination/CursorPaginationStrategy.kt

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -47,37 +47,6 @@ public class CursorPaginationStrategy<T>
4747
private val extractor: (Response) -> CursorResult<T>,
4848
private val cursorQueryParam: String = "cursor",
4949
) : PaginationStrategy<T> {
50-
/**
51-
* Creates a strategy from two body-reading lambdas.
52-
*
53-
* @deprecated Each lambda drains the single-use response body separately, so the body
54-
* is read twice per page. Use the single-pass [extractor] constructor that returns a
55-
* [CursorResult] instead.
56-
*/
57-
@Deprecated(
58-
message =
59-
"Two body-reading lambdas drain the single-use response body twice per page. " +
60-
"Pass a single extractor returning a CursorResult instead. The suggested " +
61-
"replacement only changes the API shape: collapse the two lambdas into one " +
62-
"that reads the body a single time, otherwise it still double-drains.",
63-
replaceWith =
64-
ReplaceWith(
65-
"CursorPaginationStrategy({ response -> " +
66-
"CursorResult(itemsExtractor(response), cursorExtractor(response)) }, " +
67-
"cursorQueryParam)",
68-
"org.dexpace.sdk.core.pagination.CursorResult",
69-
),
70-
)
71-
@JvmOverloads
72-
public constructor(
73-
itemsExtractor: (Response) -> List<T>,
74-
cursorExtractor: (Response) -> String?,
75-
cursorQueryParam: String = "cursor",
76-
) : this(
77-
extractor = { response -> CursorResult(itemsExtractor(response), cursorExtractor(response)) },
78-
cursorQueryParam = cursorQueryParam,
79-
)
80-
8150
override fun parse(
8251
response: Response,
8352
initialRequest: Request,

sdk-core/src/test/kotlin/org/dexpace/sdk/core/pagination/CursorSingleReadTest.kt

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import java.util.concurrent.atomic.AtomicInteger
1414
import kotlin.test.BeforeTest
1515
import kotlin.test.Test
1616
import kotlin.test.assertEquals
17-
import kotlin.test.assertFailsWith
1817
import kotlin.test.assertNull
1918

2019
/**
@@ -107,63 +106,6 @@ class CursorSingleReadTest {
107106
assertNull(end.nextCursor)
108107
}
109108

110-
@Test
111-
@Suppress("DEPRECATION")
112-
fun `deprecated two-lambda constructor still paginates for back-compat`() {
113-
// The legacy two-lambda constructor is retained but deprecated; it delegates to the
114-
// single-pass path. This proves existing callers keep working. The two lambdas read
115-
// disjoint parts of the response (items from the body, cursor from a header) so the
116-
// single-use body is not the thing being drained twice — that double-drain trap is
117-
// exactly what the deprecation steers callers away from.
118-
val client = StubHttpClient()
119-
client.on("https://api.example.com/items") { req ->
120-
textResponse(req, "a,b", extraHeaders = mapOf("X-Next-Cursor" to "more"))
121-
}
122-
client.on("https://api.example.com/items?cursor=more") { req ->
123-
textResponse(req, "c")
124-
}
125-
126-
val itemsExtractor: (Response) -> List<String> = { resp ->
127-
val body = resp.body!!.source().use { it.readUtf8() }
128-
if (body.isEmpty()) emptyList() else body.split(",")
129-
}
130-
val cursorExtractor: (Response) -> String? = { resp ->
131-
resp.headers.get("X-Next-Cursor")
132-
}
133-
134-
val strategy = CursorPaginationStrategy(itemsExtractor, cursorExtractor)
135-
val paginator = Paginator(client, initialRequest(), strategy)
136-
137-
assertEquals(listOf("a", "b", "c"), paginator.iterateAll().toList())
138-
assertEquals(2, client.callCount)
139-
}
140-
141-
@Test
142-
@Suppress("DEPRECATION")
143-
fun `deprecated two-lambda constructor double-drains when both lambdas read the body`() {
144-
// Documents the hazard the single-pass API exists to remove: when both legacy lambdas
145-
// read the body, the single-use response is drained twice and the second read fails.
146-
val client = StubHttpClient()
147-
client.on("https://api.example.com/items") { req ->
148-
singleUseResponse(req, "items=a,b\ncursor=")
149-
}
150-
151-
val itemsExtractor: (Response) -> List<String> = { resp ->
152-
val body = resp.body!!.source().use { it.readUtf8() }
153-
body.substringAfter("items=").substringBefore('\n').split(",")
154-
}
155-
val cursorExtractor: (Response) -> String? = { resp ->
156-
// Second read of the same single-use body — this is the double-drain.
157-
resp.body!!.source().use { it.readUtf8() }
158-
null
159-
}
160-
161-
val strategy = CursorPaginationStrategy(itemsExtractor, cursorExtractor)
162-
val paginator = Paginator(client, initialRequest(), strategy)
163-
164-
assertFailsWith<IllegalStateException> { paginator.iterateAll().toList() }
165-
}
166-
167109
@Test
168110
fun `single read extractor honours a custom cursor query param`() {
169111
val client = StubHttpClient()

0 commit comments

Comments
 (0)