github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/strategy_all_for_one.go (about) 1 package actor 2 3 import "time" 4 5 // NewAllForOneStrategy returns a new SupervisorStrategy which applies the given fault Directive from the decider to the 6 // failing child and all its children. 7 // 8 // This strategy is appropriate when the children have a strong dependency, such that and any single one failing would 9 // place them all into a potentially invalid state. 10 func NewAllForOneStrategy(maxNrOfRetries int, withinDuration time.Duration, decider DeciderFunc) SupervisorStrategy { 11 return &allForOneStrategy{ 12 maxNrOfRetries: maxNrOfRetries, 13 withinDuration: withinDuration, 14 decider: decider, 15 } 16 } 17 18 type allForOneStrategy struct { 19 maxNrOfRetries int 20 withinDuration time.Duration 21 decider DeciderFunc 22 } 23 24 var _ SupervisorStrategy = &allForOneStrategy{} 25 26 func (strategy *allForOneStrategy) HandleFailure(actorSystem *ActorSystem, supervisor Supervisor, child *PID, rs *RestartStatistics, reason interface{}, message interface{}) { 27 directive := strategy.decider(reason) 28 switch directive { 29 case ResumeDirective: 30 // resume the failing child 31 logFailure(actorSystem, child, reason, directive) 32 supervisor.ResumeChildren(child) 33 case RestartDirective: 34 children := supervisor.Children() 35 // try restart the all the children 36 if strategy.shouldStop(rs) { 37 logFailure(actorSystem, child, reason, StopDirective) 38 supervisor.StopChildren(children...) 39 } else { 40 logFailure(actorSystem, child, reason, RestartDirective) 41 supervisor.RestartChildren(children...) 42 } 43 case StopDirective: 44 children := supervisor.Children() 45 // stop all the children, no need to involve the crs 46 logFailure(actorSystem, child, reason, directive) 47 supervisor.StopChildren(children...) 48 case EscalateDirective: 49 // send failure to parent 50 // supervisor mailbox 51 // do not log here, log in the parent handling the error 52 supervisor.EscalateFailure(reason, message) 53 } 54 } 55 56 func (strategy *allForOneStrategy) shouldStop(rs *RestartStatistics) bool { 57 // supervisor says this child may not restart 58 if strategy.maxNrOfRetries == 0 { 59 return true 60 } 61 62 rs.Fail() 63 64 if rs.NumberOfFailures(strategy.withinDuration) > strategy.maxNrOfRetries { 65 rs.Reset() 66 return true 67 } 68 69 return false 70 }