papdashboard

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package papdashboard forwards taskqueue facts to a PapDashboard instance: a dead-lettered task becomes an alert (alert.triggered), and if the task later completes (e.g. after tq dlq --rescue), that alert is resolved (alert.resolved). The bridge consumes the same journal seam as tq tail, so it works against any Store and never mutates queue state — its one write is its own read cursor in the watermarks table.

Delivery semantics: at-least-once. The journal watermark only advances after PapDashboard accepts a fact (2xx, or a permanent 4xx which is logged then accepted), and the Idempotency-Key header (derived from the fact sequence) makes retries safe. Across restarts the bridge resumes from its persisted checkpoint instead of the journal head: incidents that fired while the bridge was down are replayed with identical idempotency keys, and Config.FromSeq overrides the checkpoint for an ops-initiated replay. A completion resolves the alert of any task that ever dead-lettered — the correlation is derived from the task's own fact trail, not process memory, so it survives restarts too. With no WatermarkStore configured the bridge keeps the legacy volatile behavior (head start, nothing persisted).

Index

Constants

View Source
const DefaultPollInterval = 5 * time.Second

DefaultPollInterval is how often the journal is tailed.

View Source
const SourceApp = "go-taskqueue"

SourceApp is the default sourceApp stamped on ingested alerts.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bridge

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

Bridge tails the taskqueue journal and mirrors dead-letter incidents into PapDashboard alerts.

func New

func New(store FactSource, checkpoints WatermarkStore, cfg Config) *Bridge

New builds a Bridge. checkpoints persists the journal cursor across restarts (queue.Store satisfies WatermarkStore); nil keeps the legacy volatile behavior. Call Run to start tailing.

func (*Bridge) Run

func (b *Bridge) Run(ctx context.Context) error

Run tails the journal until ctx is cancelled. Facts are forwarded in Seq order; the watermark advances past a fact only when it is accepted (2xx) or permanently rejected (4xx) — transient failures retry on the next poll. Each drained batch checkpoints the cursor AFTER the last accepted fact, and a failed checkpoint stops the drain exactly like a failed forward: the next poll retries from the last persisted seq, so delivery stays at-least-once and never degrades to at-most-once.

type Config

type Config struct {
	// Endpoint is PapDashboard's base URL, e.g. http://localhost:8080.
	Endpoint string
	// APIKey is the Bearer token protecting PapDashboard's ingest route.
	APIKey string
	// SourceApp overrides the default sourceApp ("go-taskqueue").
	SourceApp string
	// Severity is the alert severity for dead-lettered tasks.
	// Default "critical".
	Severity string
	// BudgetSeverity is the alert severity for budget exhaustion.
	// Default "warning".
	BudgetSeverity string
	// DailyBudget, when > 0, mirrors the agent pool's --daily-budget: the
	// day the pool enqueues its Nth task, a "daily budget exhausted" alert
	// fires once (resolved automatically when the next day's first task is
	// enqueued). 0 disables budget telemetry.
	DailyBudget int
	// PollInterval tails the journal this often. Default 5s.
	PollInterval time.Duration
	// FromSeq, when set, starts forwarding AFTER this fact sequence instead
	// of the journal head (replay mode).
	FromSeq *int64
	// Client overrides the HTTP client.
	Client *http.Client
	// Logger receives bridge diagnostics. Default slog.Default().
	Logger *slog.Logger
}

Config controls a Bridge. Endpoint and APIKey come from the PapDashboard deployment (its public /api/ingest route and the PAP_API_KEY value).

type FactSource

type FactSource interface {
	Facts(ctx context.Context, after int64, limit int) ([]journal.Fact, error)
	HeadSeq(ctx context.Context) (int64, error)
	Get(ctx context.Context, id task.ID) (task.Task, error)
	// FactsForTask reads one task's own fact trail — the durable answer to
	// "did this task ever dead-letter?" (a read, so the no-mutation
	// contract holds).
	FactsForTask(ctx context.Context, id string, limit int) ([]journal.Fact, error)
}

FactSource is the read-only slice of queue.Store the bridge needs.

type WatermarkStore added in v0.2.0

type WatermarkStore interface {
	Watermark(ctx context.Context, consumer string) (seq int64, exists bool, err error)
	SaveWatermark(ctx context.Context, consumer string, seq int64) error
}

WatermarkStore persists the bridge's journal cursor across restarts. queue.Store satisfies it; tests fake it in-process. It is deliberately separate from FactSource so the read contract stays read-only: the bridge writes only its own consumer progress, never task or fact state.

Jump to

Keyboard shortcuts

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