Skip to content

refactor: public API hygiene — non_exhaustive, re-export pruning, crate docs#86

Open
patrickleet wants to merge 2 commits into
mainfrom
hardening/public-api-hygiene
Open

refactor: public API hygiene — non_exhaustive, re-export pruning, crate docs#86
patrickleet wants to merge 2 commits into
mainfrom
hardening/public-api-hygiene

Conversation

@patrickleet

Copy link
Copy Markdown
Collaborator

Public API-surface and docs hygiene from the 2026-06-10 review (maintainability findings 5, 6, 8, 9). Free at 0.1.0, expensive later. API-affecting: root re-export pruning + #[non_exhaustive] additions.

Per-item summary

1. #[non_exhaustive] sweep

Added to the remaining growing types so new variants/fields/capabilities stop being breaking changes:

  • ReadModelError (read_model/mod.rs), HandlerError (microsvc/error.rs)
  • ConsumerAckKind, KnativeIntegrationKind, TransportCapabilities (bus/capabilities.rs)
  • OutboxMessage (outbox/message.rs)

Constructor audit: added TransportCapabilities::new(..) so external transport authors can still declare a custom capability profile now that the struct literal is blocked. OutboxMessage keeps new()/create()/encode*()/Default. The enums need no external construction helper.

Not re-touched: RepositoryError and LockError#[non_exhaustive] was already added to them in #83. No wildcard match arms were forced internally (the defining crate may still match exhaustively), so repository/error.rs and lock/error.rs are untouched.

2. Crate docs + doctests

  • Added #![doc = include_str!("../README.md")] — docs.rs now renders the README.
  • The 49 README rust fences are tagged rust,ignore and the Project Structure tree is text, so cargo test --doc compiles clean. Rationale: the README snippets are deliberately abbreviated fragments referencing app-specific types (Todo, Repo, CreateOrderInput, …) — the README's own "Example Conventions" section says so. Compiling all 49 would require heavy inline scaffolding and add noise without catching real drift. I scoped per the task's stated fallback.
  • The real drift-catching fix is in the in-source doctests: the stale microsvc examples that showed a sync dispatch / fn handle are corrected to async (dispatch(..).await, pub async fn handle, closures returning a future) in microsvc/mod.rs, context.rs, and service.rs.

3. Pruned root re-exports

Low-level outbox row plumbing (outbox_message_insert_plan, outbox_message_row_values) and the whole table::* surface are no longer re-exported at the crate root. They stay reachable under distributed::outbox::* and distributed::table::* (the outbox and outbox_worker modules are now pub). The documented quick-start API is unchanged (outbox_message_schema, outbox_message_key, OUTBOX_MESSAGES_TABLE stay at root because tests/manifest use them there). Internal (manifest.rs) and test references were repointed to the module paths.

4. Topology validators public

BusTopologyConfig and the validators (validate_namespace, validate_consumer_group, resolve_consumer_group, DEFAULT_BUS_NAMESPACE, MAX_TOPOLOGY_NAME_LEN) are now pub and re-exported from bus, matching the already-public validate_stable_message_id. Third-party transports can reuse the portable naming rules, and this removes the 13 dead-code warnings that appeared under --no-default-features and partial feature combos.

5. Dual outbox publisher decision

Documented the boundary rather than folding/retiring (option B). AsyncMessagePublisher (via BusPublisher over a Bus, wired by service.with_bus) is rustdoc'd as the production extension point; the sync OutboxPublisher/OutboxWorker/LogPublisher trio is rustdoc'd as the dev/test-only drain path (trait, OutboxWorker, LogPublisher, the outbox_worker module header, and the README Pluggable table all updated). No parallel hierarchy is introduced — they sit at different layers. Retiring the sync trait was deferred: it is exercised by tests/todos and rewriting it is out of scope for a hygiene PR.

Testing

  • cargo fmt --all --check — clean
  • cargo build (default), --no-default-features, --features postgres,nats, --features sqlite,rabbitmq,http — all build with zero warnings; topology dead-code warnings gone in every combo; #[non_exhaustive] broke no internal matches
  • cargo test --doc (and --features http, --features sqlite) — doc examples compile (0 failed)
  • cargo test (default) — all 39 test binaries green
  • cargo test --features sqlite — green (271 lib tests + integration suites, 0 failed)
  • --all-features intentionally skipped (librdkafka)

🤖 Generated with Claude Code

…te docs

API-affecting cleanup that is free at 0.1.0 and expensive later (2026-06-10
review). Root re-export pruning and #[non_exhaustive] additions change the
public surface; reachability is preserved under module paths.

