Skip to content

Accept sub-second timeout values as Numeric seconds #116

Description

@ZilvinasKucinskas

Priority: P1

Describe the issue

wreq-ruby currently converts timeout values to unsigned integer seconds. This prevents callers from setting deadlines below one second and forces them to round values before passing them to the client.

Ruby HTTP libraries normally express timeout durations in seconds while accepting integers and floats. wreq-ruby should follow that convention and retain the caller's precision when converting to Rust's Duration.

Reproduction

Tested with wreq 1.2.4:

require "wreq"

Wreq::Client.new(timeout: 0.25)
# TypeError: invalid type: expected u64, got floating point `0.25`

The same integer-only conversion is used by request-level timeout and read_timeout options. Other duration-valued client controls such as pool_idle_timeout, tcp_keepalive, and tcp_keepalive_interval use the same whole-second conversion.

Proposed Ruby API

Accept non-negative, finite Numeric values in seconds, at minimum Integer and Float:

client = Wreq::Client.new(
  timeout: 0.75,
  connect_timeout: 0.20,
  read_timeout: 0.50
)

client.get("https://example.com", timeout: 0.35)

Integers must remain backward compatible. Internally, fractional values can be converted to a Rust Duration without truncating to whole seconds.

Explicit *_ms options are not necessary for the primary API. Numeric seconds are already the established Ruby convention and allow both concise whole-second values and precise sub-second values.

Validation semantics

  • Reject negative values.
  • Reject Float::NAN and positive or negative infinity.
  • Reject non-numeric strings instead of coercing them silently.
  • Define whether 0 means “expire immediately” or “disable this timeout”; it should not be ambiguous.
  • Apply the same duration conversion rules to client-level and request-level timeout options.
  • Reuse the conversion contract for every public option documented in seconds; do not leave pool/TCP durations with a separate integer-only rule.

Acceptance criteria

  • timeout, connect_timeout, and read_timeout accept integer and fractional seconds where each option is supported.
  • pool_idle_timeout, tcp_keepalive, and tcp_keepalive_interval use the same finite Numeric-seconds conversion.
  • A value such as 0.25 is preserved with reasonable Duration precision rather than rounded to 0 or 1.
  • Invalid numeric values fail before network I/O and identify the relevant option.
  • Existing integer timeout behavior remains compatible.
  • Documentation states the unit and semantics of every timeout.
  • Tests cover integers, ordinary fractional floats, zero, negative values, NaN, infinity, and request-level overrides.

Ruby ecosystem precedent

  • Net::HTTP documents Numeric timeout values and accepts floats for open, read, and write timeouts.
  • HTTPX timeout options accept fractional seconds and distinguish connection, read, write, request, and operation deadlines.
  • http.rb supports fine-grained per-operation timeouts with fractional values.
  • Excon documents integer or float timeout seconds.
  • wreq-python accepts datetime.timedelta for total, connect, read, pool, and TCP timeout options while binding the same Rust Duration-based API.

Relevant wreq-ruby source

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    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