package nats-client-async
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=3f73132bc4b39e0b8f6960085b74868f6f4e2bd7a55528fc2a22f90caedd1ec8
sha512=4f6e6dfa0aa3029c178fbb1b266a3ea604f2c51579267d1e7ab2e7382a70335f6c05a463a851b860accdeee6eb78eca735ec887a1d4c944716d514aa63fefdfd
doc/README.html
NATS - OCaml Client & Async
Lean OCaml NATS clients built around a small protocol core and an Async runtime.
The project was inspired by romanchechyotkin/nats.ocaml, but this is a fresh implementation with an Async-first runtime, HPUB support, reconnect handling, and a smaller public surface.
Packages
nats-client- protocol types and codecs
CONNECT,PUB,HPUB,SUB,UNSUB,PING,PONG- server line parsing for
INFO,MSG,HMSG,+OK, and-ERR
nats-client-async- TCP client built on
Async - automatic reconnect with backoff
- keepalive
PING/PONG - subscriptions and request/reply
- fire-and-forget publishing
- TCP client built on
Installation
With opam:
opam install nats-client nats-client-asyncFrom source:
dune build @install
dune installIf you are developing against this repository locally, use proto to install the toolchain from .prototools, then run dune and opam directly from that shell environment.
Features
- TCP connection over
Async - required NATS handshake with automatic
protocol=1/headers=truenegotiation when the server advertises header support - configurable
CONNECTfields - HPUB publish with headers
- incoming
HMSGparsing and header delivery - JSON payload helpers via
Yojson.Safe.t - server
PINGhandling and client keepalivePING - automatic reconnect with exponential backoff
- disabled mode when
connect Noneis used - silent drop semantics for publish when disconnected or disabled
Disabled Mode
Calling Nats_client_async.connect None returns a disabled client.
In disabled mode:
publishis a no-oppublish_jsonis a no-oppublish_resultreturns`Droppedsubscribe,unsubscribe, andrequestreturn an error
This is useful when a caller wants to keep its main transaction path identical with or without NATS.
Core API
val Nats_client.Protocol.encode_connect :
?connect:Nats_client.Protocol.connect -> unit -> string
val Nats_client.Protocol.encode_pub :
subject:string -> ?reply_to:string -> string -> string
val Nats_client.Protocol.encode_hpub :
subject:string -> ?reply_to:string -> headers:Nats_client.Headers.t -> string -> string
val Nats_client.Protocol.parse_server_line :
string -> Nats_client.Protocol.parsed_lineThe protocol layer also exposes:
Nats_client.Headersfor ordered, repeatable headersNats_client.Sidfor subscription idsNats_client.Protocol.messagefor received messages
Async API
val Nats_client_async.connect :
?connect:Nats_client.Protocol.connect ->
?ping_interval:Time_ns.Span.t ->
?ping_timeout:Time_ns.Span.t ->
?reconnect_initial:Time_ns.Span.t ->
?reconnect_max:Time_ns.Span.t ->
Uri.t option ->
client Deferred.t
val Nats_client_async.publish :
client -> subject:string -> ?reply_to:string -> ?headers:Nats_client.Headers.t -> string -> unit
val Nats_client_async.publish_json :
client -> subject:string -> ?reply_to:string -> ?headers:Nats_client.Headers.t -> Yojson.Safe.t -> unit
val Nats_client_async.subscribe :
client -> subject:string -> ?queue_group:string -> ?sid:Nats_client.Sid.t -> unit -> subscription Or_error.t Deferred.t
val Nats_client_async.request :
client -> subject:string -> ?headers:Nats_client.Headers.t -> ?timeout:Time_ns.Span.t -> string -> string Or_error.t Deferred.tpublish and publish_json are fire-and-forget. If the client is unavailable, they are silently dropped.
Publish-Subscribe Example
Start NATS locally:
docker run --rm --name nats-server -p 4222:4222 nats:latestThen run code like this:
open Core
open Async
let main () =
let uri = Uri.of_string "nats://127.0.0.1:4222" in
Nats_client_async.connect (Some uri)
>>= fun client ->
Monitor.protect
~finally:(fun () -> Nats_client_async.close client)
(fun () ->
Nats_client_async.subscribe client ~subject:"greet.*" ()
>>= function
| Error error -> Error.raise error
| Ok subscription ->
List.iter [ "greet.sue"; "greet.bob"; "greet.pam" ] ~f:(fun subject ->
Nats_client_async.publish client ~subject "hello");
Pipe.read subscription.messages
>>= function
| `Eof -> Deferred.unit
| `Ok message ->
printf "'%s' received on %s\n"
message.Nats_client.Protocol.payload
message.subject;
Deferred.unit)
let () = Thread_safe.block_on_async_exn mainThere is also a runnable version in examples/natsbyexample/publish_subscribe.ml.
Quick Start With Docker
Start a local NATS server with Docker:
docker run --rm --name nats-server -p 4222:4222 nats:latestIn another shell, build or run the examples from this repo. All examples default to nats://127.0.0.1:4222, so you do not need to set NATS_URL unless you want a different server.
Examples
Build the example executables with:
dune build examples/protocol_demo.exe examples/publish_json.exe examples/request_reply.exe
dune build examples/natsbyexample/publish_subscribe.exe
dune build examples/natsbyexample/request_reply.exe
dune build examples/natsbyexample/json_for_message_payloads.exeRun them against the Docker NATS server:
dune exec ./examples/protocol_demo.exe
dune exec ./examples/publish_json.exe
dune exec ./examples/request_reply.exe
dune exec ./examples/natsbyexample/publish_subscribe.exe
dune exec ./examples/natsbyexample/request_reply.exe
dune exec ./examples/natsbyexample/json_for_message_payloads.exeThe examples cover:
- protocol framing and HPUB encoding
- JSON publishing with headers
- request/reply round trips
- a
natsbyexampledirectory with publish/subscribe, request/reply, and JSON payload examples
To run against another server, set NATS_URL, for example:
NATS_URL=nats://demo.nats.io:4222 dune exec ./examples/publish_json.exeRelease Flow
The intended release path is PR-based:
- Each user-facing PR adds a fragment under
.changes/with apatch,minor, ormajorheader. - The
release-pr.ymlworkflow aggregates those fragments intoCHANGES.mdand opens or updates arelease: vX.Y.ZPR. - Merging that release PR automatically creates and pushes the
vX.Y.Ztag from the merge commit. - The tag workflow immediately dispatches
publish.ymlfor that exact tag. This is required because tags created by a GitHub Actions workflow withGITHUB_TOKENdo not trigger downstreampushworkflows. - The
publish.ymlworkflow checks out the tag, creates the GitHub release withdune-release publish, and submits the package toopam-repositorywithdune-release opam submit. - The repo must have an
OPAM_PUBLISH_GH_TOKENsecret configured for theopam-repositorysubmission step. - After the
opam-repositoryPR is merged, users can install the packages withopam install.
License
MIT. See LICENSE.