Skip to content

Port Obvs.NATS from NATS.Client to NATS.Net - #99

Closed
christopherread wants to merge 7 commits into
masterfrom
upgrade/nats-net
Closed

christopherread wants to merge 7 commits into
masterfrom
upgrade/nats-net

Conversation

@christopherread

@christopherread christopherread commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Fixes #78. Merge after #82: this branch is built on it so CI can run the NATS tests against a real server, and the diff includes #82's commits until it merges.

Changes

  • Package: NATS.Client 1.1.8 (legacy) → NATS.Client.Core 3.3.1, the core client of NATS.Net. I used it instead of the NATS.Net meta-package because Obvs doesn't need JetStream, key-value or object store. It supports net472 (via netstandard2.0), netstandard2.1 and net10.0.
  • MessagePublisher: awaits PublishAsync on the connection. Before, it published synchronously and returned a completed task.
  • MessageSource: subscribes with SubscribeCoreAsync and reads the subscription's message channel on a background task.
    • Subscribe still blocks until the server has the subscription, as with 1.x, so messages published straight after it aren't missed.
    • Processing errors still go to OnError.
    • Disposing unsubscribes.
  • Connections: SharedConnectionFactory creates a NatsConnection(new NatsOpts { Url }) per URL; it connects on first use, as the Lazy connections did. Endpoint disposal disposes the connection, as before.
  • C# version: Obvs.NATS compiles as C# 9, because NatsOpts has init-only properties and net472/netstandard2.0 default to C# 7.3. It's compiler-only; there's no runtime requirement.
  • Analyzer warnings: NATS.Net brings in the VS threading analyzers. The deliberate sync waits (Subscribe and Dispose are synchronous in Obvs) are suppressed with a comment. The fire-and-forget receive task is explicitly discarded; it reports its own failures to the observer.

Wire format unchanged

Messages still carry the protobuf MessageWrapper envelope (properties + body) on subjects <prefix>.<TypeName>. So services on old and new Obvs.NATS versions can exchange messages. NATS headers would be the modern alternative, but switching would break mixed deployments.

⚠️ Breaking changes for consumers

  • Fluent configuration (WithNatsEndpoint(settings => …), Url, IsShared, message properties): unchanged.
  • Direct use of MessageSource and MessagePublisher: the constructors take an INatsConnection instead of Lazy<IConnection>. For example: new MessageSource<T>(new NatsConnection(new NatsOpts { Url = url }), …).
  • The NATS.Client dependency is gone. Code that uses its types alongside Obvs.NATS needs NATS.Net.

Testing

I made the tests check outcomes first, then compared the old and new client in CI against a real nats:2.15 server:

  • TestSourceAndPublisher: all 10 messages arrive, in order. It previously only printed them.
  • TestServiceBus: the reply arrives with the right Id, and the command's event is received. It previously only printed.
NATS.Client 1.1.8 (first commit) NATS.Net 3.3.1 (this PR)
NATS broker tests ✅ 2/2 ✅ 2/2

RabbitMQ (3) and Kafka (1) broker tests also pass in both runs. The solution builds for all targets with no new warnings, and all unit tests pass.

🤖 Generated with Claude Code

christopherread and others added 5 commits October 24, 2026 23:41
Start RabbitMQ, NATS and Kafka as service containers and run each
transport's Category=Explicit tests against them in a separate step.
The NATS and Kafka tests now read NATS_URL and KAFKA_BOOTSTRAP_SERVERS
(defaulting to localhost) instead of hard-coded Docker addresses, like
the RabbitMQ tests' RABBITMQ_URI.

Part of #74; the NetMQ tests join once #80 is merged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setting KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS alone replaced the
image defaults and the broker failed to start (missing process.roles).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Kafka test consumer starts at the latest offset and Subscribe returns
before partitions are assigned, so on a fresh broker it missed the
messages while __consumer_offsets was being created. Use one offsets
partition and run a warm-up consumer group first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TestSourceAndPublisher now checks all 10 messages arrive in order, and
TestServiceBus checks the reply and the event produced by the command,
instead of only printing them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….3.1)

MessageSource and MessagePublisher take an INatsConnection instead of
Lazy<IConnection>; a NatsConnection connects on first use. Publishing
awaits PublishAsync, and subscriptions read the NATS.Net message channel
on a background task. Subscribe still blocks until the server has the
subscription, so messages published straight after it aren't missed.

The protobuf MessageWrapper envelope is unchanged, so services on the old
and new client can exchange messages. The fluent configuration is
unchanged. Obvs.NATS compiles as C# 9 to set NATS.Net's init-only options.

Fixes #78

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@christopherread
christopherread marked this pull request as ready for review October 25, 2026 06:59
christopherread and others added 2 commits October 25, 2026 00:06
Master now runs tests on Microsoft.Testing.Platform (#101), so use
--project and --filter-trait. The NetMQ tests no longer clash over ports
(#80), so run them too. The broker steps now come before the unit test
step, so this branch no longer edits the lines master changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They lose the first messages on CI runners (ZeroMQ slow joiner): the
publisher socket is created on first publish and sends before
subscribers have connected. Tracked separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@christopherread

Copy link
Copy Markdown
Owner Author

Combined into #104, which includes this change as its own commit.

christopherread added a commit that referenced this pull request Oct 25, 2026
…h and NATS.Net ports, Kafka subscribe fix (#104)

Fixes #74, fixes #76, fixes #77, fixes #78, fixes #79, fixes #103.

Combines #82, #83, #96, #98 and #99, plus the Kafka subscribe fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@christopherread
christopherread deleted the upgrade/nats-net branch October 25, 2026 23:01
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.

Migrate Obvs.NATS from NATS.Client to NATS.Net

1 participant