Upgrade to HTTP.jl 2.4 (v0.3.1)#45
Conversation
HTTP.jl 2.x is a ground-up rewrite. All real-HTTP usage is isolated in
src/http.jl (plus one direct dispatcher call in batch.jl):
- readtimeout -> read_idle_timeout (2.x rename; same idle-timeout semantics)
- retry=false -> retries=0 (2.x has no `retry` boolean)
- HTTP.Exceptions.{HTTPError,TimeoutError,ConnectError} -> top-level HTTP.*
(the Exceptions submodule is gone)
- streaming uses startread's returned Response instead of http.message
- JSON3.read(resp.body) -> JSON3.read(Vector{UInt8}(resp.body)); in 2.x
resp.body is an HTTP.BytesBody wrapper JSON3 doesn't recognize
- _is_retryable_exception keeps connect timeouts retryable: 2.x surfaces them
as TimeoutError(operation="connect") rather than ConnectError
Tests: HTTP.Exceptions.X -> HTTP.X and TimeoutError(n) -> TimeoutError("read", n)
(the 1-arg ctor is gone). HTTP.Response mock ctors are backward compatible.
Compat bumped to "2.4" in Project.toml and benchmark/Project.toml. Bumps the
package to v0.3.1. Supersedes #42.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: beef0a2916
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| (e isa HTTP.HTTPError && !(e isa HTTP.TimeoutError)) || | ||
| (e isa HTTP.TimeoutError && e.operation == "connect") |
There was a problem hiding this comment.
Treat TLS handshake timeouts as connection failures
HTTP.jl 2.x also reports connection-phase TLS deadline failures as HTTP.TimeoutError with operation == "tls_handshake" (the connect_timeout budget covers the handshake), but this predicate only keeps "connect" retryable. In that HTTPS handshake-timeout scenario the request skips the existing retry loop and then the later operation != "connect" branch maps it to BentoTimeoutError, incorrectly telling users to raise the read timeout instead of treating it like the transient connection failure it is.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch — fixed in 32ef766. Generalized the connect-timeout special-case into a _CONNECT_PHASE_TIMEOUT_OPS = ("connect", "tls_handshake") set (the connect_timeout budget covers both DNS/dial and the TLS handshake), used by both the retry predicate and the two BentoTimeoutError mapping sites. Added a regression test covering both operations.
HTTP 2.x's connect_timeout budget covers DNS/dial *and* the TLS handshake. A
handshake deadline surfaces as TimeoutError(operation="tls_handshake"), not
"connect", so the previous predicate skipped the retry loop and then mislabeled
it as a read timeout (BentoTimeoutError → "raise the read timeout"), when it's
really a transient connection failure.
Generalize the connect-timeout special-case to a _CONNECT_PHASE_TIMEOUT_OPS set
{"connect", "tls_handshake"} via _is_connect_timeout, used by both the retry
predicate and the two BentoTimeoutError mapping sites. Adds a regression test.
Addresses Codex review feedback on #45.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrates the package from HTTP.jl 1.10 to 2.4. HTTP.jl 2.x is a ground-up rewrite (renamed timeout/retry keywords, top-level exception types, a body abstraction in place of raw
Vector{UInt8}).Supersedes #42 (Dependabot), which only widened the compat bound to allow 2.4 but did not perform the code migration — the package does not actually work on 2.x without these changes.
Changes
All real-HTTP usage is isolated in
src/http.jl(plus one direct dispatcher call insrc/historical/batch.jl):readtimeout→read_idle_timeout(the 2.x name; same idle-timeout semantics)retry = false→retries = 0(2.x has noretryboolean)HTTP.Exceptions.{HTTPError,TimeoutError,ConnectError}→ top-levelHTTP.*(theExceptionssubmodule is gone)resp = HTTP.startread(http)(2.x returns the response) instead of reaching intohttp.messageJSON3.read(resp.body)→JSON3.read(Vector{UInt8}(resp.body))— in 2.xresp.bodyis anHTTP.BytesBodywrapper that JSON3 doesn't recognize_is_retryable_exceptionrefined so connect timeouts stay retryable: 2.x surfaces them asTimeoutError(operation="connect")rather thanConnectError, so the naiveHTTPError && !TimeoutErrorpredicate would have silently regressed thatTests — only exception references changed (
HTTP.Exceptions.X→HTTP.X, andTimeoutError(100)→TimeoutError("read", 100)since the 1-arg ctor is gone). TheHTTP.Response(...)mock constructors are backward-compatible in 2.x and were left as-is.Compat bumped to
"2.4"inProject.tomlandbenchmark/Project.toml. Public API is unchanged, so this is released as a patch: v0.3.1.Verification
readtimeoutdeprecation warningread_idle_timeout/retries=0/startreadagainst a real socket) is only covered by the gatedtest/live/tests — runDATABENTO_LIVE_TESTS=1with a key for end-to-end confirmation before release🤖 Generated with Claude Code