ackcursor

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package ackcursor is the durable, acknowledgement-gated cursor behind every at-least-once delivery of an ordered, hash-chained row stream: federation's audit forwarder today, the per-run spool replay over the runner stream and acknowledged SIEM delivery next. The cursor moves only after the receiver acknowledges; a re-sent row is recognised by seq + row hash (a local table reset can reuse a seq, so the position keeps both).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cursor

type Cursor[T any] struct {
	Source Source[T]
	Sink   Sink[T]
	Store  Store
	// Key reads a row's seq and hash.
	Key func(T) Pos
	// Batch is the most rows delivered per Step.
	Batch int
	// OnReset is called, before the position is cleared, when the row at the
	// cursor is gone or changed; its argument is the position that failed.
	OnReset func(Pos)
	// contains filtered or unexported fields
}

Cursor runs the batch loop. Not safe for concurrent use.

func (*Cursor[T]) Load

func (c *Cursor[T]) Load(ctx context.Context) error

Load reads the durable position.

func (*Cursor[T]) Pos

func (c *Cursor[T]) Pos() Pos

Pos is the last acknowledged position.

func (*Cursor[T]) Step

func (c *Cursor[T]) Step(ctx context.Context) (more bool, err error)

Step delivers the next batch and advances the position past what was acknowledged. more is true when the batch was full, so the caller should step again without waiting. On error the position is unchanged, except that a reset already made durable stays reset.

The row at the position and the batch after it come from one read. If that row is gone or carries another hash the stream was reset: rows after it would link to nothing the receiver holds, so Step starts over from the beginning (the receiver skips what it already holds).

type Pos

type Pos struct {
	Seq  int64
	Hash string
}

Pos is a position in the stream: the seq of the last acknowledged row and that row's hash. The zero Pos is the start of the stream.

type Sink

type Sink[T any] interface {
	Deliver(ctx context.Context, rows []T) (ackSeq int64, err error)
}

Sink delivers one batch. rows is empty when there is nothing to send (a sink with a liveness signal sends it then). It returns the highest seq the receiver acknowledged; the cursor never moves past the rows read or backwards, so a sink that skips rows it cannot send returns the last seq of the batch.

type Source

type Source[T any] interface {
	// After returns up to limit rows with seq strictly greater than seq.
	After(ctx context.Context, seq int64, limit int) ([]T, error)
}

Source reads rows in ascending seq order.

type Store

type Store interface {
	Get(ctx context.Context) (Pos, error)
	Set(ctx context.Context, p Pos) error
}

Store persists the position durably.

Jump to

Keyboard shortcuts

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