NNQ — pure Ruby NNG on Async

CI Gem Version License: ISC Ruby

NNQ is a pure-Ruby implementation of nanomsg's Scalability Protocols (SP), wire-compatible with libnng. It is the nng-philosophy sibling of omq (pure-Ruby ZeroMQ).

Status: pre-alpha. v0.0.1 implements push0/pull0 over TCP only. See PLAN.md for the design and roadmap.

Why a pure-Ruby NNG?

  • No native deps. Same stack as omq: async, io-stream, protocol-sp. No C extension, no FFI.
  • Faster than libnng for the multi-fiber case (target: 10–25×). libnng's per-message aio model leaves all the throughput of write coalescing on the table.
  • Async-native. Wrap in Async{}, no background thread for users who already run a reactor.

Quickstart

require "nnq"
require "async"

Async do
  pull = NNQ::PULL.bind("tcp://127.0.0.1:5570")
  push = NNQ::PUSH.connect("tcp://127.0.0.1:5570")

  push.send("hello")
  puts pull.receive  # => "hello"

  push.close
  pull.close
end

The "no HWM" philosophy

NNQ has no high-water mark. Backpressure comes only from the kernel socket buffer. Concurrent senders are coalesced into one writev syscall by NNQ::Send::Staging, which keeps a tiny in-memory aggregation point that exists only during the moments when the drainer fiber is parked on wait_writable. See lib/nnq/send/staging.rb for the full discussion.

Cancellation

Async::Task is the aio. To cancel an in-flight send, stop the task that called send. The semantics match libnng's nng_aio_cancel exactly: best-effort, may lose the race if the message is already on the wire.