sender

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package sender turns buffered reports and pending events into ingest requests and drives the retry matrix. One batch is held across all its retries so its idempotency_key stays stable (server-side report dedupe), while sent_at is refreshed on every attempt so a retried batch is not read as clock skew. On a 202 the batch's reports and events are removed from the buffer and queue (remove-on-202, at-least-once). The four outcomes map straight from the status code: 202 succeeds, 429/404/5xx back off, the terminal 4xx (400/413/422) discards the poison batch, and 401/403/409 quarantine without wiping.

Index

Constants

View Source
const (
	DefaultBaseBackoff = 2 * time.Second
	DefaultCapBackoff  = 10 * time.Minute
	// DefaultQuarantineFloor is the minimum wait after a persistent 401. The
	// agent never hammers and never wipes: it backs off long and keeps its data,
	// so a re-enroll or an external token rotation can recover it.
	DefaultQuarantineFloor = 5 * time.Minute
)

Backoff parameters: full-jitter exponential backoff from a 2s base to a 10min cap for retryable outcomes.

Variables

This section is empty.

Functions

func MetaDigest added in v0.5.0

func MetaDigest(meta map[string]string) string

MetaDigest fingerprints a host profile for change detection: sorted key=value pairs hashed, volatile keys dropped, ram_total_bytes compared in whole GiB.

The GiB rounding is not cosmetic. MemTotal is derived from totalram_pages, and a balloon driver (virtio_balloon on KVM/Proxmox, hv_balloon on Hyper-V) hands pages back and forth at runtime, so a ballooned guest reports a MemTotal that drifts by tens of MiB all day long. Nobody resizes a VM by less than a gigabyte, so whole GiB keeps every real change and drops the entire balloon noise floor.

Exported so the wiring that feeds SetMeta can be tested against the same key the sender compares on.

Types

type Options

type Options struct {
	Client       *http.Client
	URL          string
	TokenFn      func() string
	InstanceID   string
	AgentVersion string
	Clock        platform.Clock
	Buffer       *buffer.Ring
	Events       *event.Queue
	Config       func() *config.Config
	Emitter      event.Emitter
	NewID        func() string // fresh UUIDv4 for idempotency keys
	Log          *slog.Logger
	// Fingerprint is attached to batches until the first 202 (and re-attached
	// when it changes). May be nil.
	Fingerprint map[string]string
	// Meta is the INITIAL host profile (hostinfo.Meta). It decorates the first report
	// of every batch until a batch that carried it gets a 202 - delivery-confirmed,
	// unlike the old assemble-time flag, which lost the profile for the whole
	// process lifetime when the bootstrap report was evicted from the ring
	// during a long initial ingest outage. May be nil.
	//
	// After construction the profile is owned by the Sender: hand a re-read profile
	// to SetMeta, which re-arms delivery only when it actually differs.
	Meta map[string]string
	// OnConfigVersion is called when a 202 advertises a newer config version.
	OnConfigVersion func(v uint32)

	// Tuning (zero uses defaults).
	BaseBackoff     time.Duration
	CapBackoff      time.Duration
	QuarantineFloor time.Duration
	Jitter          jitterFn
}

Options configures a Sender. Buffer, Events, Config, Clock, URL, TokenFn and InstanceID are required; the rest have defaults.

type Sender

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

Sender drives delivery.

func New

func New(opt Options) (*Sender, error)

New builds a Sender.

func (*Sender) Close

func (s *Sender) Close()

Close releases the encoder.

func (*Sender) Run

func (s *Sender) Run(ctx context.Context)

Run drives delivery until ctx is done. It holds a batch across retries so the idempotency key is stable, and only releases it on a terminal outcome (202 or a discard). On ctx cancellation any in-flight reports and events stay in the buffer and queue for the exit spool.

func (*Sender) SetMeta added in v0.5.0

func (s *Sender) SetMeta(meta map[string]string)

SetMeta installs a freshly collected host profile.

The wire contract sends meta "only on change plus the first report after start" (SERVER-AGENT.md 4.1), so this is the "on change" half. An unchanged profile is a complete no-op: neither the stored map nor the delivery flag move, and the next batch stays profile-free. A changed profile re-arms the attach flag, so the next batch carries it and mark-after-202 confirms it exactly like the bootstrap profile.

A restart needs no special case: a fresh Sender starts with metaSent false, so the first report of every process life carries the profile whether it changed or not.

func (*Sender) Wake

func (s *Sender) Wake()

Wake nudges the delivery loop to drain now (called after the collect loop enqueues a report). It never blocks.

Jump to

Keyboard shortcuts

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