Documentation
¶
Index ¶
- Constants
- func Singleton[T any](fn func() (T, error)) func() T
- type Anchor
- type Component
- type Logger
- type Option
- func WithAnchorContext(ctx context.Context) Option
- func WithCloseTimeout(timeout time.Duration) Option
- func WithDefaultSlog() Option
- func WithExponentialReadyCheckBackoff(base time.Duration) Option
- func WithFixedReadyCheckBackoff(d time.Duration) Option
- func WithLinearReadyCheckBackoff(increment time.Duration) Option
- func WithLogger(logger Logger) Option
- func WithNoopLogger() Option
- func WithReadyCallback(fn func(ctx context.Context) error) Option
- func WithReadyCheckBackoff(fn func(ctx context.Context, attempt int) (time.Duration, error)) Option
- func WithSetupTimeout(timeout time.Duration) Option
- func WithSlog(log *slog.Logger) Option
- func WithStartTimeout(timeout time.Duration) Option
- type TestingM
- type Wire
- type WireFunc
Examples ¶
Constants ¶
const ( // OK signals the Anchor shutdown with no errors // after it was interrupted by the Wire OK = 0 // Interrupted signals the Anchor failed to set up or close within the timeout Interrupted = 1 // SetupFailed signals the Anchor received an error during Setup. SetupFailed = 3 // Internal signals the Anchor shutdown due to a Component returning an error. Internal = 4 )
Variables ¶
This section is empty.
Functions ¶
func Singleton ¶
Singleton creates a func that returns a value T created by fn. The value is created only once. If fn returns an error, Singleton panics.
This function is meant to be used as part of application wiring, where a panic seems may seem acceptable.
It is similar to sync.OnceValue, but differs in the way that the creator function fn can return an error.
Example ¶
type Service struct {
ID int
HostName string
}
service := anchor.Singleton(func() (*Service, error) {
fmt.Println("Creating service")
return &Service{
ID: rand.Int(),
HostName: "localhost",
}, nil
})
s := service()
fmt.Printf("host: %s\n", s.HostName)
fmt.Printf("id equal: %v\n", service().ID == s.ID)
Output: Creating service host: localhost id equal: true
Types ¶
type Anchor ¶
type Anchor struct {
// contains filtered or unexported fields
}
Anchor the application Components to a Wire.
The Anchor will run each Component in the order they are added. A Component will follow the lifecycle steps (Setup, Start, Close), so the full application start and close gracefully.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/kyuff/anchor"
)
type ExampleService struct {
name string
}
func (svc *ExampleService) Setup(ctx context.Context) error {
fmt.Printf("Setup of %s\n", svc.name)
return nil
}
func (svc *ExampleService) Start(ctx context.Context) error {
fmt.Printf("Starting component\n")
// A component can act in three different ways:
// 1. Block using the ctx as a signal for when to gracefully shut down
// 2. Block and implement the Close() method as a signal for graceful shutdown
// 3. Return a nil when there is no background work that needs to be done.
<-ctx.Done()
return nil
}
func (svc *ExampleService) Close() error {
fmt.Printf("Closing %s\n", svc.name)
return nil
}
func main() {
code := anchor.New(newAutoClosingWire(time.Millisecond*100)).
Add(
&ExampleService{name: "component-a"},
&ExampleService{name: "component-b"},
).
Run()
fmt.Printf("Exit code: %d\n", code)
}
func newAutoClosingWire(duration time.Duration) anchor.WireFunc {
return func(ctx context.Context) (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(ctx)
go func() {
defer cancel()
time.Sleep(duration)
fmt.Printf("Closing down the Anchor\n")
}()
return ctx, cancel
}
}
Output: Setup of component-a Setup of component-b Starting component Starting component Closing down the Anchor Closing component-b Closing component-a Exit code: 0
func New ¶
New creates an Anchor that is bound to the Wire. When the Wire is closed, the Anchor will Close all Components.
type Component ¶
Component is a central part of an application that needs to have it's lifetime managed.
A Component can optionally Setup and Close methods.. By doing so, Anchor will guarantee to call the methods in order: Setup, Start, Close. This allows applications to prepare and gracefully clean up.
An example of a Component could be a database connection. It can read it's configuration in the Setup phase, connect at Start and disconnect at Close. If the database connection disconnects due to a network outage, it can return and error from Start, which closes down the entire application.
func Close ¶
Close creates a component that have an empty Start() and Setup() method, but have Close. It is a convenience to run cleanup code
func Make ¶
Make a component by it's setup func. A convenience when the Component is not needed as a reference by other parts of the application, but just needs it's lifecycle handled.
func MakeProbe ¶
func MakeProbe[T Component](name string, setup func() (T, error), probe func(ctx context.Context) error) Component
MakeProbe a component by it's setup and probe functions. A convenience when the Component is not needed as a reference by other parts of the application, but just needs it's lifecycle handled. The probe function is called after Start to check if the Component is ready.
type Logger ¶
type Logger interface {
// InfofCtx logs on an INFO level
InfofCtx(ctx context.Context, template string, args ...any)
// ErrorfCtx logs on an ERROR level
ErrorfCtx(ctx context.Context, template string, args ...any)
}
Logger is an interface for logging by the Anchor. There is default implementation for slog.Logger.
type Option ¶
type Option func(cfg *config)
Option for an Anchor configuration.
See config.go for defaults.
func WithAnchorContext ¶
WithAnchorContext runs the Anchor in the given Context. If it is canceled, the Anchor will shutdown.
Default: context.Background()
func WithCloseTimeout ¶
WithCloseTimeout is the combined time components have to perform a graceful shutdown.
Default: No timeout
func WithDefaultSlog ¶
func WithDefaultSlog() Option
WithDefaultSlog uses slog.Default() for logging
func WithExponentialReadyCheckBackoff ¶
WithExponentialReadyCheckBackoff doubles the wait time with each retry.
func WithFixedReadyCheckBackoff ¶
WithFixedReadyCheckBackoff waits a fixed amount of time between retries.
func WithLinearReadyCheckBackoff ¶
WithLinearReadyCheckBackoff increases the wait time linearly with each retry.
func WithReadyCallback ¶
WithReadyCallback is called when all Components have been Setup and Started and succeeded any Probe.
This is useful for enabling features that require all Components to be ready before they can be used. If the function returns an error, the Anchor will fail to start and go into a shutdown state.
func WithReadyCheckBackoff ¶
WithReadyCheckBackoff is called when a Component fails a Probe.
The function should return the amount of time to wait before retrying. If the function returns an error, the Anchor will fail to start and go into a shutdown state.
Default: linear backoff with 100 millisecond increment
func WithSetupTimeout ¶
WithSetupTimeout fails an Anchor if all Components have not been Setup within the timeout provided.
Default: No timeout
func WithStartTimeout ¶
WithStartTimeout fails an Anchor if all Components have not been Started within the timeout provided.
Default: No timeout
type Wire ¶
Wire keeps the Anchor running.
When the returned Context is canceled, all Components are Closed and the CancelFunc is called.
func DefaultSignalWire ¶
func DefaultSignalWire() Wire
DefaultSignalWire returns a Wire that listens for SIGINT and SIGTERM.
func SignalWire ¶
SignalWire returns a Wire that listens for the given os signals.
Use DefaultSignalWire to listen for SIGINT and SIGTERM.
func TestingWire ¶
TestingWire returns a Wire for use in testing. It will Run the tests and and then signal the application to shutdown.