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.