server

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package server exposes RunLore's HTTP endpoints (incident webhooks).

Index

Constants

View Source
const ForwardedHeader = "X-Runlore-Forwarded"

ForwardedHeader marks a request a follower has already proxied once to the replica it believed was the leader. A request carrying it is NEVER forwarded again: if the receiver isn't the leader either (a stale holder view during a failover, or two followers briefly pointing at each other), it answers 421 instead of hopping on — forwarding is strictly single-hop, loops are structurally impossible.

Variables

This section is empty.

Functions

This section is empty.

Types

type Actions

type Actions struct {
	Approvals    *action.Approvals
	Pauser       Pauser
	Feedback     FeedbackRecorder // opt-in 👍/👎 recording (notify.slack.feedback_buttons)
	Token        string
	SlackSecret  string
	WebhookToken string   // optional bearer token required on POST /webhook/alertmanager
	ApproverIDs  []string // Slack user IDs permitted to approve actions
}

Actions bundles the optional rung-2/rung-3 wiring: the approval queue, the auto kill-switch, the shared control token, the Slack signing secret, and the opt-in feedback recorder.

type FeedbackRecorder added in v0.5.0

type FeedbackRecorder interface {
	Feedback(triggerKey, rating, user string, at time.Time) error
}

FeedbackRecorder persists a human 👍/👎 rating on a delivered investigation — the ground-truth signal the learning loop weighs recalled knowledge by (implemented by *outcome.Ledger).

type Forward added in v0.8.0

type Forward struct {
	// IsLeader reports whether THIS replica currently leads. With leader
	// election disabled the caller pins it true, so everything serves locally.
	IsLeader func() bool
	// LeaderAddr returns the "host:port" of the current lease holder, or ""
	// when no holder is known yet or the holder's identity carries no routable
	// IP (an old-format identity from a pre-#264 replica during a
	// mixed-version rollout) — the request is then shed with 503 + Retry-After,
	// matching the pre-#264 behavior of a standby that received traffic.
	LeaderAddr func() string
	// SelfName is THIS replica's pod name (POD_NAME / hostname), i.e. the
	// name half of its own lease identity. Paired with LeaderName it guards the
	// takeover self-race: see the check in middleware. Empty disables the guard
	// (single-replica, tests) — safe, since without a name to match on there is
	// no way to mistake the tracked holder for ourselves.
	SelfName string
	// LeaderName returns the pod-name part of the tracked holder identity (""
	// before the first OnNewLeader). Compared against SelfName to detect the
	// tracker briefly pointing at THIS pod (or a dead predecessor sharing our
	// stable StatefulSet name) so we serve locally instead of proxying to
	// ourselves.
	LeaderName func() string
	// Client posts the proxied request. nil defaults to a bounded
	// httpx.SecureClient — never http.DefaultClient (unbounded hang).
	Client *http.Client
	Log    *slog.Logger
}

Forward routes work-bearing requests from a non-leader replica to the current leader. Since #264 /readyz no longer reflects leadership — every warm replica is Ready and the Service may route to any of them — so "only the leader's queue processes work" is preserved here instead of by readiness-based routing: a follower that receives a work-bearing request (source webhooks, slack interactions, action control) proxies it to the leader it learned from the leader-election Lease. A nil *Forward (CLI, tests, single-replica without leader election) serves everything locally.

type Pauser

type Pauser interface {
	Pause()
	Resume()
	Paused() bool
}

Pauser is the rung-3 auto-execution kill-switch.

type Server

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

Server handles incoming incident webhooks and applies the trigger policy.

func New

func New(ready func() bool, acts Actions, built []source.Built, pipe *source.Pipeline, metricsHandler http.Handler, fwd *Forward, log *slog.Logger) *Server

New builds a Server. ready reports whether this replica should serve; nil = always ready. The caller composes what readiness means (e.g. a warm catalog — since #264 deliberately NOT leadership, so every warm replica is Ready and Helm --wait/kstatus succeeds with replicaCount>1). acts (optional) enables the rung-2 approval endpoints + the rung-3 kill-switch, gated by acts.Token (X-Approval-Token). /healthz is liveness; /readyz is readiness (gated by the caller-supplied ready func). built + pipe wire the registered event sources: webhook sources are mounted at their paths and feed the ingest pipeline. metricsHandler (optional) serves OTel Prometheus metrics on GET /metrics when non-nil. fwd (optional) is the leader-forwarding policy: every WORK-BEARING route (source webhooks, slack interactions, action control) goes through it so a follower proxies the request to the leader; nil serves everything locally.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the HTTP handler (built once at construction; Go 1.22+ method routing).

Jump to

Keyboard shortcuts

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