Skip to content

feat(client): default request_timeout applied at the REST seam#41

Merged
eddietejeda merged 1 commit into
mainfrom
feat/default-request-timeout
Jul 8, 2026
Merged

feat(client): default request_timeout applied at the REST seam#41
eddietejeda merged 1 commit into
mainfrom
feat/default-request-timeout

Conversation

@eddietejeda

Copy link
Copy Markdown
Contributor

The generated SDK sends _request_timeout=None (urllib3 no-timeout) on
every call unless a caller passes one per call — and the helper methods
(load_managed_table, list_managed_tables, ...) expose no such knob — so
a stalled or black-holed server blocks the calling thread indefinitely,
and the configured urllib3 read retries never fire because no read
timeout ever triggers them.

HotdataClient (and ManagedDatabaseClient, passing through) now accept
request_timeout: seconds or a (connect, read) pair, installed once at
construction by wrapping rest_client.request to default the per-call
_request_timeout. Explicit per-call values still win; the default stays
None so existing behavior is unchanged unless opted in. A construction-
time deadline means stalled calls fail at the socket and the connection
tears down — no caller-side thread tricks, and new call sites are
bounded by construction.

The generated SDK sends _request_timeout=None (urllib3 no-timeout) on
every call unless a caller passes one per call — and the helper methods
(load_managed_table, list_managed_tables, ...) expose no such knob — so
a stalled or black-holed server blocks the calling thread indefinitely,
and the configured urllib3 read retries never fire because no read
timeout ever triggers them.

HotdataClient (and ManagedDatabaseClient, passing through) now accept
request_timeout: seconds or a (connect, read) pair, installed once at
construction by wrapping rest_client.request to default the per-call
_request_timeout. Explicit per-call values still win; the default stays
None so existing behavior is unchanged unless opted in. A construction-
time deadline means stalled calls fail at the socket and the connection
tears down — no caller-side thread tricks, and new call sites are
bounded by construction.
Comment on lines +92 to +99
def request_with_default_timeout(
method,
url,
headers=None,
body=None,
post_params=None,
_request_timeout=None,
):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: (not blocking) This nested function is fully unannotated (params + return), which trips this repo's strict mypy config (disallow_untyped_defs = true). Relatedly, rest_client.request = request_with_default_timeout on line 111 will trigger mypy's [method-assign] ("cannot assign to a method"). CI only runs pytest so the build isn't broken, but the rest of the codebase is strict-mypy clean, so this is a regression against that bar. Consider annotating the signature and adding # type: ignore[method-assign] on the assignment.

Separately, hard-coding the full method, url, headers, body, post_params, _request_timeout signature couples this wrapper to the exact generated RESTClientObject.request shape — a future SDK regeneration that adds a parameter would silently break (dropped kwarg or TypeError). Forwarding via *args, **kwargs (defaulting _request_timeout when absent/None) would survive regeneration.

Comment on lines 73 to +75



Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: (not blocking) Three blank lines here — ruff (E303, which this repo selects) wants at most two between top-level definitions. Drop one.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The wrapper correctly targets the REST seam, is invoked as a plain instance attribute (so the no-self signature is right), preserves explicit per-call _request_timeout, and the tests cover the real paths. Left two non-blocking nits (strict-mypy typing gap + wrapper signature coupling; an E303 blank-line).

@eddietejeda eddietejeda merged commit 197f282 into main Jul 8, 2026
4 checks passed
@eddietejeda eddietejeda deleted the feat/default-request-timeout branch July 8, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant