Documentation
¶
Overview ¶
Package beat runs a single background Job on a schedule: on an interval ("@every 5s") or a cron expression ("*/5 * * * * *"), optionally after a start hook, bounded by a per-run timeout, wrapped by a chain of Middleware. Build a Beat with MakeBeat and drive it with Start/Stop, or use the beat/beatfx subpackage to wire it into an Uber Fx application.
beat has no built-in metrics: after every run it hands a Record to a Handler, the same way slog hands a Record to its handler. Metrics, logging and tracing are adapters the caller supplies. Configuration is declared as a plain struct with koanf and env tags and loaded by the application through confmaker/confx, so beat never reads files or the environment itself.
Scheduling has two modes. An "@every" interval measures the gap from the end of one run to the start of the next, so the effective period grows by the Job's duration. A cron spec fires at fixed wall-clock points and skips a point a long run overruns - it never queues catch-up runs.
One Beat runs one Job; beat is single-instance per application. The core does not recover panics: a panic in the Job (or Handler) propagates and crashes the process, with a full stack on stderr - the honest default for user code that misbehaves. To keep the scheduler alive instead, add middleware/recovery, which recovers the panic, optionally logs it with its stack, and reports it as a *PanicError on the Record.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Beat ¶
type Beat struct {
// contains filtered or unexported fields
}
Beat is a scheduled runner for one Job. Build it with Module; the Fx lifecycle drives its hooks and loop.
It keeps two independent contexts: loopCtx gates scheduling (cancelled to stop launching new runs) and jobCtx is the parent of each run (cancelled to abort an in-flight run). Splitting them lets stop drain - end scheduling while letting the current run finish - or cancel, depending on the graceful flag.
func MakeBeat ¶
MakeBeat resolves cfg against opts and builds a Beat. job is required; handler may be nil (a no-op handler is used). Drive the returned Beat with Start and Stop; the beatfx subpackage does this from the Fx lifecycle.
func (*Beat) Start ¶
Start runs the OnStart hook and launches the run loop. It is the OnStart half of the lifecycle; the loop runs in its own goroutine, so Start returns once it is launched. ctx bounds the hook. A returned error aborts startup.
type Config ¶
type Config struct {
// Spec is the schedule: an interval such as "@every 5s" or a cron
// expression such as "*/5 * * * * *". Required.
Spec string `koanf:"spec" env:"SPEC"`
// JobTimeout bounds the context of a single Job execution. Zero (unset)
// uses the default, 1m; every execution is bounded, so set a larger value
// for a legitimately long Job.
JobTimeout time.Duration `koanf:"job_timeout" env:"JOB_TIMEOUT"`
// Jitter is the maximum random delay used to stagger instances so replicas
// do not all fire at once. For an interval it is applied once before the
// first run; for cron it is added to every tick, so keep it below the cron
// interval. Zero disables it.
Jitter time.Duration `koanf:"jitter" env:"JITTER"`
}
Config is the configuration beat declares. Both tag namespaces are inert strings: an application loads them with confmaker/confx (koanf from the file, env from the environment) and provides the filled Config into the container. beat itself never reads files or the environment.
type Handler ¶
Handler receives a Record after every run. It is the single observability seam of beat: metrics, logging and tracing are all built on top of it, so the core depends on none of them. Handle must not block for long - it runs inline on the run loop. It mirrors slog.Handler.
func MultiHandler ¶
MultiHandler returns a Handler that passes each Record to every handler in turn, skipping nil ones. Use it to run several sinks - metrics and logging, say - behind Module's single Handler slot. Handlers run in order and are not isolated: the core does not recover a panicking handler, so one panic propagates and crashes the process. Keep handlers panic-free.
type HandlerFunc ¶
HandlerFunc adapts an ordinary function to a Handler, like http.HandlerFunc.
type Job ¶
Job is the unit of work beat runs on each tick. It reports how many items it processed - return 0 when the job is not item-oriented - and an error if the run failed. A Job must respect ctx: beat bounds it with the job timeout and, unless graceful stop is enabled, cancels it on shutdown.
type Middleware ¶
Middleware wraps a Job to add behaviour around it - recovery, backoff, context enrichment, extra logging. It is classic Go composition: a Middleware receives the next Job and returns a Job that calls it.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option customizes a Beat built by Module.
func WithGracefulStop ¶
func WithGracefulStop() Option
WithGracefulStop lets the in-flight run finish on shutdown instead of having its context cancelled. beat stops scheduling new runs immediately; the current run continues until it returns or the stop deadline (fx.StopTimeout) elapses, at which point its context is cancelled as a last resort.
func WithHandler ¶
WithHandler sets the observability Handler. It overrides a Handler provided through the Fx container.
func WithMiddleware ¶
func WithMiddleware(mw ...Middleware) Option
WithMiddleware wraps the Job. The first middleware is the outermost layer and runs first.
func WithOnStart ¶
WithOnStart registers a hook run once before the loop starts. A returned error aborts startup.
type PanicError ¶
PanicError wraps a value recovered from a panic in the Job. The recovery middleware returns it as the run error, so a Handler can tell a panic from an ordinary error with errors.As and inspect the recovered value and its stack. The beat core does not recover panics; without the recovery middleware a panic crashes the process (with a stack on stderr).
func (*PanicError) Error ¶
func (e *PanicError) Error() string
type Record ¶
type Record struct {
// Iteration is the 1-based run counter for this Beat instance.
Iteration int64
// Start is the wall-clock time the run began.
Start time.Time
// Duration is how long the Job took.
Duration time.Duration
// Processed is the number of items the Job reported for this run.
Processed int
// Err is the error the Job returned, or nil on success. A panic recovered
// by the recovery middleware is reported as a *PanicError.
Err error
// Mode is the scheduling mode that produced this run.
Mode Mode
}
Record describes a single completed run of the Job. It is handed to a Handler after each run, mirroring the shape of slog.Record: the library produces the data, the caller decides what to do with it (metrics, logging, tracing).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package beatfx wires a beat.Beat into an Uber Fx application: it builds the Beat from the container's Config, Job and optional Handler, and drives its Start/Stop from the Fx lifecycle.
|
Package beatfx wires a beat.Beat into an Uber Fx application: it builds the Beat from the container's Config, Job and optional Handler, and drives its Start/Stop from the Fx lifecycle. |
|
middleware
|
|
|
batch
Package batch provides a beat.Middleware that pauses after each run for a delay chosen from how much the run processed and its error - useful for draining a queue fast while it is full and backing off when it empties.
|
Package batch provides a beat.Middleware that pauses after each run for a delay chosen from how much the run processed and its error - useful for draining a queue fast while it is full and backing off when it empties. |
|
idle
Package idle provides a beat.Middleware that pauses after each run for a delay chosen from the run's error - a backoff on failure, for example.
|
Package idle provides a beat.Middleware that pauses after each run for a delay chosen from the run's error - a backoff on failure, for example. |
|
recovery
Package recovery provides a beat.Middleware that recovers from a panic in the Job and turns it into a *beat.PanicError, so one bad run does not crash the process.
|
Package recovery provides a beat.Middleware that recovers from a panic in the Job and turns it into a *beat.PanicError, so one bad run does not crash the process. |