github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/strategy_exponential_backoff.go (about)

     1  package actor
     2  
     3  import (
     4  	"math/rand"
     5  	"time"
     6  )
     7  
     8  // NewExponentialBackoffStrategy creates a new Supervisor strategy that restarts a faulting child using an exponential
     9  // back off algorithm:
    10  //
    11  //	delay =
    12  func NewExponentialBackoffStrategy(backoffWindow time.Duration, initialBackoff time.Duration) SupervisorStrategy {
    13  	return &exponentialBackoffStrategy{
    14  		backoffWindow:  backoffWindow,
    15  		initialBackoff: initialBackoff,
    16  	}
    17  }
    18  
    19  type exponentialBackoffStrategy struct {
    20  	backoffWindow  time.Duration
    21  	initialBackoff time.Duration
    22  }
    23  
    24  var _ SupervisorStrategy = &exponentialBackoffStrategy{}
    25  
    26  func (strategy *exponentialBackoffStrategy) HandleFailure(actorSystem *ActorSystem, supervisor Supervisor, child *PID, rs *RestartStatistics, reason interface{}, _ interface{}) {
    27  	strategy.setFailureCount(rs)
    28  
    29  	backoff := rs.FailureCount() * int(strategy.initialBackoff.Nanoseconds())
    30  	noise := rand.Intn(500)
    31  	dur := time.Duration(backoff + noise)
    32  	time.AfterFunc(dur, func() {
    33  		logFailure(actorSystem, child, reason, RestartDirective)
    34  		supervisor.RestartChildren(child)
    35  	})
    36  }
    37  
    38  func (strategy *exponentialBackoffStrategy) setFailureCount(rs *RestartStatistics) {
    39  	if rs.NumberOfFailures(strategy.backoffWindow) == 0 {
    40  		rs.Reset()
    41  	}
    42  
    43  	rs.Fail()
    44  }