Skip to content

core: PoC - MirroringInterceptor for traffic shadowing (#12448)#12721

Open
themechbro wants to merge 7 commits intogrpc:masterfrom
themechbro:feature/grpc-mirroring-unary
Open

core: PoC - MirroringInterceptor for traffic shadowing (#12448)#12721
themechbro wants to merge 7 commits intogrpc:masterfrom
themechbro:feature/grpc-mirroring-unary

Conversation

@themechbro
Copy link
Contributor

Description

This Draft PR is a Proof-of-Concept implementation of the MirroringInterceptor designed to shadow traffic to a secondary Channel.

Motivation & Credit

This implementation is directly inspired by the excellent architectural proposal outlined by @sibasispadhi in Issue #12448.

@sibasispadhi - I saw your comment about wanting to tackle this and draft a ClientInterceptor approach. I didn't want to step on your toes, but I was so interested in the concept that I decided to build a local prototype to see if I could make the fire-and-forget and lifecycle requirements work. I'm submitting this PoC to help validate your proposed architecture. I am more than happy to collaborate on this, hand the branch over to you, or close this if you already have a working branch going!

Implementation Details (Based on the proposed design)

  • Asynchronous Fire-and-Forget: Mirroring logic is executed on a provided Executor.
  • Full Streaming Support: The interceptor captures headers during start(), initializes a single mirrorCall per stream, and reuses it for all subsequent sendMessage() invocations to ensure correct ordering.
  • Lifecycle Management: The shadow call accurately tracks the primary call by propagating halfClose() and cancel() signals.
  • Thread Safety: Initial metadata is explicitly copied and merged before being passed to the background executor.

Testing Done

  • Verified locally via InProcess transport.
  • Confirmed header propagation and correct handling of both unary and streaming lifecycles.

Add a reachability fence in shutdown() and shutdownNow() to ensure the
wrapper is not garbage collected while shutdown logic is executing.
This prevents a race condition when using directExecutor() where a
warning could be logged despite a proper shutdown.

Fixes grpc#12641
This adds a fire-and-forget interceptor that mirrors Unary and Streaming
traffic to a secondary channel without blocking the primary call.
Headers are copied and propagated safely, and the secondary call
respects the lifecycle (halfClose, cancel) of the primary stream.

Addresses the Java ClientInterceptor proposal discussed in grpc#12448
@sibasispadhi
Copy link

@themechbro - no worries. I was waiting for owners & reviewers to comment before proceeding. Since you have started, please go ahead. Let me know if need to review anything.

@themechbro
Copy link
Contributor Author

@themechbro - no worries. I was waiting for owners & reviewers to comment before proceeding. Since you have started, please go ahead. Let me know if need to review anything.

Thanks so much, @sibasispadhi! I really appreciate it.

I just pushed a quick fix for some Checkstyle and import errors that the CI caught. As soon as these GitHub Actions turn green, I would absolutely love to get your thoughts and review on the implementation—especially to see if the way I handled the streaming lifecycle and halfClose aligns with your original design thoughts.

Thanks again for the great proposal that kicked this off!

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.

2 participants