mirror of
https://github.com/kemko/reproxy.git
synced 2026-01-01 15:55:49 +03:00
* wip * resolve merge artifacts * full coverage for conductor * wire plugin conductor to main and proxy * wip, with separate match handler * split matching logic with another handler, add initial docs * move parts of proxy to handlers, add tests * add headers in to be sent to proxied url * merged from master * add example with docker compose * supress excesive debug reporting 0-9 disabled in docker * add plugin tests * randomize test port * lint: minor warns * lint: err shadow
65 lines
1.8 KiB
Go
65 lines
1.8 KiB
Go
// Package repeater call fun till it returns no error, up to repeat some number of iterations and delays defined by strategy.
|
|
// Repeats number and delays defined by strategy.Interface. Terminates immediately on err from
|
|
// provided, optional list of critical errors
|
|
package repeater
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/go-pkgz/repeater/strategy"
|
|
)
|
|
|
|
// Repeater is the main object, should be made by New or NewDefault, embeds strategy
|
|
type Repeater struct {
|
|
strategy.Interface
|
|
}
|
|
|
|
// New repeater with a given strategy. If strategy=nil initializes with FixedDelay 5sec, 10 times.
|
|
func New(strtg strategy.Interface) *Repeater {
|
|
if strtg == nil {
|
|
strtg = &strategy.FixedDelay{Repeats: 10, Delay: time.Second * 5}
|
|
}
|
|
result := Repeater{Interface: strtg}
|
|
return &result
|
|
}
|
|
|
|
// NewDefault makes repeater with FixedDelay strategy
|
|
func NewDefault(repeats int, delay time.Duration) *Repeater {
|
|
return New(&strategy.FixedDelay{Repeats: repeats, Delay: delay})
|
|
}
|
|
|
|
// Do repeats fun till no error. Predefined (optional) errors terminate immediately
|
|
func (r Repeater) Do(ctx context.Context, fun func() error, errors ...error) (err error) {
|
|
|
|
ctx, cancelFunc := context.WithCancel(ctx)
|
|
defer cancelFunc() // ensure strategy's channel termination
|
|
|
|
inErrors := func(err error) bool {
|
|
for _, e := range errors {
|
|
if e == err {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
ch := r.Start(ctx) // channel of ticks-like events provided by strategy
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
case _, ok := <-ch:
|
|
if !ok { // closed channel indicates completion or early termination, set by strategy
|
|
return err
|
|
}
|
|
if err = fun(); err == nil {
|
|
return nil
|
|
}
|
|
if err != nil && inErrors(err) { // terminate on critical error from provided list
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|