/// <summary> /// <para> /// Given a function, returns an internally retrying Task. /// The first attempt will be made immediately, each subsequent attempt will be made with a backoff time, /// if the previous attempt failed. /// </para> /// If attempts are exhausted the returned Task is simply the result of invoking attempt. /// </summary> /// <param name="attempt">TBD</param> /// <param name="attempts">TBD</param> /// <param name="minBackoff">minimum (initial) duration until the child actor will started again, if it is terminated.</param> /// <param name="maxBackoff">the exponential back-off is capped to this duration.</param> /// <param name="randomFactor">after calculation of the exponential back-off an additional random delay based on this factor is added, e.g. `0.2` adds up to `20%` delay. In order to skip this additional delay pass in `0`.</param> /// <param name="scheduler">The scheduler instance to use.</param> public static Task <T> Retry <T>(Func <Task <T> > attempt, int attempts, TimeSpan minBackoff, TimeSpan maxBackoff, int randomFactor, IScheduler scheduler) { if (attempt == null) { throw new ArgumentNullException("Parameter attempt should not be null."); } if (minBackoff <= TimeSpan.Zero) { throw new ArgumentException("Parameter minBackoff must be > 0"); } if (maxBackoff < minBackoff) { throw new ArgumentException("Parameter maxBackoff must be >= minBackoff"); } if (randomFactor < 0.0 || randomFactor > 1.0) { throw new ArgumentException("RandomFactor must be between 0.0 and 1.0"); } return(Retry(attempt, attempts, attempted => BackoffSupervisor.CalculateDelay(attempted, minBackoff, maxBackoff, randomFactor), scheduler)); }
private bool WaitChildTerminatedBeforeBackoff(object message, IActorRef childRef) { var terminated = message as Terminated; if (terminated != null && terminated.ActorRef.Equals(childRef)) { Become(Receive); Child = null; var restartDelay = BackoffSupervisor.CalculateDelay(RestartCountN, _minBackoff, _maxBackoff, _randomFactor); Context.System.Scheduler.ScheduleTellOnce(restartDelay, Self, BackoffSupervisor.StartChild.Instance, Self); RestartCountN++; } else if (message is BackoffSupervisor.StartChild) { // Ignore it, we will schedule a new one once current child terminated. } else { return(false); } return(true); }
private bool WaitChildTerminatedBeforeBackoff(object message, IActorRef childRef) { switch (message) { case Terminated terminated when terminated.ActorRef.Equals(childRef): { Become(Receive); Child = null; var restartDelay = BackoffSupervisor.CalculateDelay(RestartCountN, _minBackoff, _maxBackoff, _randomFactor); Context.System.Scheduler.ScheduleTellOnce(restartDelay, Self, BackoffSupervisor.StartChild.Instance, Self); RestartCountN++; break; } case BackoffSupervisor.StartChild _: // Ignore it, we will schedule a new one once current child terminated. break; default: return(false); } return(true); }