nats

package
v2.36.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultClientMaxPendingBytes = 512 * 1024 * 1024

DefaultClientMaxPendingBytes is the pending byte limit applied via SetPendingLimits to each coalesced *natsgo.Subscription when PendingLimits.Bytes is zero. Unlike DefaultServerMaxPendingBytes, which bounds the server-side outbound buffer for a whole connection, this bounds the nats.go client's per-subscription pending buffer: messages the client has received from the server but the subscription's async message handler has not yet dispatched. When that handler falls behind and the buffer overflows, NATS marks the subscription a slow consumer and drops messages, which the package surfaces as pubsub.ErrDroppedMessages.

View Source
const DefaultServerMaxPendingBytes int64 = 512 << 20

DefaultServerMaxPendingBytes caps how many bytes the embedded NATS server will hold in memory for a single client connection while waiting to write them out to that connection. Each message the server needs to deliver to a connection is queued in that connection's outbound buffer until the socket can accept it; if the consumer reads slower than messages arrive, the buffer grows. When it exceeds this cap, NATS declares the connection a slow consumer and drops messages rather than buffer without bound.

The connection that fills this buffer in practice is the subscribe connection: the server writes every message bound for a replica's local subscribers out over its subscribe connection pool, which defaults to a single connection. In a cluster, cross-node fan-out therefore concentrates all of a replica's inbound deliveries on that one connection's outbound buffer. Benchmarking high-fanout cluster workloads (10 subjects, 10 publishers, 50 subscribers) showed the 128 MiB default overflowing and dropping 10-15% of deliveries, while 256 MiB and above dropped none; 512 MiB is chosen for headroom.

This is a ceiling, not a reservation: the buffer grows only with actual backlog, so a connection that keeps up holds nearly nothing and raising the cap costs memory only during the overload bursts it absorbs.

Variables

This section is empty.

Functions

This section is empty.

Types

type NopPeerFetcher

type NopPeerFetcher struct{}

func (NopPeerFetcher) FetchNATSPeers

func (NopPeerFetcher) FetchNATSPeers() []string

func (NopPeerFetcher) SetSelfNATSPort

func (NopPeerFetcher) SetSelfNATSPort(int32)

type Options

type Options struct {
	// MaxPayload is the NATS max payload. Zero means server default.
	MaxPayload int32

	// MaxPending is the per-client outbound pending byte budget on the
	// embedded server. Zero or negative means the package default,
	// 128 MiB.
	MaxPending int64

	// PendingLimits configures per-subscription NATS pending limits.
	// Positive Msgs also sets local listener queue capacity.
	// Zero fields use package defaults: Msgs -1 and Bytes 512 MiB.
	PendingLimits PendingLimits

	// ReconnectWait controls client reconnect delay. Zero keeps the
	// NATS default.
	ReconnectWait time.Duration

	// InProcess, when true, uses nats.InProcessServer instead of TCP
	// loopback. Intended for benchmarks and tests.
	InProcess bool

	// PublishConns is the number of publisher connections. Each Publish
	// is routed by a stable hash of the subject. Zero or negative means 1.
	PublishConns int

	// SubscribeConns is the number of subscriber connections. Each
	// shared subscription is pinned to one connection by a stable hash
	// of its subject. Zero or negative means 1.
	SubscribeConns int

	// ClusterHost is the embedded NATS route listener host. Empty means
	// all interfaces when cluster mode is enabled.
	ClusterHost string

	// ClusterPort is the embedded NATS route listener port. Zero means
	// 6222 when cluster mode is enabled. NATS `server.RANDOM_PORT` can be
	// used to select a random port.
	ClusterPort int

	// ClusterAuthToken is the shared route authentication token for
	// clustered embedded NATS servers. Empty disables route auth.
	ClusterAuthToken string

	// ClusterCA enables mutual TLS on the cluster route listener. When set
	// (and cluster mode is enabled), each replica mints an ephemeral leaf
	// certificate from the active nats_ca CA and verifies peers against the
	// CA fetched from this cache on each handshake. Nil keeps routes
	// plaintext (token auth only). cryptokeys.SigningKeycache satisfies this.
	//
	// The leaf's IP SAN (and the accept-side source binding) is this replica's
	// ClusterHost, so ClusterHost must be an IP for mTLS to activate.
	ClusterCA cryptokeys.SigningKeycache

	// PeerFetcher provides the current set of peer route addresses.
	// RefreshPeers uses it to update the configured cluster routes.
	PeerFetcher PeerFetcher

	// RoutePoolSize is the NATS route pool size. Zero means the package
	// default when cluster mode is enabled.
	RoutePoolSize int
	// contains filtered or unexported fields
}

