anchor package - github.com/kyuff/anchor - Go Packages
- 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
const ( OK = 0 Interrupted = 1 SetupFailed = 3 Internal = 4 )
This section is empty.
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.
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
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.
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
New creates an Anchor that is bound to the Wire. When the Wire is closed, the Anchor will Close all Components.
Add will manage the Component list by the Anchor.
When Run is called, all Components will be started in the order they were given to the Anchor.
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.
Close creates a component that have an empty Start() and Setup() method, but have Close. It is a convenience to run cleanup code
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.
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.
Setup creates a component that have an empty Start() and Close() method, but have Setup. It is a convenience to run code before full application start.
Logger is an interface for logging by the Anchor. There is default implementation for slog.Logger.
type Option func(cfg *config)
Option for an Anchor configuration.
See config.go for defaults.
WithAnchorContext runs the Anchor in the given Context. If it is canceled, the Anchor will shutdown.
Default: context.Background()
WithCloseTimeout is the combined time components have to perform a graceful shutdown.
Default: No timeout
func WithDefaultSlog() Option
WithDefaultSlog uses slog.Default() for logging
WithExponentialReadyCheckBackoff doubles the wait time with each retry.
WithFixedReadyCheckBackoff waits a fixed amount of time between retries.
WithLinearReadyCheckBackoff increases the wait time linearly with each retry.
WithLogger sets the Logger for the application.
Default: No logging is done.
func WithNoopLogger() Option
WithNoopLogger disables logging
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.
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
WithSetupTimeout fails an Anchor if all Components have not been Setup within the timeout provided.
Default: No timeout
WithSlog uses the give *slog.Logger
WithStartTimeout fails an Anchor if all Components have not been Started within the timeout provided.
Default: No timeout
type TestingM interface {
Run() int
}
Wire keeps the Anchor running.
When the returned Context is canceled, all Components are Closed and the CancelFunc is called.
func DefaultSignalWire() Wire
DefaultSignalWire returns a Wire that listens for SIGINT and SIGTERM.
SignalWire returns a Wire that listens for the given os signals.
Use DefaultSignalWire to listen for SIGINT and SIGTERM.
WireFunc is a convenience type for creating a Wire from a function.