Skip to content

feat(xmtp_api_d14n): XmtpMlsBidiStreams trait + v3 Subscribe transport#3771

Draft
tylerhawkes wants to merge 1 commit into
tyler/xip83-2-bidi-transportfrom
tyler/xip83-3-bidi-api
Draft

feat(xmtp_api_d14n): XmtpMlsBidiStreams trait + v3 Subscribe transport#3771
tylerhawkes wants to merge 1 commit into
tyler/xip83-2-bidi-transportfrom
tyler/xip83-3-bidi-api

Conversation

@tylerhawkes

@tylerhawkes tylerhawkes commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Stack 3/4 of the XIP-83 bidi client lane: #3769#3770#3771#3772.

Native-only XmtpMlsBidiStreams trait in xmtp_proto::api_clientsubscribe_bidi(BoxStream<SubscribeRequest>) -> Stream<Result<SubscribeResponse>> — and its V3Client implementation: prost-encode outbound frames over bidi_stream("/xmtp.mls.api.v1.MlsApi/Subscribe"), decode inbound via the existing XmtpStream. Browsers stay on XmtpMlsStreams + watchdog (gRPC-Web cannot full-duplex).

🤖 Generated with Claude Code

Note

Add XmtpMlsBidiStreams trait and V3 bidirectional Subscribe transport for native targets

  • Defines a new native-only XmtpMlsBidiStreams trait in api_client.rs with a subscribe_bidi method that accepts a BoxStream<SubscribeRequest> and returns a stream of SubscribeResponse.
  • Implements the trait for V3Client in a new bidi.rs module, opening a long-lived bidirectional stream at /xmtp.mls.api.v1.MlsApi/Subscribe and mapping transport errors to include the endpoint.
  • Both the trait and implementation are gated behind cfg(not(target_arch = "wasm32")) and are not available in WASM builds.
📊 Macroscope summarized 0f1cead. 2 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@claude

claude Bot commented Jun 12, 2026

Copy link
Copy Markdown

Claude finished @tylerhawkes's task —— View job


Code Review Complete

Review Date: 2026-06-16 21:06 UTC

Summary

The implementation is straightforward and follows established patterns. However, there are two critical issues that need to be addressed for consistency with the rest of the codebase:


🔴 Critical Issues

