Last active
October 26, 2022 06:25
-
-
Save danielfbm/bcf036ba6a94caa160e4d749a3a9c6fe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"time" | |
redis "gopkg.in/redis.v5" | |
) | |
// CircuitBreaker responsible for creating a circuit breaking | |
// logic for redis client | |
type CircuitBreaker struct { | |
// backoff time before retrying | |
Backoff time.Duration | |
// max number of retries before backoff | |
MaxRetries int | |
// backoff internals | |
isBackoff bool | |
retries int | |
backoffStart time.Time | |
} | |
func (c *CircuitBreaker) handleError(err error) error { | |
if err == nil { | |
if c.isBackoff { | |
c.reset() | |
} | |
return nil | |
} | |
c.retries++ | |
if c.retries > c.MaxRetries { | |
c.isBackoff = true | |
c.backoffStart = time.Now() | |
} | |
return err | |
} | |
// IsBackoff returns true if the circuit braker is locked | |
func (c *CircuitBreaker) IsBackoff() bool { | |
if !c.isBackoff { | |
return false | |
} | |
if c.backoffStart.Add(c.Backoff).Before(time.Now()) { | |
// should unlock | |
c.reset() | |
} | |
return c.isBackoff | |
} | |
func (c *CircuitBreaker) reset() { | |
c.isBackoff = false | |
c.retries = 0 | |
c.backoffStart = time.Time{} | |
} | |
// KeyIncrFunc key function definition | |
type KeyIncrFunc func(key string) *redis.IntCmd | |
func (c *CircuitBreaker) KeyFunc(f KeyIncrFunc) KeyIncrFunc { | |
return func(key string) *redis.IntCmd { | |
if c.IsBackoff() { | |
return redis.NewIntCmd(key) | |
} | |
e := f(key) | |
c.handleError(e.Err()) | |
return e | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment