notification

package
v1.6.5 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ConnectorInfo

type ConnectorInfo = sink.ConnectorInfo

ConnectorInfo carries resolved connector metadata for template rendering.

type DeliveryCallback

type DeliveryCallback func(result DeliveryResult)

DeliveryCallback is invoked after each dispatch attempt to report delivery results back to the lifecycle processor for status tracking.

type DeliveryResult

type DeliveryResult struct {

	// ID is the canonical sink-status key for this delivery.
	// It matches Request.ShortName() and is used to index
	// per-sink state inside HibernateNotification.Status.SinkStatuses.
	//
	// Format: <sink>|<namespace>/<plan>|<cycle>|<operation>
	ID string

	NotificationRef types.NamespacedName
	SinkName        string
	PlanNamespace   string
	PlanName        string
	CycleID         string
	Operation       string

	// Timestamp is when the dispatch completed.
	Timestamp time.Time

	// Success is true when the notification was delivered without error.
	Success bool

	// Error is the dispatch error, if any. Nil when Success is true.
	Error error

	// States carries sink-specific arbitrary key/value context emitted by sink
	// delivery implementations (for example thread identifiers).
	States map[string]string
}

DeliveryResult reports the outcome of a single notification dispatch.

func FromRequest

func FromRequest(req Request) DeliveryResult

FromRequest pre-fills the identifier fields of a DeliveryResult from a Request.

func (DeliveryResult) At

At sets the completion timestamp.

func (DeliveryResult) WithError

func (r DeliveryResult) WithError(err error) DeliveryResult

WithError marks the result as failed and records the error.

func (DeliveryResult) WithOutcome

func (r DeliveryResult) WithOutcome(success bool, err error) DeliveryResult

WithOutcome sets both the success flag and the error in one call.

func (DeliveryResult) WithStates

func (r DeliveryResult) WithStates(states map[string]string) DeliveryResult

WithStates attaches sink-specific state metadata.

func (DeliveryResult) WithSuccess

func (r DeliveryResult) WithSuccess() DeliveryResult

WithSuccess marks the result as succeeded.

type Dispatcher

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

Dispatcher is a standalone controller-runtime Runnable that processes notification dispatch requests asynchronously. Hook closures submit Requests via Submit, which returns immediately (fire-and-forget). Requests are routed into per-stream FIFO slots managed by keyedworker. Each stream is processed by at most one worker at a time, guaranteeing deterministic ordering for that stream while preserving concurrency across independent streams.

The dispatcher:

  • resolves sink credentials (Secret lookup via informer cache)
  • renders the message via TemplateEngine (built-in defaults or custom ConfigMap templates)
  • sends to the appropriate sink with a per-request timeout
  • records Prometheus metrics (sent/errors/latency/drops)

Dispatch failures are logged and metered but never propagate errors to the caller.

func NewDispatcher

func NewDispatcher(log logr.Logger, c client.Reader, registry *sink.Registry, cfg DispatcherConfig, opts ...DispatcherOption) *Dispatcher

NewDispatcher creates a new NotificationDispatcher. The client should be the cached reader (informer cache) for Secret lookups.

func (*Dispatcher) NeedLeaderElection

func (d *Dispatcher) NeedLeaderElection() bool

NeedLeaderElection returns true — notifications should only fire from the leader.

func (*Dispatcher) Notifier

func (d *Dispatcher) Notifier() Notifier

Notifier returns the Notifier interface backed by this Dispatcher. Consumers (plan processors, state handlers) should depend on this interface rather than on *Dispatcher directly.

func (*Dispatcher) Start

func (d *Dispatcher) Start(ctx context.Context) error

Start implements manager.Runnable. It wires keyed per-stream workers and blocks until ctx is cancelled. During shutdown, new submissions are rejected and active stream workers are given a bounded time window to drain pending per-stream items before Start returns.

func (*Dispatcher) Submit

func (d *Dispatcher) Submit(req Request)