Options configures the embedded NATS Pubsub.

type PeerFetcher

type PeerFetcher interface {
	FetchNATSPeers() []string
	SetSelfNATSPort(port int32)
}

PeerFetcher fetches NATS peer route addresses.

type PendingLimits

type PendingLimits struct {
	// Msgs is the per-subscription pending message limit. Zero or
	// negative disables the message limit, leaving the byte limit
	// (PendingLimits.Bytes) as the only per-subscription bound.
	Msgs int

	// Bytes is the per-subscription pending byte limit.
	// Zero uses the package default. Negative disables this limit.
	Bytes int
}

PendingLimits configures per-subscription NATS pending limits set via SetPendingLimits on each *natsgo.Subscription.

type Pubsub

type Pubsub struct {
	Server *natsserver.Server
	// contains filtered or unexported fields
}

Pubsub is an embedded NATS-backed implementation of pubsub.Pubsub.

Each Pubsub owns one embedded server, a pool of publisher *natsgo.Conns (Options.PublishConns) and a pool of subscriber *natsgo.Conns (Options.SubscribeConns). Publishes and shared subscriptions are pinned to a connection by a stable hash of the subject, so same-subject traffic preserves per-subject ordering and every local subscriber for a subject coalesces onto one underlying *natsgo.Subscription.

func New

func New(ctx context.Context, logger slog.Logger, opts Options) (pubSub *Pubsub, retErr error)

New creates an embedded NATS Pubsub. The returned *Pubsub owns the embedded server and the publisher and subscriber connection pools. Close shuts down all owned resources.

func (*Pubsub) Close

func (p *Pubsub) Close() error

Close stops local delivery and shuts down the Pubsub. It is idempotent. Close does not drain queued listener messages.

func (*Pubsub) Collect

func (p *Pubsub) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector. The subscriber and event gauges are maintained as atomic counters by metrics, so Collect does not lock the Pubsub.

func (*Pubsub) Describe

func (p *Pubsub) Describe(descs chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

func (*Pubsub) Flush

func (p *Pubsub) Flush() error

Flush blocks until every publisher connection has flushed buffered publishes to the embedded server. Returns the first error encountered; remaining connections are still flushed.

func (*Pubsub) Publish

func (p *Pubsub) Publish(event string, message []byte) error

Publish publishes a message under the given event name. The publisher connection is selected by a stable hash of the subject so same-subject publishes preserve per-subject ordering.

func (*Pubsub) RefreshPeers

func (p *Pubsub) RefreshPeers()

RefreshPeers signals the peer refresh worker to fetch and apply the latest peer route addresses. Multiple pending refreshes are coalesced.

func (*Pubsub) SetCACache added in v2.36.0

func (p *Pubsub) SetCACache(ca cryptokeys.SigningKeycache)

SetCACache swaps the cluster mTLS CA cache, then triggers a peer refresh so any route blocked by the previous (for example noop) cache is retried. It is a no-op unless the pubsub was started with cluster TLS enabled (Options.ClusterCA set, which installs the TLS callbacks). Passing a noop cache reverts to no mTLS: new route handshakes can no longer mint a leaf and will not form. The leaf IP SAN is fixed at construction from ClusterHost, so it is not passed here. It logs the resulting mTLS state.

func (*Pubsub) SetPeerFetcher

func (p *Pubsub) SetPeerFetcher(fetcher PeerFetcher)

SetPeerFetcher replaces the peer fetcher used by RefreshPeers and triggers an immediate peer refresh. Passing nil disables peering.

func (*Pubsub) Subscribe

func (p *Pubsub) Subscribe(event string, listener pubsub.Listener) (cancel func(), err error)

Subscribe subscribes a Listener to the given event name. Errors such as ErrDroppedMessages are silently ignored, mirroring the legacy pubsub Listener semantics.

func (*Pubsub) SubscribeWithErr

func (p *Pubsub) SubscribeWithErr(event string, listener pubsub.ListenerWithErr) (cancel func(), err error)

SubscribeWithErr subscribes a ListenerWithErr to the given event name. The listener also receives error deliveries such as pubsub.ErrDroppedMessages. Multiple local subscribers on the same event share a single underlying *natsgo.Subscription with per-listener bounded inboxes so a slow listener cannot block its peers.

Directories

Path Synopsis
Command natsbench benchmarks Coder's NATS-backed pubsub (github.com/coder/coder/v2/coderd/x/nats) under high fan-out load.
Command natsbench benchmarks Coder's NATS-backed pubsub (github.com/coder/coder/v2/coderd/x/nats) under high fan-out load.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL