Skip to content

Implement typed microsvc route bundles - #95

Merged
patrickleet merged 3 commits into
mainfrom
codex/microsvc-routes-api
Jun 23, 2026
Merged

patrickleet merged 3 commits into
mainfrom
codex/microsvc-routes-api

Conversation

@patrickleet

@patrickleet patrickleet commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Introduce typed Routes<D> bundles and make Service a non-generic deployment router that indexes multiple route bundles.
  • Add the primary routes! macro and remove the legacy register_handlers! macro; backwards compatibility with service-owned registration is intentionally not retained.
  • Route direct dispatch, HTTP, gRPC, bus consumption, and immediate outbox publish-on-commit through the service-level index.
  • Add explicit route dependency-combination coverage for custom, repo-only, read-model-only, and repo+read-model bundles in one service.

Verification

  • cargo fmt --check
  • git diff --check
  • cargo check --tests --all-features
  • cargo test service_dispatches_all_route_dependency_builder_combinations --all-features
  • cargo test microsvc::service --all-features
  • cargo test --all-features --test microsvc --test sagas --test durable_enqueue_sqlite --test distributed_read_model --test distributed_read_model_board
  • cargo test microsvc::runtime --all-features
  • cargo test --all-features

Review follow-up

  • Addressed CodeRabbit discussion r3462873453 by removing register_handlers! entirely, per the decision that backwards compatibility is not required.
  • Added service_dispatches_all_route_dependency_builder_combinations after review discussion about covering all route-builder dependency shapes.

Notes

  • cargo clippy --all-targets --all-features -- -D warnings is currently blocked by pre-existing lints in untouched files: tests/todos/main.rs (await_holding_lock) and src/outbox_worker/worker.rs (manual_async_fn).

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces Routes<D> as a typed handler-bundle abstraction and removes the generic Service<D> type parameter. Handler registration moves from Service to Routes<D> bundles; Service now holds multiple type-erased bundles behind an ErasedRoutes trait. A new routes! macro replaces register_handlers!. All transport adapters, the runtime bus wiring, and every test are updated accordingly.

Changes

Routes<D> bundle model and de-genericized Service

