Help us shape the future of Go! Take the 2026 Go Developer Survey

beatfx

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 4 Imported by: 0

README

beatfx

Go Reference CI Release

Install · Quick start · Lifecycle · Configuration · Examples

Optional Uber Fx lifecycle integration for beat. This independent module owns the Fx dependency; beat itself does not.

Installation

Requires Go 1.27 or later.

go get github.com/uchaloop/beatfx@v0.1.0

Quick start

package main

import (
    "context"
    "time"

    "github.com/uchaloop/beat"
    "github.com/uchaloop/beatfx"
    "github.com/uchaloop/job"
    "go.uber.org/fx"
)

func main() {
    fx.New(
        fx.Supply(beat.Config{Period: 5 * time.Minute, Jitter: 30 * time.Second}),
        fx.Provide(func() (*job.Runner, error) {
            return job.MakeRunner(
                job.Config{Timeout: 4 * time.Minute},
                func(ctx context.Context) (int64, error) {
                    // Replace with one batch of application work.
                    return 0, ctx.Err()
                },
            )
        }),
        beatfx.Module(beat.WithGracefulStop()),
        fx.StopTimeout(5 * time.Minute),
    ).Run()
}

The application can instead provide the Runner using the separate jobfx module. beatfx requires only the Runner value, not that specific adapter.

Module requires beat.Config and *job.Runner. beat.Handler and one ordered beatfx.Options slice are optional. A container Handler is the default; explicit WithHandler options override it. Static options precede container options. Use one Module per application.

How it works

flowchart LR
    A["app.Run"] --> B["OnStart → beat.Start"]
    B --> C["Scheduled attempts"]
    C -->|terminal loop error| D["Request Fx shutdown: code 1"]
    D --> E["OnStop → beat.Stop"]
    S["SIGINT / SIGTERM"] --> E
Event Behaviour
Attempt returns an error Continue the schedule
Another cluster owns the point Skip this point
Loop cannot continue Request application shutdown with code 1
Application shuts down Stop scheduling; cancel or drain accepted work

Startup starts the scheduler. Shutdown stops scheduling and drains or cancels work according to beat's options. Ordinary attempt errors do not stop the daemon. If the scheduling loop terminates unexpectedly, beatfx requests Fx shutdown with exit code 1. app.Run handles this automatically. Applications driving Start/Stop manually must receive app.Wait and call Stop themselves. The original loop error is returned by beat.Stop through the shutdown hook.

Documentation

API reference on pkg.go.dev

[!TIP] We recommend confmaker for typed ENV configuration and confx for its Fx integration. Configuration loading stays in the application; it is optional for the work libraries.

Configure from ENV with confmaker / confx

Replace fx.Supply(beat.Config{...}) in the quick start with these Fx options:

confx.Module(),
confx.Provide[beat.Config](),

Import github.com/uchaloop/confx. Include confx.Module() once, even when registering several config types. Keep the work constructor and adapter Module.

BEAT_PERIOD=5m BEAT_JITTER=30s fills beat.Config. To load the Runner timeout as well, add confx.Provide[job.Config]() and have its constructor accept cfg job.Config instead of constructing that value inline.

Library Purpose
beat Scheduling and shutdown contracts
jobfx An optional way to provide the Runner

Acknowledgements

Thanks to the authors and maintainers of Uber Fx for dependency injection and lifecycle primitives that make this adapter possible.

License

MIT

Documentation

Overview

Package beatfx connects one beat.Beat to an Fx lifecycle. Module requires beat.Config and a *job.Runner. beat.Handler and Options are optional. Provide Options once as an ordered slice; static Module options are applied first, followed by the slice. Repeated setter options use their last value.

A ready set can be supplied with fx.Supply(beatfx.Options{...}). A constructor returning Options can use dependencies from the container. The application owns Fx startup and shutdown budgets. Use one Module per Fx application.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Module

func Module(opts ...beat.Option) fx.Option

Module provides a private Beat and registers its Start and Stop hooks. Static opts are applied before the optional container-provided Options.

Example
package main

import (
	"context"
	"log/slog"
	"time"

	"github.com/uchaloop/beat"
	"github.com/uchaloop/beatfx"
	"github.com/uchaloop/job"
	"github.com/uchaloop/job/middleware/recovery"
	"go.uber.org/fx"
)

func main() {
	app := fx.New(
		fx.Supply(beat.Config{Period: time.Minute}),
		fx.Supply(slog.Default()),

		// The runner carries the work, its middleware and its timeout.
		fx.Provide(func(log *slog.Logger) (*job.Runner, error) {
			return job.MakeRunner(
				job.Config{Timeout: 45 * time.Second},
				func(ctx context.Context) (int64, error) { return 0, ctx.Err() },
				job.WithMiddleware(recovery.Middleware(recovery.WithLogger(log))),
			)
		}),

		fx.Provide(func() beatfx.Options {
			return beatfx.Options{beat.WithGracefulStop()}
		}),

		beatfx.Module(),
		fx.StopTimeout(time.Minute),
		fx.NopLogger,
	)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	if err := app.Start(ctx); err != nil {
		panic(err)
	}
	if err := app.Stop(ctx); err != nil {
		panic(err)
	}
}

Types

type Options

type Options []beat.Option

Options is the ordered set of beat options an application builds from the container. Provide it once, and the order inside it is the order applied:

fx.Provide(func(db *sql.DB) beatfx.Options {
	return beatfx.Options{beat.WithOnStart(db.PingContext)}
})

A set that needs nothing from the container can be supplied outright with fx.Supply(beatfx.Options{...}), though such options can also go straight to Module.

Jump to

Keyboard shortcuts

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