Skip to content

feat: Wire in-service RPC core for ctx.rpc.call#156

Merged
doubleailes merged 1 commit into
mainfrom
feat/in-service-rpc-core
Apr 29, 2026
Merged

feat: Wire in-service RPC core for ctx.rpc.call#156
doubleailes merged 1 commit into
mainfrom
feat/in-service-rpc-core

Conversation

@doubleailes
Copy link
Copy Markdown
Owner

Summary

Builds on #155 (the async handler / RpcContext refactor) to make ctx.rpc.call(...) actually work.

  • New girolle/src/rpc_core.rsRpcCallerCore owns a per-service reply queue (rpc.listener-<service-uuid>), a publish channel, and a DashMap<correlation_id, oneshot::Sender<PayloadResult>> correlation map. new() declares the queue, starts a delegate that drains correlations into the map, and returns Arc<Self>.
  • RpcCaller now holds Option<Arc<RpcCallerCore>> plus the parent delivery's FieldTable. pub async fn call(service, method, payload) -> GirolleResult<Value> is live. Per-delivery, the consumer derives a caller via with_parent_headers(inbound_headers) so nameko.call_id_stack propagates from the parent. nameko.AMQP_URI is always stamped; the stack is seeded with the service identifier when the parent had none.
  • RpcService startup calls RpcCallerCore::new(&conn, conf, id) once and stores the resulting caller in SharedData.
  • Adds dashmap = 6.1 and the proxy_service example forwarding proxy.hellovideo.hello from inside its handler.

Known limitations (deferred)

  • Pending entries with no reply leak forever; no timeout yet.
  • Outbound call_id_stack is propagated as-is from the parent — Python Nameko also stamps the parent service's outbound call entry on the way out. Cosmetic; the chain is still continued correctly by the target.
  • EventDispatcher still inert — that's the next PR.

Test plan

  • cargo build --workspace
  • cargo build --examples (incl. new proxy_service)
  • cargo test --workspace --lib (14 passed)
  • cargo test --workspace --doc (30 + 1 passed)
  • cargo clippy --workspace --all-targets
  • Smoke test: run `simple_macro` + `proxy_service` against RabbitMQ; call `proxy.hello` and confirm reply matches `video.hello`'s output.

🤖 Generated with Claude Code

Add a real implementation behind the placeholder `RpcCaller` introduced
in the previous commit. Each `RpcService` now stands up a per-instance
reply queue (`rpc.listener-<service-uuid>`), a publish channel, and a
`DashMap<correlation_id, oneshot::Sender<PayloadResult>>` correlation
map that the reply consumer drains.

`RpcCaller::call(service, method, payload)` is `pub async`. Per
delivery, the consumer derives a caller stamped with the inbound
delivery's headers via `with_parent_headers`, so `nameko.call_id_stack`
propagates from the parent. `nameko.AMQP_URI` is always stamped; the
stack is seeded with the service identifier when the parent had none.

The new `examples/src/proxy_service.rs` demonstrates a service that
forwards `proxy.hello` to `video.hello` from inside its handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

@doubleailes doubleailes merged commit cfdd60d into main Apr 29, 2026
5 checks passed
@doubleailes doubleailes deleted the feat/in-service-rpc-core branch April 29, 2026 09:47
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