Layer / File(s) Summary
Routes<D> / Service core data model and dispatch
src/microsvc/service.rs
Defines Routes<D>, ErasedRoutes, OutboxConfigurator, RouteBuilder<D>, and the non-generic Service struct. Implements duplicate-aware handler registration, Routes::invoke for guard+handler execution, Service::add_routes for bundle indexing, Service::invoke via bundle-index lookup, and configure_outbox_publishers iterating all bundles.
routes! macro, register_handlers! alias, and public re-exports
src/microsvc/mod.rs
Adds the routes! macro (plus hidden __routes/__routes_continue expanders) that builds Routes<D> bundles from command/event/events module lists. Converts register_handlers! into a compatibility alias delegating to routes!. Expands public re-exports to include RouteBuilder and Routes.
Transport adapters and MessageRouter de-genericized
src/microsvc/grpc.rs, src/microsvc/http.rs, src/microsvc/knative_ingress.rs, src/microsvc/message_router.rs, src/bus/router.rs, src/bus/handlers.rs
Removes the D type parameter from GrpcHandler, grpc_server, serve_grpc, router, serve, cloud_events_router, and the MessageRouter impl. All transport entry points now accept Arc<Service> directly.
Runtime bus wiring de-genericized
src/microsvc/runtime.rs
Moves with_bus and run_consumers from impl<D> Service<D> to impl Service. with_bus calls configure_outbox_publishers with DynBusPublisher; run_consumers takes Arc<Service>. Updates runtime tests to build services via Routes::new() and capture outbox stores from repo before dispatch.
service.rs unit tests migrated to Routes builder
src/microsvc/service.rs
Introduces test_routes() and test_service(routes) helpers; rewrites all unit tests (dispatch, subscription plan, guards, request/response, event recording, duplicate registration, multi-bundle) to construct services via route bundles.
Integration and transport test migration
src/outbox_worker/outbox_source.rs, tests/microsvc/*, tests/transport_conformance/mod.rs, tests/sagas/microsvc_saga.rs, tests/distributed_read_model/..., tests/distributed_read_model_board/..., tests/durable_enqueue_sqlite/main.rs, tests/kafka_transport/main.rs, tests/nats_transport/main.rs, tests/rabbitmq_transport/main.rs, tests/postgres_transport/main.rs, tests/knative_cloudevents/main.rs
Migrates all integration and transport tests to Service::new().routes(Routes::new()...) or the routes! macro. Helpers returning Arc<Service<D>> now return Arc<Service>. State verification reads from shared repository stores instead of service.repo().
README and doc comment updates
README.md, src/microsvc/mod.rs, src/bus/router.rs, src/bus/handlers.rs
Updates quickstart, "Swap persistence and transports," microsvc section, guards snippet, and handler-convention examples to use Routes::new()/routes!/Service::new().routes(routes). Doc comments updated to reference the non-generic Service and route bundles.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Service
  participant RouteIndex
  participant RouteBundle
  participant Handler

  Client->>Service: dispatch message
  Service->>RouteIndex: lookup by kind and name
  RouteIndex-->>Service: selected bundle
  Service->>RouteBundle: invoke message
  RouteBundle->>Handler: run guard and handler
  Handler-->>RouteBundle: HandlerResult
  RouteBundle-->>Service: HandlerResult
  Service-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • hops-ops/distributed#43: Modifies the same register_handlers! macro and handler builder APIs in src/microsvc/mod.rs that this PR repurposes as a compatibility alias delegating to the new routes! system.
  • hops-ops/distributed#51: Establishes the MessageRouter seam in src/microsvc/message_router.rs and src/bus/router.rs that this PR updates to target the non-generic Service.
  • hops-ops/distributed#77: Adds MessageRouter::consumer_group() for Service identity via Service::named, which this PR touches when retargeting the MessageRouter impl from Service<D> to Service.

Poem

🐇 Hoppity-hop, no more D to drag,
My bundles are typed in a neat little bag!
Routes::new() I build, then pass them along,
The Service collects them — the whole clever throng.
No generics to puzzle, no <D> in my way,
Just routes full of handlers to brighten my day! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Implement typed microsvc route bundles' accurately and concisely summarizes the main change: introducing a new typed Routes<D> structure for organizing service routes with type safety, which is the core objective of this changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/microsvc-routes-api

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/microsvc/mod.rs`:
- Around line 196-206: The register_handlers! macro is documented as a
backward-compatibility alias but currently just forwards directly to routes! on
both match arms, which breaks legacy service-based calls like
register_handlers!(Service::new(), command handlers::x). You need to modify the
register_handlers! macro to properly handle the legacy pattern where the first
argument is a Service instance followed by a handler type and handlers, and
internally convert that to the appropriate routes! call instead of directly
forwarding all arguments to routes!.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35142d56-2dcc-4691-87c0-ebaf6039dcce

📥 Commits

Reviewing files that changed from the base of the PR and between e28f91f and 26f8a01.

📒 Files selected for processing (33)
  • README.md
  • src/bus/handlers.rs
  • src/bus/router.rs
  • src/microsvc/grpc.rs
  • src/microsvc/http.rs
  • src/microsvc/knative_ingress.rs
  • src/microsvc/message_router.rs
  • src/microsvc/mod.rs
  • src/microsvc/runtime.rs
  • src/microsvc/service.rs
  • src/outbox_worker/outbox_source.rs
  • tests/distributed_read_model/checkout_saga_service/service.rs
  • tests/distributed_read_model/main.rs
  • tests/distributed_read_model/projection_service/service.rs
  • tests/distributed_read_model/seat_inventory_service/service.rs
  • tests/distributed_read_model_board/board_service/service.rs
  • tests/distributed_read_model_board/main.rs
  • tests/distributed_read_model_board/projections_service/mod.rs
  • tests/durable_enqueue_sqlite/main.rs
  • tests/kafka_transport/main.rs
  • tests/knative_cloudevents/main.rs
  • tests/microsvc/basic.rs
  • tests/microsvc/convention.rs
  • tests/microsvc/session.rs
  • tests/microsvc/transport_grpc.rs
  • tests/microsvc/transport_http.rs
  • tests/microsvc/transport_listen.rs
  • tests/microsvc/transport_subscribe.rs
  • tests/nats_transport/main.rs
  • tests/postgres_transport/main.rs
  • tests/rabbitmq_transport/main.rs
  • tests/sagas/microsvc_saga.rs
  • tests/transport_conformance/mod.rs

Comment thread src/microsvc/mod.rs Outdated
@patrickleet
patrickleet merged commit 07daf63 into main Jun 23, 2026
8 checks passed
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