Skip to content

docs: document response caching, cookie storage, and connection-pool sizing as deliberate non-goals #224

Description

@OmarAlJarrah

Summary

Three HTTP-client capabilities are intentionally absent from the toolkit, but nothing in docs/product-spec.md records that they are deliberate. A reader surveying the surface can reasonably read each absence as an oversight rather than a decision:

  1. RFC 9111 response cache. There is no response cache anywhere in core. sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.kt and sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.kt are pure RFC 7232 header helpers — ETag models the ETag/If-Match/If-None-Match value forms, and RequestConditions.applyTo writes the conditional headers onto a Headers.Builder. Neither carries any storage, freshness, or revalidation logic.
  2. Cookie jar / session cookies. There is no CookieJar, CookieStore, or CookieHandler type in the SDK. The OkHttp builder's build() (sdk-transport-okhttp/.../OkHttpTransport.kt:496) never installs a cookieJar, so the SDK-managed client keeps OkHttp's CookieJar.NO_COOKIES default; the JDK transport builder never installs a CookieHandler and names it a BYO-only knob (sdk-transport-jdkhttp/.../JdkHttpTransport.kt:371).
  3. Connection-pool / keep-alive sizing. Both transport builders expose timeouts, proxy, and redirect handling, but neither exposes pool sizing. The OkHttp builder KDoc already directs pool sizing to a BYO client (sdk-transport-okhttp/.../OkHttpTransport.kt:391-395, "connection pool sizing"), and java.net.http.HttpClient.Builder has no pool-sizing knob at all.

This is a documentation-only task. The proposal is to state all three as explicit non-goals with their bring-your-own escape hatches; it does not propose building any of them.

Rationale

The SDK is a platform — a core HTTP-client toolkit consumed by generated service clients, downstream SDKs, and application code — so the boundary of what the toolkit does and does not own is itself part of the contract. When that boundary is left implicit, an external consumer cannot distinguish "we decided not to own this, here is where it lives instead" from "this was forgotten." Writing these down as non-goals turns each gap into a documented seam the consumer can plan around.

Each of the three belongs above core, or in a BYO client, for a platform-specific reason:

  • Response cache. A conformant RFC 9111 cache needs transport-specific persistent storage and revalidation state. Pulling that into core would break the near-zero-dependency guarantee that SEAM-1 / NFR-1 encode: core MUST NOT carry a runtime dependency on any concrete transport, serialization library, I/O implementation, or async framework, and a persistent cache store is exactly such a dependency. If a cache is wanted, it belongs in the transport: a BYO OkHttpClient configured with an okhttp3.Cache works today, because OkHttpTransport.close() is ownership-aware and closes the response cache only for SDK-created clients (OkHttpTransport.kt:352, client.cache?.close(), reached only after the !owned early return) while leaving a caller-supplied client untouched (TRANSPORT-15, XCUT-22).
  • Cookie jar. Stateful session management is application/session policy, not wire plumbing — it belongs one layer up (the generated client or the application), where the session lifecycle actually lives. The redirect step passes the origin-scoped Cookie header through on a same-origin hop (REDIR-10) and strips it only on a cross-origin redirect (sdk-core/.../http/pipeline/steps/DefaultRedirectStep.kt:283, REDIR-9 / XCUT-17) for credential hygiene — that is hygiene, not cookie storage.
  • Pool sizing. This is genuinely native-client-specific. OkHttp exposes a ConnectionPool; java.net.http.HttpClient.Builder exposes nothing equivalent. A cross-transport pool-sizing surface in core would be a leaky lowest-common-denominator abstraction that could not be honored uniformly, so it stays BYO on the native client.

Documenting these keeps the platform honest about its edges without weakening SEAM-1 / NFR-1.