Submit enqueues a dispatch request. It never blocks the caller. Requests are routed into per-stream FIFO slots; if a per-stream buffer is full, the request is dropped by the slot and counted in NotificationDropTotal. After shutdown begins (d.done closed), requests are discarded with a metric.

type DispatcherConfig

type DispatcherConfig struct {
	// ChannelSize is the buffered channel capacity for dispatch requests.
	// Default: 256.
	ChannelSize int

	// DispatchTimeout is the per-sink HTTP call timeout.
	// Default: 5s.
	DispatchTimeout time.Duration

	// WorkerIdleTTL is how long an idle per-stream worker stays alive before exiting.
	// Default: 30m.
	WorkerIdleTTL time.Duration
}

DispatcherConfig holds tuning knobs for the notification Dispatcher. Zero values are replaced with sensible defaults.

type DispatcherOption

type DispatcherOption func(*Dispatcher)

DispatcherOption configures an optional dependency of a Dispatcher.

type Instance

type Instance struct {
	// Notifier is the submit-only interface distributed to plan processors and
	// state handlers — analogous to status.Updater.
	Notifier Notifier

	// Runnable is the controller-runtime Runnable that must be registered via
	// mgr.Add(). It owns the dispatch goroutine pool and channel lifecycle.
	Runnable manager.Runnable
}

Instance represents a notification subsystem instance with its Notifier interface and Runnable dispatcher.

func New

func New(log logr.Logger, cl client.Reader, opts ...Option) Instance

New constructs the notification subsystem instance: sink registry, template engine, and dispatcher. It registers all built-in sink implementations (Slack, Telegram, fake) using a shared retryable HTTP client unless DisableDefaultSinks is specified, builds a TemplateEngine backed by the controller-runtime client, and returns an Instance whose Notifier can be distributed to processors.

This is the single public entry point that hides all notification internals from the setup/wiring layer.

type Notifier

type Notifier interface {
	Submit(req Request)
}

Notifier is the write-facing interface exposed to consumers (state handlers, processors). It intentionally hides all dispatcher and pool internals, mirroring the pattern used by status.Updater.

type Option

type Option func(*config)

Option configures the notification subsystem constructed by New.

func DisableDefaultSinks

func DisableDefaultSinks() Option

DisableDefaultSinks disables the default built-in sink registrations (Slack, Telegram, fake). Combine with WithSink to construct a fully-controlled registry for testing.

func WithDeliveryCallback

func WithDeliveryCallback(cb DeliveryCallback) Option

WithDeliveryCallback registers a callback invoked after each dispatch attempt. Used by the notification lifecycle processor to track per-sink delivery status.

func WithDispatcherConfig

func WithDispatcherConfig(cfg DispatcherConfig) Option

WithDispatcherConfig overrides the default dispatcher configuration.

func WithSink

func WithSink(s sink.Sink) Option

WithSink registers an additional sink implementation into the registry. This is the primary hook for E2E tests to inject a custom in-memory or recording sink without touching production code paths.

type Overflow

type Overflow[T any] struct {
	// contains filtered or unexported fields
}

Overflow is a concurrency-safe, unbounded spillover queue.

It is designed as a companion to a bounded channel: when the channel is full, callers Append items here instead of blocking. A background drainer moves items from the Overflow back into the channel as capacity becomes available.

All methods are safe for concurrent use. The Consume method uses a take-and-return pattern to process items outside the lock without positional-mismatch races.

func (*Overflow[T]) Append

func (o *Overflow[T]) Append(item T)

Append adds an item to the back of the overflow queue.

func (*Overflow[T]) Clear

func (o *Overflow[T]) Clear()

Clear removes all items from the queue.

func (*Overflow[T]) Consume

func (o *Overflow[T]) Consume(fn func(ctx context.Context, item T) bool)

Consume atomically takes ownership of items, processes them outside the lock, and prepends any unconsumed remainder back under the lock.

