webhook

package
v1.10.1-rc1 Latest Latest
Warning

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

Go to latest
Published: May 12, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package webhook is the L11 plugin that delivers core daemon events to an external HTTP(S) endpoint. Subscribes to the daemon's event bus through coreapi.Deps.Events and POSTs each event as a JSON payload. Owns the HTTP client, retry+circuit-breaker state, and the persisted-URL file (~/.pilot/webhook_url) — none of which pkg/daemon (L7) is allowed to know about.

Extracted from pkg/daemon/webhook.go in T4.1 (webhook-inversion). The daemon publishes; the plugin subscribes — the layered architecture's separation of "what happened" (core) from "tell the outside world" (plugin).

Index

Constants

View Source
const (
	MaxRetries           = 3
	InitialBackoff       = 1 * time.Second
	CircuitOpenThreshold = 5
	CircuitCooldown      = 30 * time.Second
)

Tunable circuit-breaker + retry constants.

Variables

This section is empty.

Functions

func LoadPersistedURL

func LoadPersistedURL() (string, error)

LoadPersistedURL reads the previously-saved webhook URL. Returns empty string if no file exists or the contents don't pass validation.

func SavePersistedURL

func SavePersistedURL(url string) error

SavePersistedURL writes the URL to ~/.pilot/webhook_url, or deletes the file if url is empty.

func Validate

func Validate(rawURL string) error

Validate checks that a webhook URL uses http(s) and does not target cloud metadata or link-local endpoints (SSRF prevention). Delegates to pkg/urlvalidate so other packages can share the same rules without importing this plugin.

Types

type Client

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

Client dispatches events asynchronously to an HTTP(S) endpoint. If URL is empty, all methods are no-ops (zero overhead when disabled).

func NewClient

func NewClient(url string, nodeIDFunc func() uint32, opts ...Option) *Client

NewClient creates a webhook dispatcher. If url is empty, returns nil.

func (*Client) CircuitSkips

func (wc *Client) CircuitSkips() uint64

CircuitSkips returns the number of events short-circuited because the breaker was open. Nil-safe.

func (*Client) Close

func (wc *Client) Close()

Close drains the queue and stops the background goroutine. Idempotent. Waits up to 5 seconds for the queue to drain before abandoning remaining events.

func (*Client) Dropped

func (wc *Client) Dropped() uint64

Dropped returns the number of events dropped due to a full queue. Nil-safe.

func (*Client) Emit

func (wc *Client) Emit(event string, data interface{})

Emit queues an event for async delivery. Non-blocking; drops if buffer full. Safe to call after Close (becomes a no-op).

type Event

type Event struct {
	EventID   uint64      `json:"event_id"`
	Event     string      `json:"event"`
	NodeID    uint32      `json:"node_id"`
	Timestamp time.Time   `json:"timestamp"`
	Data      interface{} `json:"data,omitempty"`
}

Event is the JSON payload POSTed to the webhook endpoint.

type Option

type Option func(*Client)

Option configures a Client.

func WithCircuitCooldown

func WithCircuitCooldown(d time.Duration) Option

WithCircuitCooldown overrides the default 30s circuit-breaker cooldown. Tests use a small value to exercise open→probe→reset cycles quickly.

func WithHTTPTimeout

func WithHTTPTimeout(d time.Duration) Option

WithHTTPTimeout sets the HTTP client timeout (default 5s).

func WithRetryBackoff

func WithRetryBackoff(d time.Duration) Option

WithRetryBackoff sets the initial retry backoff (default 1s, doubles each retry).

type Service

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

Service is the L11 plugin that delivers core daemon events to an HTTP(S) endpoint. Implements coreapi.Service: on Start, subscribes to the bus ("*") and forwards every event to its internal Client. On Stop, cancels the subscription and drains the Client.

The URL can be hot-swapped at runtime via SetURL — that path is invoked from cmd/daemon when IPC's set-webhook handler fires.

func NewService

func NewService(initialURL string, opts ...Option) *Service

NewService constructs a webhook plugin Service. initialURL is taken from the daemon's -webhook flag; if empty, the plugin tries the persisted URL file (~/.pilot/webhook_url) on Start.

func (*Service) Name

func (s *Service) Name() string

func (*Service) Order

func (s *Service) Order() int

Order: webhook starts AFTER core foundation (50-79: trust/identity) but BEFORE app services (100+) so it captures their startup events (node.registered, agent.registered, network.auto_joined). 90 is the observability slot per coreapi/lifecycle.go.

func (*Service) SetURL

func (s *Service) SetURL(url string)

SetURL hot-swaps the webhook URL. Called from cmd/daemon's IPC adapter when `pilotctl set-webhook <url>` fires. An empty url disables webhook delivery (becomes a no-op until set again).

func (*Service) Start

func (s *Service) Start(_ context.Context, deps coreapi.Deps) error

func (*Service) Stats

func (s *Service) Stats() Stats

Stats returns dispatcher counters for the daemon's Info() response. Nil-safe across "no client configured" and "service stopped."

func (*Service) Stop

func (s *Service) Stop(_ context.Context) error

type Stats

type Stats struct {
	Dropped      uint64
	CircuitSkips uint64
}

Stats is the snapshot of per-Client counters needed by daemon's DaemonInfo response. Returned by (*Service).Stats(); each call reads the underlying atomics. Nil-safe at the Service level — returns the zero value if no Client is configured.

Jump to

Keyboard shortcuts

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