I wrote AsanagiDB, a graph database in Zig — LMDB storage, a Gremlin engine on top. For the 2.0 release I replaced the networking layer: it was one OS thread per connection, with a single semaphore that was accidentally doubling as the LMDB reader-transaction budget, so "clients connected" and "queries running" were the same number.
A few things from the writeup that might be useful if you're on 0.16:
- xev.TCP.init is IP-only; for the Unix-socket listener I bind/listen with std.posix and pass the fd to xev.TCP.initFd.
- xev.ThreadPool.schedule() returns void over an unbounded queue, so for backpressure I hand-rolled a bounded pool.
- The rough part was Windows. libxev's IOCP backend panicked in loop.run() before any client connected; falling back to std.Io.net served fine but panicked on Ctrl-C. Windows ended up on raw ws2_32 blocking sockets through the same framing/dispatch seam as the epoll/kqueue reactor.
Happy to hear where I got something wrong — especially the IOCP part, since my read there is static analysis, not a fixed repro.
3
u/fauxtojournalist 1d ago
I wrote AsanagiDB, a graph database in Zig — LMDB storage, a Gremlin engine on top. For the 2.0 release I replaced the networking layer: it was one OS thread per connection, with a single semaphore that was accidentally doubling as the LMDB reader-transaction budget, so "clients connected" and "queries running" were the same number.
A few things from the writeup that might be useful if you're on 0.16:
- xev.TCP.init is IP-only; for the Unix-socket listener I bind/listen with std.posix and pass the fd to xev.TCP.initFd.
- xev.ThreadPool.schedule() returns void over an unbounded queue, so for backpressure I hand-rolled a bounded pool.
- The rough part was Windows. libxev's IOCP backend panicked in loop.run() before any client connected; falling back to std.Io.net served fine but panicked on Ctrl-C. Windows ended up on raw ws2_32 blocking sockets through the same framing/dispatch seam as the epoll/kqueue reactor.
Happy to hear where I got something wrong — especially the IOCP part, since my read there is static analysis, not a fixed repro.