Repository navigation
docs: make the docs.rs reference usable - #149
Merged
Merged
Conversation
JosteinGj
force-pushed
the
refactor/remove-inert-config-and-auth-diagnostics
branch
from
September 24, 2026 09:19
aadb203 to
d3cd185
Compare
JosteinGj
force-pushed
the
docs/usable-api-reference
branch
from
September 24, 2026 09:19
5124b79 to
55d2041
Compare
…DME reads The docs.rs index opened with about forty lines of raw `pub use` and no prose at all — nothing saying what the crate is or how to make one call. - a crate-level `//!`: what it is, a runnable `create_api_service()` example, a table mapping each `ApiService` field to its module, then the four things a caller hits immediately — `DataWrapper`/`GraphDataWrapper`, id-or-externalId, `ResponseError` and its problem document, and the list/filter/search split. - `[package.metadata.docs.rs] all-features = true`, so the `blocking` client is documented at all. docs.rs builds default-features-only, so a feature the README points callers at was absent from the reference. `doc_cfg` badges it, guarded by `cfg_attr(docsrs, ...)` so stable builds are unaffected. - clears all five rustdoc warnings. Two were links into private items, which render as dead text rather than links: `DEFAULT_SCOPE` pointing at `OAuthConfig::effective_scope`, and `set_advanced_filter` at a private field. Both now say the thing instead of linking to it. Verified clean on stable and on nightly with `--cfg docsrs`, which is what docs.rs runs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
The entry point and the type every caller starts from both had no docs, so the two most-visited pages in the reference were a bare signature and a list of bare field names. `ApiService` now says what it is, that the services share one HTTP client and token cache so the Arc should be cloned rather than the client rebuilt, and that one client is one tenant. Each service field links to its module. `create_api_service` documents what it reads from the environment, carries a runnable example, and has a Panics section — it calls `from_env().unwrap()`, so a missing BASE_URL panics at construction rather than on the first call, and `DataHubConfig::from_env` + `ApiService::new` is the Result-based route. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Nineteen of the twenty-three modules rendered on the docs.rs index as a bare name with no description, including every service a caller starts from. Each now says what it is, what it covers, and the one or two things that will otherwise surprise you — events.list() returning the oldest events, Function::related_resources always being empty, FileUpload::new panicking on an unreadable path, a listener closing as idle if it is not polled. Hides four items that are public only because the services need them, as one group so no survivor is left referencing a hidden name: ApiServiceProvider, DataWrapperDeserialization, process_response and the serde_helper module. doc(hidden) rather than pub(crate) — serde_helper's id-as-string adapters are legitimately reusable by a downstream type's own #[serde(with = ...)], and hiding does not restrict. GraphNode and Identifiable stay visible deliberately: both appear as bounds in public signatures, where hiding renders them as unclickable bare names. Four doc comments contradicted the api and are corrected here: - labels::get said a miss returns empty items; it is a 404. - EdgeProxy claimed it is returned from GET /functions, which answers RelatedNode and never populates it. - TimeSeries::value_type said graph reads do not carry it; they do now. - the subscriptions module is not "CRUD" — there is no update or get. labels::delete's documented 400 was checked against the backend and left alone: it really is a 400 with `fields`, not the 409 `would-strand` that resources and edges answer with. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Thirty-four public types rendered with no description at all, including the ones a caller meets first: DataWrapper, ResponseError, Event, TimeSeries, Resource, Dataset, Unit, Subscription and every service struct. Service structs get a one-liner pointing at their module doc rather than repeating it. Entity types say what the thing is and carry the one fact that is not guessable from the field list — an Event is keyed by UUID and its externalId is deliberately not unique; a Dataset's connected_data_sets is input-only; a TimeSeries value_type cannot change after creation; DatapointString is stringly-typed so a decimal never passes through an f64; FileUpload::new panics on an unreadable path. DataWrapper gets the longest entry, since it is the return type of nearly every call and the "it is also a request body" trick is what makes `create(&event)` work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Twenty-eight API calls still had no doc comment, so the reference showed a bare signature for things like datasets.create, events.filter, files.upload_file, timeseries.retrieve_datapoints and the whole units service. Each now names the endpoint it calls and carries what the signature cannot say: that events.create stamps a UUID v7 so a retry dedups and can answer 202 when buffering spooled the batch; that resources.delete is refused with 409 would-strand; that files.delete is a soft delete; that retrieve_datapoints takes a half-open window; that a supplied TOKEN is never refreshed; that deleting a subscription with a live listener attached is refused. Leaves the builder setters and field getters alone. A one-line doc on `set_name` saying it sets the name is noise, and there are several hundred of them; the types they hang off are documented instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Nothing was checking the documentation, so the two things that make a reference actively wrong both happened silently. A broken intra-doc link is not a build failure — rustdoc renders it as dead text and carries on, so it only shows up on docs.rs, after release. There were five in the tree before this branch. `-D warnings` on the rustdoc build turns them into failures. And the examples were never compiled: CI runs `cargo test --no-run`, which does not build doctests at all. So the `create_api_service()` example on the landing page would have rotted the moment a method was renamed, with nothing to say so. Only `--doc` is run here. Every other test in this crate needs a live backend, which CI has no way to reach; the doctests are the documentation's own examples and are pure construction, verified to pass with BASE_URL pointed at a dead address and no credentials in the environment. The doc build uses nightly with `--cfg docsrs` to match what docs.rs actually runs, since `doc_cfg` — which badges the `blocking` feature — is nightly-only. Verified by injecting a broken link: the step exits 101. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
JosteinGj
force-pushed
the
docs/usable-api-reference
branch
from
September 24, 2026 09:27
55d2041 to
7522e16
Compare
JosteinGj
force-pushed
the
refactor/remove-inert-config-and-auth-diagnostics
branch
from
September 24, 2026 09:27
d3cd185 to
b0df19e
Compare
Closed
…oc that it needs the feature The doc_cfg badge on `blocking` was the only reason for nightly, in CI and in the docs.rs rustdoc-args. The module doc now names the feature and shows the Cargo.toml line instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: jgjesdal <jostein@intellistream.ai>
Base automatically changed from
refactor/remove-inert-config-and-auth-diagnostics
to
chore/remove-dead-code
September 30, 2026 10:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The rendered API reference opened with about forty lines of raw
pub useand no prose at all — nothing saying what the crate is or how to make one call. 19 of 23 modules rendered as a bare name with no description. 34 public types had none either, includingDataWrapper,ResponseError,Event,TimeSeriesand every service struct.Judge this by building it rather than by the diff:
What changed
A landing page. What the crate is, a runnable
create_api_service()example, a table mapping eachApiServicefield to its module, then the four things a caller hits immediately: theDataWrapperenvelope, id-or-externalId,ResponseErrorand its problem document, and the list/filter/search split.blockingwas absent from docs.rs entirely. With no[package.metadata.docs.rs], docs.rs builds default-features-only — so the README pointed callers at a client the reference never showed. Nowall-features = true, and theblockingmodule doc states up front that it needs the feature, with theCargo.tomlline. (Adoc_cfgbadge would do the same but needs nightly, so it was left out.)Every module and every public type described. Service structs get a one-liner pointing at their module doc; entity types carry the fact that is not guessable from the field list — an
Eventis keyed by UUID and itsexternalIdis deliberately not unique, aTimeSeriesvalue_typeis fixed at creation,FileUpload::newpanics on an unreadable path.Plumbing hidden, as one group so no survivor is left referencing a hidden name:
ApiServiceProvider,DataWrapperDeserialization,process_response,serde_helper.doc(hidden)rather thanpub(crate)— the id-as-string serde adapters are legitimately reusable by a downstream type's own#[serde(with = …)], and hiding does not restrict.GraphNodeandIdentifiablestay visible on purpose: both appear as bounds in public signatures, where hiding renders them as unclickable bare names.The 28 remaining service methods documented —
datasets.create,events.filter,files.upload_file,timeseries.retrieve_datapoints, the whole units service. Builder setters and field getters are deliberately left alone: a line onset_namesaying it sets the name is noise, and there are several hundred.Four doc comments were contradicting the api
Found while drafting, each checked against the backend source:
labels::getsaid a miss returns empty items. It is a 404.EdgeProxyclaimed it is returned fromGET /functions, which answersRelatedNodeand never populates it.TimeSeries::value_typesaid graph reads do not carry it. They do now.labels::delete's documented 400 was checked and left alone: it really is a 400 withfields, not the 409would-strandthat resources and edges answer with. Generalising there would have introduced an error.CI now runs the doctests
cargo test --no-rundoes not build doctests at all, so the landing-page example was never compile-checked.The existing
cratejob now also runscargo test --doc, and only that — every other test in this crate needs a live backend, which CI cannot reach. The doctests are the documentation's own examples and are pure construction; confirmed passing withBASE_URLpointed at a dead address and no credentials in the environment.Numbers
Rustdoc coverage 33.8% → 41.8% (+87 items), zero rustdoc warnings, 248 tests and 7 doctests green.
The 644 still-undocumented items are overwhelmingly builder setters and struct fields. A coverage ratchet was considered and deliberately left out.
Stack, 5 of 5 — based on #148.
Two things this does not do, both deliberate:
pub use resources::*,events::*,timeseries::*) stay. They do duplicate items between the crate root and their modules, but removing them breaksuse intellistream_datahub_sdk::TimeSeriesfor every existing caller — that belongs in a release, not a docs pass.v0.2.0is still the only one, so the published reference predates the filter refactor, the assets service and theNodetype.Unrelated bug found, not fixed here:
GraphDataWrapper::set_http_status_codeispub fn set_http_status_code(&mut self, _status_code: u16) {}— argument discarded, empty body. It is called on both parse paths, so a normal 200 fromresources.create,updateoredges.by_idscomes back withhttp_status_code: None.DataWrapper's version stores correctly, so the two wrappers disagree. That is a behaviour fix and wants its own PR.🤖 Generated with Claude Code