Skip to content

SDK polish: rate-limit headers, error context, Arc<Inner>, lint attrs, CI hygiene #116

Description

@martinkersner

A collection of small, independent polish items surfaced while evaluating the SDK against widely-used Rust crates. None is individually large; together they're most of what separates this crate's public surface from an octocrab/aws-sdk-rust-tier one. Each is independently closeable.

API / runtime

  • Surface rate-limit headers. The client parses Retry-After on 429 but ignores any x-ratelimit-remaining / x-ratelimit-reset-style headers, if the API sends them. Callers currently have no way to pace themselves short of getting 429'd. (First step: confirm what headers the API actually returns.)

  • Error::UnexpectedStatusCode(u16) drops the response body. Every other error arm that has a body carries it (BadRequest(String), InternalServerError(String)). An unexpected status is the case where you most want the body, and it's the one that throws it away.

  • No error carries the endpoint that failed. Err(Error::NotFound) tells you nothing about which of the 49 endpoints 404'd. Adding request context (endpoint, status) to the error would make failures diagnosable without turning on tracing.

  • Client clones two Strings per accessor call. Client is { base_url: String, api_key: String, inner_client: reqwest::Client, retry: RetryConfig } and every client.cex_candle() does a full self.clone(). reqwest::Client is a cheap Arc clone, but the two Strings are heap allocations. Wrapping the fields in Arc<ClientInner> makes Client::clone a single refcount bump — the standard shape for this pattern.

  • parse_retry_after doesn't handle the HTTP-date form. Only integer delay-seconds (RFC 9110 §10.2.3) is parsed; the date form yields None and falls back to jittered backoff. Documented, low impact, but a gap.

Lints / CI hygiene

  • Add #![forbid(unsafe_code)] to src/lib.rs. The crate has no unsafe; make that a guarantee rather than a coincidence.

  • Add #![warn(missing_docs)]. The hand-written api.rs is documented to an unusually high standard, but the generated Options builder methods (CexCandleOptions::market, ::interval, ::from, ::to, …) carry no doc comments at all. Enabling the lint would force codegen to emit them — the descriptions already exist in the spec, since they're on the corresponding struct fields.

  • Add cargo-deny (or cargo-audit) to CI. No advisory-database check runs today on a crate whose whole job is to make network calls.

  • Add cargo-semver-checks to CI. The crate has shipped 0.3.3 → 0.12.0 with no mechanical check that the version bumps matched the API changes.

Naming

  • Two different blocking modules. pub use generated::* re-exports generated::blocking as datamaxi::blocking, which sits next to the unrelated datamaxi::api::blocking. One holds endpoint wrappers, the other holds Client/ClientBuilder/Paginator, and the docs have to keep explaining that you need both. Also worth weighing: the glob re-export puts ~200 generated type names directly in the crate root.

Metadata

Metadata

Assignees

Labels

claude-foundSurfaced by Claude during reviewenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions