https://github.com/zio/zio-nats
https://github.com/zio/zio-nats
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/zio/zio-nats
- Owner: zio
- License: apache-2.0
- Created: 2025-07-16T15:04:56.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2026-02-26T00:01:34.000Z (3 months ago)
- Last Synced: 2026-02-26T04:06:05.515Z (3 months ago)
- Language: Shell
- Size: 21.5 KB
- Stars: 1
- Watchers: 0
- Forks: 8
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# zio-nats
A lightweight ZIO 2.x wrapper around the official Java NATS client (jnats).
Features:
- ZLayer-based managed connection acquisition & clean shutdown via `Nats.live` / `Nats.liveZIO`
- Simple publish & request APIs (string or byte array)
- Streaming consume API via ZStream using a NATS Dispatcher bridged through a ZIO Queue
- Minimal service (`Nats`) you pull from the environment with `ZIO.service[Nats]`
- Configurable via ZIO Config (env vars or system properties by default)
## Usage
Provide the layer and obtain the `Nats` service:
```scala
import zio.*
import zio.nats.*
val program = for {
nats <- ZIO.service[Nats]
_ <- nats.publishString("demo.events", "hello world")
msg <- nats
.subscribe("demo.events")
.take(1)
.runHead
.someOrFail(new RuntimeException("No message received"))
_ <- Console.printLine(s"Received: ${msg.asString()}")
} yield ()
val run = program.provide(Nats.live(NatsConfig.default), Scope.default)
```
### Requests
```scala
for {
nats <- ZIO.service[Nats]
response <- nats.requestString("service.echo", "ping", 2.seconds)
} yield response
```
(Requires some service already replying on that subject.)
### Raw byte APIs
If you want lower-level control:
```scala
val publishBytes: RIO[Nats, Unit] =
ZIO.serviceWithZIO[Nats](_.publish("binary.subject", Array[Byte](1,2,3)))
```
### Layer Variants
You can derive the layer from config (env / system properties) directly:
```scala
val layer: ZLayer[Scope, Throwable, Nats] = Nats.live
```
Or provide an explicit `NatsConfig`:
```scala
val layerExplicit = Nats.live(NatsConfig(host = "localhost", port = 4222))
```
You can also customize the `Options.Builder` from jnats if you need to. See [jnats docs](https://github.com/nats-io/nats.java) for details.
```scala
val layerCustom = Nats.live(NatsConfig.default, _.maxReconnects(5))
```
## Configuration via Environment
We use ZIO Config to load configuration (nested under `nats`). Via environment variables for example:
| Variable | Meaning | Default |
|-----------------|-------------------------|------------|
| NATS_HOST | Hostname | localhost |
| NATS_PORT | Port | 4222 |
| NATS_USERNAME | Username (optional) | - |
| NATS_PASSWORD | Password (optional) | - |
| NATS_TLS | Enable TLS (true/false) | false |
```scala
val layer = Nats.live
```
## Streaming Example
```scala
import zio.*
import zio.stream.*
import zio.nats.*
val streamProgram = ZStream.serviceWithStream[Nats](_.subscribe("orders.created"))
.map(_.asString())
.tap(str => Console.printLine(s"Order event: $str"))
.runDrain
```
## Testing
An integration test spec (`NatsSpec`) exercises publish / subscribe, request / reply, and queue group distribution. Run with Mill:
```bash
mill zioNats.test
```
It uses the [java nats server runner](https://github.com/nats-io/java-nats-server-runner) and requires a NATS server being installed locally.
## Notes & Future Work
- Add request/reply helper for automatic responders
- Add JetStream (streaming persistence) support (future)
- Add structured error model + retries/backoff utilities
## License
Apache 2.0