I’ve been working on a NATS client library over the last few weeks. It’s now at the point that I’m happy to share it with others, but definitely not production ready at this point. It’s very much based on the official NATS Go and C libraries, but using Zig idioms. NATS Core should work well, JetStream is not as well tested yet. The goal is to have feature parity with the official client libraries. And the API is also very similar, so if you follow the official docs, the functions names and options they use are named the same here.
I know there are a couple of other libraries for NATS, but they are either abandoned and/or their API is really different from the official one and/or I didn’t trust the code when looking at it.
For now I’m using blocking sockets, would definitely like to switch to non-blocking sockets an an IO loop (maybe using libxev), but that will have to wait a little bit and it’s not as important as threads will be needed for message dispatching anyway.
Hey, I’ll be honest, I saw your library before I started and I didn’t like it. Just the naming put me off, but then I looked further and saw that there is no reconnection handling, the parser is significantly less efficient than the state machine in the official libraries and similar things.
Personally I don’t like automatic re-connection provided by client libraries. It may create real mess in the flow. Bit it is my personal experience/opinion. So it was by intent
Also I don’t use any C library - just native Zig for fun
And sorry offthetopic - may be you know how to activate log.debug in Release* mode ?
The reconnection is an important part of the libraries, because you can dynamically extend the cluster, the clients will immediately discover new nodes to connect to via the INFO message and that enables much a better HA solution.
For the logging, I have log level in std_options set to debug and my custom log handler filter what gets printed based on runtime parameters.
Exact now I found the root of the problem:
there are two addTest in my build.zig:
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const lib_unit_tests = b.addTest(.{
.root_source_file = b.path("src/all_tests.zig"),
.target = target,
.optimize = optimize,
.single_threaded = false,
.error_tracing = true,
.test_runner = .{ .path = b.path("testRunner.zig"), .mode = .simple },
});
NATS is much easier in this regard, because it has proper specs, and it’s done in layers, so the complexity is fairly isolated, plus it has multiple client libraries that can be for cross-referencing.
The whole project started as an experiment how far can I get if I give Claude Code enough reference material. I wouldn’t even attempt doing this, if I didn’t have prior good experience with these AI tools I mainly just focused on the high level parts, how to design the API in Zig, the low level details were extracted and translated by Claude Code for me. I started with a clone of the C library and then started diverging as I could do more and more things the Zig way.
I’ve now updated the NATS client to use my zio runtime. It’s much nicer to be able to use coroutines when working with queues. Plus, it can now run single-threaded and it’s more responsive that way.
I’m sorry if anyone was using the threaded version before, the library will be migrated to std.Io once 0.16 is released, for now it’s zio only.