kafka

package
v0.19.1237 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: AGPL-3.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const EnvelopeVersion = 1

Variables

This section is empty.

Functions

func DedupToken

func DedupToken(topic string, partition int32, first, last int64) string

DedupToken builds a stable per-batch token from a partition's offset range, suitable for a ClickHouse insert_deduplication_token.

func Wrap

func Wrap(source, typ string, payload any) ([]byte, error)

Wrap marshals payload into a versioned envelope stamped with source and type.

Types

type Config

type Config struct {
	Brokers          []string
	ClientID         string
	SecurityProtocol string

	// TLSCAPath is the bundle used to verify brokers; empty uses system roots.
	TLSCAPath string
	// TLSCertPath and TLSKeyPath enable mTLS and must be set together.
	TLSCertPath string
	TLSKeyPath  string

	// ProduceTimeout bounds a synchronous produce. franz-go retries a buffered
	// record effectively forever by default, so without a bound a broker outage
	// would block a caller waiting on the ack indefinitely. Only applies to the
	// sync path; async producers never wait.
	ProduceTimeout time.Duration
}

Config is the Kafka client configuration shared by the producer and consumer.

type Consumer

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

Consumer runs a consumer-group poll loop and dispatches each partition's records to a Handler, committing offsets only after the handler succeeds.

func NewConsumer

func NewConsumer(cfg Config, ccfg ConsumerConfig, handler Handler, l *zap.Logger) (*Consumer, error)

func (*Consumer) Start

func (c *Consumer) Start()

func (*Consumer) Stop

func (c *Consumer) Stop()

func (*Consumer) Stuck

func (c *Consumer) Stuck(max time.Duration) (time.Duration, bool)

Stuck reports whether a handler call has been running longer than max, and for how long. Intended for a liveness check, not the hot path: a handler call is expected to be bounded by its own timeout (e.g. a ClickHouse write deadline), so this only trips on a genuine hang that bound failed to catch.

type ConsumerConfig

type ConsumerConfig struct {
	Group        string
	Topics       []string
	FetchMaxWait time.Duration
	// FetchMinBytes is the batch floor, the rest are ceilings. Worst-case buffered
	// bytes is
	//
	//	min(FetchMaxBytes, partitionsOnBroker*FetchMaxPartitionBytes) * MaxConcurrentFetches
	//
	// so partitions-per-pod — replica count, not topic size — is usually what
	// actually bounds a consumer's memory.
	FetchMinBytes          int32
	FetchMaxBytes          int32
	FetchMaxPartitionBytes int32
	MaxConcurrentFetches   int
}

type Envelope

type Envelope struct {
	Version    int             `json:"version"`
	Type       string          `json:"type"`
	ProducedAt time.Time       `json:"produced_at"`
	Source     string          `json:"source"`
	Payload    json.RawMessage `json:"payload"`
}

Envelope is the versioned wrapper every Kafka message uses. Payload is left as raw JSON so consumers decode it by Type/Version rather than the producer and consumer sharing a compiled payload type.

func Unwrap

func Unwrap(b []byte) (Envelope, error)

Unwrap parses an envelope. The caller unmarshals Payload based on Type/Version.

Rejects a version newer than EnvelopeVersion, not merely a different one: an older envelope must still pass, since a rolling deploy can have not-yet-restarted producers still writing it while consumers have already upgraded to accept a new one. Bumping EnvelopeVersion is an expand-then-contract change — consumers accept the new version first, then producers start writing it — so an exact-match check would reject the new version everywhere until every consumer had rolled, which defeats the expand step entirely.

type Handler

type Handler func(ctx context.Context, partition int32, records []*kgo.Record) error

Handler processes one partition's batch. Returning nil commits the batch; returning an error leaves it uncommitted for redelivery.

type Message

type Message struct {
	Key     string
	Payload any
}

Message is one record for a batch produce.

type Producer

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

Producer wraps a franz-go client. A disabled producer is a no-op, letting callers keep a legacy fallback path so downstream writes never depend on Kafka being present.

Two produce modes, chosen by what the caller's current write does:

  • Produce / ProduceEnvelope are fire-and-forget. Correct where the existing path is already lossy — heartbeats buffer in memory and flush on a 5s ticker, so a crash already drops a few seconds of them and nothing cares.
  • ProduceEnvelopesSync waits for the acks. Correct where the existing path is synchronously durable, as the OTLP log write is: it blocks on a ClickHouse insert before returning 201, so producing fire-and-forget instead would hand the caller a success for records that live only in a process buffer.

func DisabledProducer

func DisabledProducer(l *zap.Logger, mw metrics.Writer) *Producer

func NewProducer

func NewProducer(cfg Config, l *zap.Logger, mw metrics.Writer) (*Producer, error)

func (*Producer) Close

func (p *Producer) Close()

func (*Producer) Enabled

func (p *Producer) Enabled() bool

func (*Producer) Flush

func (p *Producer) Flush(ctx context.Context) error

func (*Producer) Ping

func (p *Producer) Ping(ctx context.Context) error

func (*Producer) Produce

func (p *Producer) Produce(ctx context.Context, topic, key string, value []byte)

Produce sends a single pre-marshaled message. Fire-and-forget: the async callback records metrics and logs on failure, so callers never block on the broker.

func (*Producer) ProduceEnvelope

func (p *Producer) ProduceEnvelope(ctx context.Context, topic, key, typ string, payload any) error

ProduceEnvelope wraps payload in the versioned envelope and produces it. Fire-and-forget; see ProduceEnvelopesSync when the caller needs the ack.

func (*Producer) ProduceEnvelopesSync

func (p *Producer) ProduceEnvelopesSync(ctx context.Context, topic, typ string, msgs []Message) []int

ProduceEnvelopesSync wraps each message and produces the batch, blocking until every record is acked. Acks are already RequiredAcks(AllISRAcks) with idempotence on, so an ack here means the record is on every in-sync replica.

Returns the indices of messages that were NOT acked, so a caller with a fallback can write exactly those rather than re-writing the whole batch and duplicating the ones that succeeded. An empty return means everything is durable in Kafka.

Produces the whole batch in one call rather than looping: ProduceSync enqueues all records, cancels lingering, and waits once, so this costs one round trip's latency instead of N serialized ones.

On timeout the outcome for an in-flight record is genuinely ambiguous. franz-go will not fail a buffered record that has already been sent while producing idempotently, because it cannot know whether the broker applied it. Such a record is reported as failed here — so the caller writes it via the fallback — and may still land in Kafka afterwards. That is an at-least-once choice: a duplicate row is recoverable, a silently dropped log line is not.

Jump to

Keyboard shortcuts

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