Documentation
¶
Overview ¶
Package breaker provides flexible mechanism to make your code breakable.
Example (GracefulShutdown) ¶
example := make(chan struct{})
breaker := Multiplex(
BreakBySignal(os.Interrupt, syscall.SIGINT, syscall.SIGTERM),
BreakByTimeout(250*time.Millisecond),
)
defer breaker.Close()
server := http.Server{
BaseContext: func(net.Listener) context.Context {
return ToContext(breaker)
},
}
go func() {
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
close(example)
}()
<-breaker.Done()
if err := server.Shutdown(context.TODO()); err == nil && errors.Is(breaker.Err(), Interrupted) {
fmt.Println("works well")
}
<-example
Output: works well
Example (HttpRequest) ¶
const url = "http://example.com/"
example := make(chan struct{})
close(example)
breaker := Multiplex(
BreakByChannel(example),
BreakBySignal(os.Interrupt, syscall.SIGINT, syscall.SIGTERM),
BreakByTimeout(time.Hour),
)
defer breaker.Close()
req, err := http.NewRequestWithContext(ToContext(breaker), http.MethodGet, url, nil)
if err != nil {
panic(err)
}
//nolint:bodyclose
if _, err := http.DefaultClient.Do(req); errors.Is(err, context.Canceled) && errors.Is(breaker.Err(), Interrupted) {
fmt.Println("works well")
}
Output: works well
Index ¶
- func ToContext(br Interface) context.Context
- type Error
- type Interface
- func BreakByChannel(signal <-chan struct{}) Interface
- func BreakByContext(ctx context.Context, cancel context.CancelFunc) Interface
- func BreakByDeadline(deadline time.Time) Interface
- func BreakBySignal(sig ...os.Signal) Interface
- func BreakByTimeout(timeout time.Duration) Interface
- func Multiplex(breakers ...Interface) Interface
- func MultiplexThree(one, two, three Interface) Interfacedeprecated
- func MultiplexTwo(one, two Interface) Interfacedeprecated
- func New() Interface
- func WithContext(ctx context.Context) (Interface, context.Context)deprecated
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ToContext ¶ added in v1.2.0
ToContext converts the breaker into the Context.
interrupter := breaker.Multiplex(
breaker.BreakBySignal(os.Interrupt),
breaker.BreakByTimeout(time.Minute),
)
defer interrupter.Close()
request, err := http.NewRequestWithContext(breaker.ToContext(interrupter), ...)
if err != nil { handle(err) }
response, err := http.DefaultClient.Do(request)
if err != nil { handle(err) }
handle(response)
Types ¶
type Error ¶ added in v1.2.0
type Error string
Error defines the package errors.
const Interrupted Error = "operation interrupted"
Interrupted is the error returned by the breaker when a cancellation signal occurred.
type Interface ¶
type Interface interface {
// Close closes the Done channel and releases resources associated with it.
Close()
// Done returns a channel that's closed when a cancellation signal occurred.
Done() <-chan struct{}
// If Done is not yet closed, Err returns nil.
// If Done is closed, Err returns a non-nil error.
// After Err returns a non-nil error, successive calls to Err return the same error.
Err() error
// contains filtered or unexported methods
}
Interface carries a cancellation signal to interrupt an action execution.
Example based on github.com/kamilsk/retry/v5 module:
if err := retry.Do(breaker.BreakByTimeout(time.Minute), action); err != nil {
log.Fatal(err)
}
Example based on github.com/kamilsk/semaphore/v5 module:
if err := semaphore.Acquire(breaker.BreakByTimeout(time.Minute), 5); err != nil {
log.Fatal(err)
}
func BreakByChannel ¶ added in v1.2.0
func BreakByChannel(signal <-chan struct{}) Interface
BreakByChannel returns a new breaker based on the channel.
signal := make(chan struct{})
go func() {
<-time.After(time.Minute)
close(signal)
}()
interrupter := breaker.BreakByChannel(signal)
defer interrupter.Close()
background.Job().Do(interrupter)
func BreakByContext ¶ added in v1.1.1
func BreakByContext(ctx context.Context, cancel context.CancelFunc) Interface
BreakByContext returns a new breaker based on the Context.
interrupter := breaker.BreakByContext(context.WithTimeout(req.Context(), time.Minute)) defer interrupter.Close() background.Job().Do(interrupter)
func BreakByDeadline ¶
BreakByDeadline closes the Done channel when the deadline occurs.
interrupter := breaker.BreakByDeadline(time.Now().Add(time.Minute)) defer interrupter.Close() background.Job().Do(interrupter)
func BreakBySignal ¶
BreakBySignal closes the Done channel when the breaker will receive OS signals.
interrupter := breaker.BreakBySignal(os.Interrupt) defer interrupter.Close() background.Job().Do(interrupter)
func BreakByTimeout ¶
BreakByTimeout closes the Done channel when the timeout happens.
interrupter := breaker.BreakByTimeout(time.Minute) defer interrupter.Close() background.Job().Do(interrupter)
func Multiplex ¶
Multiplex combines multiple breakers into one.
interrupter := breaker.Multiplex( breaker.BreakByContext(req.Context()), breaker.BreakBySignal(os.Interrupt), breaker.BreakByTimeout(time.Minute), ) defer interrupter.Close() background.Job().Do(interrupter)
func MultiplexThree
deprecated
MultiplexThree combines three breakers into one. It's an optimized version of a more generic Multiplex.
interrupter := breaker.MultiplexThree( breaker.BreakByContext(req.Context()), breaker.BreakBySignal(os.Interrupt), breaker.BreakByTimeout(time.Minute), ) defer interrupter.Close() background.Job().Do(interrupter)
Deprecated: Multiplex has the same optimization under the hood now. TODO:v2 will be removed.
func MultiplexTwo
deprecated
MultiplexTwo combines two breakers into one.
interrupter := breaker.MultiplexTwo( breaker.BreakByContext(req.Context()), breaker.BreakBySignal(os.Interrupt), ) defer interrupter.Close() background.Job().Do(interrupter)
Deprecated: Multiplex has the same optimization under the hood now. TODO:v2 will be removed.
func New ¶ added in v1.2.0
func New() Interface
New returns a new breaker, which can be interrupted only by a Close call.
interrupter := breaker.New() go background.Job().Do(interrupter) <-time.After(time.Minute) interrupter.Close()
func WithContext
deprecated
WithContext returns a new breaker and an associated Context based on the passed one.
interrupter, ctx := breaker.WithContext(req.Context()) defer interrupter.Close() background.Job().Run(ctx)
Deprecated: use BreakByContext instead. TODO:v2 will be removed.