- #[non_exhaustive] sweep on the remaining growing types: ReadModelError,
  HandlerError, ConsumerAckKind, KnativeIntegrationKind, TransportCapabilities,
  and OutboxMessage. Added TransportCapabilities::new(..) so external transport
  authors can still build a custom capability profile now that the struct
  literal is blocked. OutboxMessage keeps its new()/create()/encode()/Default
  constructors. NOTE: RepositoryError and LockError were intentionally NOT
  re-touched — #[non_exhaustive] was already added to them in #83.

- Crate-level docs: #![doc = include_str!("../README.md")] so docs.rs renders
  the README. README rust fences are tagged `rust,ignore` (the snippets are
  deliberately abbreviated fragments referencing app-specific types, per the
  README's own "Example Conventions" note); the Project Structure tree is now
  `text`. cargo test --doc compiles clean. The real drift-catching fix is in
  the in-source doctests: the stale microsvc examples that showed a SYNC
  dispatch / `fn handle` are corrected to async (`dispatch(..).await`,
  `pub async fn handle`, closures returning a future) in microsvc/mod.rs,
  context.rs, and service.rs.

- Pruned crate-root re-exports: the low-level outbox row plumbing
  (outbox_message_insert_plan, outbox_message_row_values) and the whole
  table::* surface are no longer re-exported at the crate root. They stay
  reachable under distributed::outbox::* and distributed::table::* (the outbox
  and outbox_worker modules are now `pub`). The documented quick-start API is
  unchanged. Internal/test references were repointed to the module paths.

- Made BusTopologyConfig and the namespace/consumer-group validators
  (validate_namespace, validate_consumer_group, resolve_consumer_group,
  DEFAULT_BUS_NAMESPACE, MAX_TOPOLOGY_NAME_LEN) pub and re-exported from `bus`,
  matching validate_stable_message_id. Third-party transports can now reuse the
  portable naming rules, and this removes the dead-code warnings that appeared
  under --no-default-features and partial feature combos.

- Resolved the dual outbox publisher story by documenting the boundary (no
  parallel hierarchies introduced): AsyncMessagePublisher (BusPublisher over a
  Bus, wired by service.with_bus) is THE production extension point; the sync
  OutboxPublisher/OutboxWorker/LogPublisher trio is rustdoc'd as the dev/test
  drain path. Folding/retiring the sync trait was deferred — it is exercised by
  tests/todos and retiring it is out of scope for a hygiene PR.

Verified: cargo fmt --all --check; cargo build for default, --no-default-features,
postgres+nats, sqlite+rabbitmq+http (all zero warnings, no topology dead code);
cargo test --doc; cargo test and cargo test --features sqlite (all green).

Implements [[tasks/public-api-docs-hygiene]]

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@patrickleet, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 1 second. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b769f08b-0629-4672-84ca-9cb6eab6fc20

📥 Commits

Reviewing files that changed from the base of the PR and between 95e4318 and da55d6b.

📒 Files selected for processing (17)
  • README.md
  • src/bus/capabilities.rs
  • src/bus/mod.rs
  • src/bus/topology.rs
  • src/lib.rs
  • src/manifest.rs
  • src/microsvc/context.rs
  • src/microsvc/error.rs
  • src/microsvc/mod.rs
  • src/microsvc/service.rs
  • src/outbox/message.rs
  • src/outbox_worker/mod.rs
  • src/outbox_worker/publisher.rs
  • src/outbox_worker/worker.rs
  • src/read_model/mod.rs
  • tests/distributed_read_model/read_models/mod.rs
  • tests/sqlite_repository/main.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hardening/public-api-hygiene

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

The root re-export pruning in this PR was too aggressive: it dropped
`table::*` (including `TableSchemaRegistry`) and the outbox row-plumbing
fns from the crate root, but `TableSchemaRegistry` is consumed by the
crate's own integration tests via `distributed::TableSchemaRegistry`
(tests/postgres_repository/main.rs) and is the entry point downstream
users build before bootstrapping table migrations. A symbol that the
integration tests import through the crate root is effectively public
API, so it must stay re-exported.

The local verification used `--features sqlite`, which does not compile
the postgres/all-features test crates, so the unresolved-import breaks
were missed in CI (coverage `--all-features` and postgres jobs).

Re-add only `TableSchemaRegistry` to the crate root. The remaining
table primitives stay reachable under `distributed::table::*` (no
test/external root consumers), and the genuinely internal outbox row
plumbing (`outbox_message_insert_plan`, `outbox_message_row_values`)
stays pruned — confirmed zero consumers outside `src/outbox/`.

All test targets now compile, including the postgres and all-features
(librdkafka) coverage targets that previously failed.

Refines [[tasks/public-api-docs-hygiene]]
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