1. Missing blanket implementations for Box<T> and Arc<T> (macroscopeapp's comment is correct)

Location: crates/xmtp_proto/src/api_client.rs:192

The new XmtpMlsBidiStreams trait is missing blanket impls that exist for all other traits in this module (XmtpMlsClient, XmtpMlsStreams, XmtpIdentityClient). See api_client/impls.rs:262-329 for the pattern.

Impact: Any code that wraps the client in Box<dyn XmtpMlsBidiStreams> or Arc<dyn XmtpMlsBidiStreams> will fail to compile.

Fix needed in crates/xmtp_proto/src/api_client/impls.rs:

#[xmtp_common::async_trait]
impl<T> XmtpMlsBidiStreams for Box<T>
where
    T: XmtpMlsBidiStreams + Sync + ?Sized,
{
    type Error = <T as XmtpMlsBidiStreams>::Error;
    type SubscribeStream = <T as XmtpMlsBidiStreams>::SubscribeStream;

    async fn subscribe_bidi(
        &self,
        requests: futures::stream::BoxStream<'static, crate::mls_v1::SubscribeRequest>,
    ) -> Result<Self::SubscribeStream, Self::Error> {
        (**self).subscribe_bidi(requests).await
    }
}

#[xmtp_common::async_trait]
impl<T> XmtpMlsBidiStreams for Arc<T>
where
    T: XmtpMlsBidiStreams + ?Sized,
{
    type Error = <T as XmtpMlsBidiStreams>::Error;
    type SubscribeStream = <T as XmtpMlsBidiStreams>::SubscribeStream;

    async fn subscribe_bidi(
        &self,
        requests: futures::stream::BoxStream<'static, crate::mls_v1::SubscribeRequest>,
    ) -> Result<Self::SubscribeStream, Self::Error> {
        (**self).subscribe_bidi(requests).await
    }
}

Note: These impls also need #[cfg(not(target_arch = "wasm32"))] since the trait itself is native-only.

2. Test Coverage Missing

Location: crates/xmtp_api_d14n/src/queries/v3/bidi.rs

Codecov reports 0% coverage on the new bidi.rs file (4 lines untested: 30, 33, 36, 39). The implementation has no tests.

Recommendation: Add at least a basic integration test that:

  • Opens a bidirectional stream
  • Sends a SubscribeRequest
  • Receives a SubscribeResponse
  • Verifies error handling

Minor Observations

  1. Performance instrumentation (insipx's comment): Consider adding #[xmtp_common::rpc_span] to subscribe_bidi at line 25 for consistency with other RPC methods in the codebase (see xmtp_api/src/mls.rs:97).

  2. Error handling: The error mapping at line 39 correctly adds endpoint context via .endpoint(SUBSCRIBE_PATH.to_string()), consistent with other methods.

  3. Stream construction: The prost encoding at line 30 and XmtpStream wrapping at lines 40-43 follow established patterns.


Non-Issues

  • ✅ Native-only gating is correct (#[cfg(not(target_arch = "wasm32"))])
  • ✅ Module structure follows conventions
  • ✅ Type signatures are sound
  • ✅ Implementation delegates correctly to underlying bidi_stream transport

&self,
requests: futures::stream::BoxStream<'static, SubscribeRequest>,
) -> Result<Self::SubscribeStream, Self::Error> {
tracing::debug!("opening bidirectional subscription");

@insipx insipx Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could annotate with #[xmtp_common::rpc_span] when this makes it to xmtp_api to capture the perf span

#[xmtp_common::rpc_span]

@tylerhawkes tylerhawkes force-pushed the tyler/xip83-2-bidi-transport branch from 5329964 to ba3c4de Compare June 12, 2026 21:33
@tylerhawkes tylerhawkes force-pushed the tyler/xip83-3-bidi-api branch from 22b2c8b to a9ffc28 Compare June 12, 2026 21:33
@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (tyler/xip83-2-bidi-transport@af6ab11). Learn more about missing BASE report.

Files with missing lines Patch % Lines
crates/xmtp_api_d14n/src/queries/v3/bidi.rs 0.00% 4 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                       @@
##             tyler/xip83-2-bidi-transport    #3771   +/-   ##
===============================================================
  Coverage                                ?   84.41%           
===============================================================
  Files                                   ?      409           
  Lines                                   ?    59908           
  Branches                                ?        0           
===============================================================
  Hits                                    ?    50573           
  Misses                                  ?     9335           
  Partials                                ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@tylerhawkes tylerhawkes force-pushed the tyler/xip83-2-bidi-transport branch from ba3c4de to cf43cdd Compare June 12, 2026 21:59
@tylerhawkes tylerhawkes force-pushed the tyler/xip83-3-bidi-api branch 2 times, most recently from 249cf99 to 13bce00 Compare June 15, 2026 20:20
@tylerhawkes tylerhawkes force-pushed the tyler/xip83-2-bidi-transport branch from cf43cdd to 7ef18f0 Compare June 15, 2026 20:20
requests: futures::stream::BoxStream<'static, crate::mls_v1::SubscribeRequest>,
) -> Result<Self::SubscribeStream, Self::Error>;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium src/api_client.rs:192

Adding XmtpMlsBidiStreams without blanket impls for Box<T> and Arc<T> breaks the boxed/arced client pattern used throughout xmtp_proto. Callers that erase concrete clients into Box<dyn XmtpMlsBidiStreams> or Arc<dyn XmtpMlsBidiStreams> will get a compile error when calling subscribe_bidi because the wrapper types don't implement the new trait. Consider adding the standard blanket impls: impl<T: XmtpMlsBidiStreams + ?Sized> XmtpMlsBidiStreams for Box<T> and Arc<T>.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @crates/xmtp_proto/src/api_client.rs around line 192:

Adding `XmtpMlsBidiStreams` without blanket impls for `Box<T>` and `Arc<T>` breaks the boxed/arced client pattern used throughout `xmtp_proto`. Callers that erase concrete clients into `Box<dyn XmtpMlsBidiStreams>` or `Arc<dyn XmtpMlsBidiStreams>` will get a compile error when calling `subscribe_bidi` because the wrapper types don't implement the new trait. Consider adding the standard blanket impls: `impl<T: XmtpMlsBidiStreams + ?Sized> XmtpMlsBidiStreams for Box<T>` and `Arc<T>`.

tylerhawkes added a commit that referenced this pull request Jun 16, 2026
…#3769)

**Stack 1/4** of the XIP-83 bidi client lane: #3769#3770#3771#3772.

Regenerated `xmtp.mls.api.v1` from xmtp/proto#337: the bidirectional
`Subscribe` RPC with versioned `SubscribeRequest`/`SubscribeResponse`,
id-based `Mutate` (cursors, `history_only`), `Ping`/`Pong`,
`TopicsLive`, `CATCHUP_COMPLETE`, and STARTED `capabilities`. Purely
additive (+1,896 generated lines); `proto_version` pinned to that
branch's sha — draft until the proto PR merges.
…t (XIP-83, native-only)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tylerhawkes tylerhawkes force-pushed the tyler/xip83-2-bidi-transport branch from 7ef18f0 to af6ab11 Compare June 16, 2026 21:04
@tylerhawkes tylerhawkes force-pushed the tyler/xip83-3-bidi-api branch from 13bce00 to 0f1cead Compare June 16, 2026 21:04
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