Proposed change

  1. Add a capability non-goals subsection to docs/product-spec.md. §1 already carries a Non-goals of this specification paragraph (line 13) that scopes what the document prescribes (language, framework, codegen, and so on); this new subsection is distinct — it records capabilities the toolkit deliberately does not build — so place it adjacent to that paragraph under §1 Product Overview (line 15), or under §17 Transport Adapter Conformance Contract (line 795), whichever the maintainer prefers for discoverability. Anchor the response-cache entry to §4.6 Conditional-request helpers (line 154), where ETag/RequestConditions are already specified. For each capability, state (a) that it is a deliberate non-goal, (b) the platform reason it is out of core, and (c) the BYO escape hatch:
    • Response caching (RFC 9111): not provided; ETag/RequestConditions are RFC 7232 header helpers only. Escape hatch: a BYO OkHttpClient with an okhttp3.Cache, whose lifecycle stays with the caller (TRANSPORT-15, XCUT-22).
    • Cookie jar / session cookies: no CookieJar/CookieStore/CookieHandler; OkHttp keeps NO_COOKIES, the JDK transport installs no CookieHandler. Stateful cookies belong to the generated client / application; the redirect step's cross-origin Cookie stripping is hygiene, not storage.
    • Connection-pool / keep-alive sizing: not exposed by either transport builder; keep it BYO on the native client because it is native-specific (OkHttp ConnectionPool; the JDK builder has no pool config).
  2. Add a one-line BYO note about cookies to the OkHttp transport, alongside the existing BYO guidance in the Builder KDoc (OkHttpTransport.kt:391-395), so the cookie non-goal is discoverable from the code, matching how connection-pool sizing is already handled there.

Acceptance criteria

  • docs/product-spec.md gains a capability non-goals subsection that names all three capabilities as deliberate non-goals, each with its rationale and BYO escape hatch as above, and that is clearly distinct from the existing document-scope Non-goals of this specification paragraph.
  • The response-cache entry references the RFC 7232 nature of ETag/RequestConditions and the okhttp3.Cache + ownership-aware-close escape hatch, and cites SEAM-1/NFR-1 for why a cache stays out of core.
  • The cookie entry notes the OkHttp NO_COOKIES default and the absent JDK CookieHandler, points session management one layer up, and references the redirect step's cross-origin Cookie stripping (REDIR-9/XCUT-17) as hygiene rather than storage.
  • The pool-sizing entry explains the leaky lowest-common-denominator problem (OkHttp has a pool, the JDK builder does not) and keeps it BYO.
  • The OkHttp Builder KDoc mentions cookies among the BYO-only concerns.
  • No production/runtime code implements caching, a cookie jar, or a pool-sizing surface as part of this change.

References

  • sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.kt — RFC 7232 ETag/If-Match/If-None-Match helper; no storage/revalidation.
  • sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.kt — RFC 7232 conditional-request headers (applyTo writes them onto a Headers.Builder); no cache logic.
  • sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:496build() never installs a cookieJar (keeps OkHttp NO_COOKIES).
  • sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:391-395Builder KDoc directs connection-pool sizing (and other unmapped knobs) to a BYO OkHttpClient.
  • sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:352 — ownership-aware close() calls client.cache?.close() only for SDK-owned clients (guarded by the !owned early return).
  • sdk-transport-jdkhttp/src/main/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransport.kt:371Builder KDoc names the cookie handler a BYO-only concern; no CookieHandler is installed.
  • sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/DefaultRedirectStep.kt:283 — strips the Cookie header on a cross-origin redirect.
  • docs/product-spec.mdSEAM-1 (MUST, near-zero-dep core), NFR-1 (MUST, no concrete runtime deps in core), NFR-2 (SHOULD, adapter = core + at most one third-party lib), TRANSPORT-15 / XCUT-22 (MUST, ownership-aware close; BYO resources never closed), REDIR-9 / XCUT-17 (MUST, cross-origin Cookie/Proxy-Authorization stripping), REDIR-10 (SHOULD, same-origin Cookie retained). §1 Product Overview (line 15), §4.6 Conditional-request helpers (line 154), §17 Transport Adapter Conformance Contract (line 795).
  • Relates to Reconsider transport-config surface: delegate pass-through settings to the underlying client #159 (reconsider the transport-config surface: delegate pass-through settings to the underlying client).

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationsdk-coresdk-core toolkit

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions