Documentation
¶
Overview ¶
Package hayden watches web pages for content and fires a webhook when a target matches.
Index ¶
- Constants
- func AutoMigrate(ctx context.Context, db *gorm.DB) error
- func Connect(ctx context.Context, databaseURL string) (*gorm.DB, error)
- func SeedConfig(ctx context.Context, store *Store, cf *ConfigFile) (int, error)
- func ShouldNotify(t *Target, matched bool, contentHash string) bool
- type Config
- type ConfigFile
- type Event
- type Fetcher
- type HTTPNotifier
- type Matcher
- type Notifier
- type Scanner
- type Scheduler
- type Store
- func (s *Store) Count(ctx context.Context) (int64, error)
- func (s *Store) Create(ctx context.Context, t *Target) error
- func (s *Store) Delete(ctx context.Context, id uint) error
- func (s *Store) Get(ctx context.Context, id uint) (*Target, error)
- func (s *Store) List(ctx context.Context) ([]*Target, error)
- func (s *Store) ListEnabled(ctx context.Context) ([]*Target, error)
- func (s *Store) SaveRunState(ctx context.Context, t *Target) error
- type Target
Constants ¶
const (
// Service is the service name used for logging and telemetry.
Service = "hayden"
)
Variables ¶
This section is empty.
Functions ¶
func AutoMigrate ¶
AutoMigrate syncs the schema with the current models; safe on every startup.
func SeedConfig ¶
SeedConfig inserts the config file's targets into an empty store (no-op if it already has any), defaulting legacy targets to headless fetching.
Types ¶
type Config ¶
type Config struct {
Log *zap.SugaredLogger `json:"-"`
DefaultHook string `json:"default-hook"`
DefaultPeriod int `json:"default-period"`
}
Config holds service-wide defaults shared across targets.
type ConfigFile ¶
ConfigFile is the on-disk representation of the service config and its targets.
func ParseConfigFile ¶
func ParseConfigFile(stream []byte) (*ConfigFile, error)
ParseConfigFile decodes a ConfigFile from JSON bytes.
type Event ¶
type Event struct {
Target string `json:"target"`
URL string `json:"url"`
Matched bool `json:"matched"`
MatchedAt time.Time `json:"matched_at"`
MatchType string `json:"match_type"`
}
Event is the JSON payload POSTed to a target's hook when it matches.
type Fetcher ¶
Fetcher retrieves the content of a target for matching.
func FetcherFor ¶
FetcherFor returns the Fetcher for a fetch mode.
type HTTPNotifier ¶
HTTPNotifier POSTs the event JSON to the target hook (or DefaultHook).
type Matcher ¶
type Matcher interface {
Match(content []byte, value string) (bool, error)
Validate(value string) error
}
Matcher decides whether fetched content matches a target's configured value, and validates that value up front.
func MatcherFor ¶
MatcherFor returns the Matcher for a match type.
type Scanner ¶
type Scanner struct {
Store *Store
Notifier Notifier
// Fetcher overrides per-target resolution when set (tests); nil → FetcherFor.
Fetcher Fetcher
// Now overrides the clock (tests).
Now func() time.Time
}
Scanner runs a single target through fetch → match → notify → persist.
type Scheduler ¶
type Scheduler struct {
Scanner *Scanner
Store *Store
Cfg *Config
Log *zap.SugaredLogger
// PeriodFor overrides per-target period (tests); nil → EffectivePeriod.
PeriodFor func(*Target) time.Duration
// contains filtered or unexported fields
}
Scheduler runs one ticker per enabled target, scanning each on its period.
func (*Scheduler) Reload ¶
Reload restarts the tickers to reflect the current set of enabled targets.
type Store ¶
Store persists targets and their run-state in Postgres.
func (*Store) ListEnabled ¶
ListEnabled returns only enabled targets, in id order.
type Target ¶
type Target struct {
ID uint `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
Name string `gorm:"not null" json:"name"`
URL string `gorm:"not null" json:"url"`
FetchMode string `gorm:"not null;default:http" json:"fetch_mode"` // http | headless
MatchType string `gorm:"not null;default:substring" json:"match_type"` // substring (css|regex|jsonpath in a later phase)
MatchValue string `json:"match_value"`
Invert bool `json:"invert"`
NotifyMode string `gorm:"not null;default:once" json:"notify_mode"` // once (change in a later phase)
Hook string `json:"hook,omitempty"`
Period int `json:"period,omitempty"` // seconds; 0 → Config.DefaultPeriod
Enabled bool `gorm:"not null" json:"enabled"` // defaulted in app code; gorm can't tell unset from false
LastRunAt *time.Time `json:"last_run_at,omitempty"`
LastStatus string `json:"last_status,omitempty"` // ok | error
LastMatchAt *time.Time `json:"last_match_at,omitempty"`
LastMatched bool `json:"last_matched"`
LastError string `json:"last_error,omitempty"`
LastContentHash string `json:"-"`
}
Target is a single web page to watch, the match that triggers its hook, and the persisted state of its most recent scan.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
migrate
command
Command migrate connects to Postgres and syncs the schema.
|
Command migrate connects to Postgres and syncs the schema. |
|
Command server runs the hayden HTTP service: watch targets in Postgres, scanned on a schedule, firing a webhook on a match, managed via a small API.
|
Command server runs the hayden HTTP service: watch targets in Postgres, scanned on a schedule, firing a webhook on a match, managed via a small API. |
|
static
Package static embeds the server's static assets and seed config.
|
Package static embeds the server's static assets and seed config. |