Real NATS JetStream pull consumer implementation added to consumer.rs, completing the abstraction seam established in Task 4.
Location
/Users/levander/coding/pmv2/telegram_connector-outbound/crates/telegram_connector/src/consumer.rs
Trait Seam (Task 4, lines 1–19)
Three types form the abstraction layer that lets tests inject a fake transport:
pub enum Disposition { Ack, Nak(Option<Duration>), Term }
#[async_trait] pub trait IncomingMessage: Send + Sync {
fn payload(&self) -> &[u8];
async fn settle(&self, d: Disposition) -> anyhow::Result<()>;
}
#[async_trait] pub trait MessageSource: Send {
async fn next(&mut self) -> Option<anyhow::Result<Box<dyn IncomingMessage>>>;
}Real Implementation (Task 5, lines 21–95)
connect(url, nkey_seed)
Creates an async_nats::Client. When nkey_seed is non-empty, wraps with ConnectOptions::new().nkey(seed). Requires the nkeys feature (enabled on the workspace dep).
build_source(client, stream, durable, subject, ack_wait_secs, max_deliver)
- Calls
jetstream::new(client)to get the JetStream context. js.get_stream(stream)— gets the named stream (local variable renamednats_streamto avoid shadowing thestream: &strparam).nats_stream.get_or_create_consumer(durable, pull::Config { ... })— creates a durable pull consumer with explicit ack policy, configurableack_wait,max_deliver, andfilter_subject.consumer.messages()— returns the pull message stream.- Wraps in
NatsSource.
NatsSource / NatsMessage
| Type | Wraps | Role |
|---|---|---|
NatsSource | jetstream::consumer::pull::Stream | Implements MessageSource via StreamExt::next() |
NatsMessage | jetstream::Message | Implements IncomingMessage; settle() maps Disposition → AckKind |
Disposition → AckKind mapping
Disposition | jetstream::AckKind |
|---|---|
Ack | Ack |
Nak(Option<Duration>) | Nak(delay) |
Term | Term |
async-nats 0.49 API Notes
For Agents
All type paths and variant names from async-nats 0.38 docs are compatible with 0.49. No API migration was required. Only code change driven by the upgrade: rename local
streamvar tonats_streamto avoid shadowing the function parameter.
async_nats::jetstream::consumer::pull::Stream— the pull message stream typeasync_nats::jetstream::AckKind— ack variant enumfutures::StreamExt— provides.next()on the pull stream; imported viafuturesworkspace dep
Dependencies Added
In crates/telegram_connector/Cargo.toml:
async-nats = { workspace = true } # workspace pins 0.49, features = ["nkeys"]
futures = { workspace = true } # StreamExt on pull::StreamCommit & Build
- Commit:
95b8288onfeat/outbound-relay - Build: clean (no warnings)
- Tests: 19 passing