nntpserver

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package nntpserver provides an in-process NNTP server that speaks enough of the wire protocol for a real *nntppool.Client to connect, authenticate, pipeline commands, and fetch yEnc article bodies.

It exists because the questions "how much does a STAT sweep cost a live stream" and "does the priority lane actually protect playback" cannot be answered with a client-level fake. Those behaviours live inside nntppool's per-connection scheduler — the shared inflight semaphore, the separate body semaphore, the priority/normal request channels, and the strict FIFO reply ordering of a single NNTP connection. internal/testsupport/fakepool replaces that scheduler wholesale, so it cannot observe any of it.

Wire fidelity

The one property that matters is pipelining with in-order replies: a client may have many commands outstanding on one connection, the server may work on them concurrently, but responses MUST come back in the order the commands arrived. Each connection therefore runs a reader that enqueues a response future per command and a writer that drains those futures in order. Without this, head-of-line effects — a STAT queued behind a 750 KB body, a priority BODY queued behind a hundred STATs — silently disappear.

Timing model

RTT (± jitter) is applied per command as time-to-first-byte, concurrently across the connection's outstanding commands. Body payload bytes are then written by the single writer goroutine at BandwidthPerConn, which models one wire shared by everything in flight on that connection.

All exported methods are safe for concurrent use.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// RTT is the time-to-first-byte applied to every command.
	RTT time.Duration
	// Jitter is the maximum symmetric deviation from RTT (uniform in
	// [-Jitter, +Jitter]). Zero makes latency deterministic.
	Jitter time.Duration
	// BandwidthPerConn throttles body payload bytes per connection, in bytes
	// per second. Zero disables the throttle.
	BandwidthPerConn int64
	// AggregateBandwidth caps total body payload bytes across ALL connections,
	// in bytes per second. Zero disables it.
	//
	// Without this, N connections each throttled to R sum to N×R, which no real
	// link does — and a harness that lets 100 connections reach 800 MB/s draws
	// exactly the wrong conclusions about whether spending connections on
	// latency costs throughput. Set it to the deployment's actual link rate.
	AggregateBandwidth int64
	// ArticleSize is the decoded size of the single article every BODY
	// request returns.
	ArticleSize int
	// Missing is the set of message-ids answered with 430 instead of a hit.
	// A nil map means every id exists.
	Missing map[string]struct{}
	// RequireAuth makes the server reject commands until AUTHINFO succeeds.
	RequireAuth bool
}

Config describes the simulated provider.

type Counters

type Counters struct {
	Conns        int64
	Stats        int64
	StatMisses   int64
	Bodies       int64
	BytesWritten int64
	PeakInflight int64 // highest number of concurrently-computing commands on any one connection
	UnknownCmds  int64
}

Counters is a snapshot of what the server has served.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a running fake NNTP provider.

func New

func New(cfg Config) (*Server, error)

New starts a server on a loopback port. Close it when done.

func (*Server) Addr

func (s *Server) Addr() string

Addr is the server's listening address.

func (*Server) Close

func (s *Server) Close() error

Close stops the listener and waits for connection goroutines to finish.

func (*Server) Counters

func (s *Server) Counters() Counters

Counters snapshots what has been served so far.

func (*Server) Dial

func (s *Server) Dial(ctx context.Context) (net.Conn, error)

Dial satisfies nntppool.ConnFactory.

func (*Server) ResetPeakInflight

func (s *Server) ResetPeakInflight()

ResetPeakInflight zeroes the pipeline-depth high-water mark, so a benchmark can measure its own window rather than inheriting a warm-up burst.

Jump to

Keyboard shortcuts

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