fn is called for each item in order. If fn returns true the item is consumed and discarded. If fn returns false processing stops; that item and all remaining items are returned to the front of the queue (preserving order for the next call).

Because items are extracted before fn runs, concurrent Append calls do not interfere with the consumed prefix — eliminating the positional-mismatch race that would occur with a snapshot-then-trim approach.

func (*Overflow[T]) Len

func (o *Overflow[T]) Len() int

Len returns the number of items currently in the queue.

func (*Overflow[T]) Range

func (o *Overflow[T]) Range(fn func(T))

Range calls fn for each item while holding the lock. Use for short, non-blocking callbacks only; for potentially blocking work prefer Consume.

func (*Overflow[T]) Set

func (o *Overflow[T]) Set(i int, v T) bool

Set replaces the item at index i. Returns false if i is out of bounds.

func (*Overflow[T]) Snapshot

func (o *Overflow[T]) Snapshot() []T

Snapshot returns a shallow copy of the current items. The caller owns the returned slice; mutations do not affect the queue.

type Payload

type Payload = sink.Payload

Payload carries the notification event data passed to sinks for dispatch.

type PlanInfo

type PlanInfo = sink.PlanInfo

PlanInfo carries plan metadata for the template context.

type Request

type Request struct {
	// Payload carries the notification event data.
	Payload Payload

	// SinkName is the human-readable sink identifier (for logging).
	SinkName string

	// SinkType is the sink provider type (e.g., "slack", "telegram", "webhook").
	SinkType string

	// SecretRef references the Secret containing sink config.
	// If Key is empty, the dispatcher uses a default key.
	SecretRef hibernatorv1alpha1.ObjectKeyReference

	// TemplateRef optionally references a ConfigMap key for custom templates.
	// Nil means use the default template.
	TemplateRef *hibernatorv1alpha1.ObjectKeyReference

	// NotificationRef identifies the HibernateNotification that owns this request.
	// Used by the delivery callback to update per-sink status.
	NotificationRef types.NamespacedName
}

Request represents a single notification request submitted by a hook closure. It contains all data needed by the dispatcher to resolve credentials, render the message, and send it to the sink.

func (Request) ShortName

func (r Request) ShortName() string

ShortName returns the canonical sink-status key for this request.

Format: <sink>|<namespace>/<plan>|<cycle>|<operation>

This key is used to index per-sink delivery state inside HibernateNotification.Status.SinkStatuses.

func (Request) String

func (r Request) String() string

String returns a fully-qualified string that uniquely identifies this request across the entire cluster. It includes the notification reference so that two requests for the same sink/plan/cycle but different HibernateNotification objects do not collide.

Format: <notification>|<sink>|<namespace>/<plan>|<cycle>|<operation>

type Result

type Result = sink.SendResult

Result carries the outcome of a sink Send operation, including any sink-specific metadata.

type TargetInfo

type TargetInfo = sink.TargetInfo

TargetInfo holds execution state for a single target.

type TemplateEngine

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

TemplateEngine renders notification messages from Go templates. It implements the sink.Renderer interface so that sinks can request on-demand rendering of their built-in or custom templates.

Default (embedded) templates are parsed once and cached by sink type — they never change at runtime. Custom (user-provided) templates are re-parsed on every call so content changes take effect immediately.

func NewTemplateEngine

func NewTemplateEngine(log logr.Logger) *TemplateEngine

NewTemplateEngine creates a new TemplateEngine. Default templates are lazily cached on first Render call for each sink type.

func (*TemplateEngine) Render

func (e *TemplateEngine) Render(ctx context.Context, payload Payload, opts ...sink.RenderOption) string

Render implements sink.Renderer. It resolves the template for the given payload (default for the sink type, or a custom override via RenderOption), executes it against the Payload, and returns the rendered message. On any error, a plain-text fallback is returned.

Directories

Path Synopsis
Package sink defines the contract between the notification dispatcher and external delivery backends.
Package sink defines the contract between the notification dispatcher and external delivery backends.

Jump to

Keyboard shortcuts

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