/// <summary> /// Creates a new State computation that is primed with the data of a particular /// failure event. /// </summary> /// <param name="strategy">Strategy as a State computation</param> /// <param name="pid">Process ID that failed</param> /// <param name="sender">Process that sent the message that cause the failure</param> /// <param name="parent">Supervisor of the failed Process</param> /// <param name="siblings">The siblings of the failed Process</param> /// <param name="ex">Exception</param> /// <param name="msg">Message that caused the failure</param> /// <returns>State computation that can be invoked by passing it /// an object of StrategyState. This will result in a StateResult that contains /// the mutated StrategyState and a StrategyDecision. The StrategyDecision /// contains all the information needed to decide the fate of a Process (and /// related processes)</returns> public static State <StrategyState, StrategyDecision> Failure( this State <StrategyContext, Unit> strategy, ProcessId pid, ProcessId sender, ProcessId parent, IEnumerable <ProcessId> siblings, Exception ex, object msg ) { return(stateInst => { var now = DateTime.UtcNow; var state = strategy(StrategyContext.Empty.With( Global: stateInst.With(Failures: stateInst.Failures + 1), FailedProcess: pid, ParentProcess: parent, Sender: sender, Siblings: siblings, Exception: ex, Message: msg)).State; var decision = new StrategyDecision( state.Directive.IfNone(Directive.Restart), state.MessageDirective.IfNone(MessageDirective.ForwardToDeadLetters), state.Affects, state.Pause ); return StateResult.Return(state.Global.With(LastFailure: now), decision); }); }
InboxDirective RunMessageDirective( ProcessId pid, ProcessId sender, StrategyDecision decision, Exception e, object message ) { var directive = decision.MessageDirective; switch (directive.Type) { case MessageDirectiveType.ForwardToParent: tell(pid.Parent(), message, sender); return(InboxDirective.Default); case MessageDirectiveType.ForwardToSelf: tell(pid, message, sender); return(InboxDirective.Default); case MessageDirectiveType.ForwardToProcess: tell((directive as ForwardToProcess).ProcessId, message, sender); return(InboxDirective.Default); case MessageDirectiveType.StayInQueue: return(InboxDirective.PushToFrontOfQueue); default: tell(ActorContext.DeadLetters, DeadLetter.create(sender, pid, e, "Process error: ", message)); return(InboxDirective.Default); } }
/// <summary> /// Creates a new State computation that is primed with the data of a particular /// failure event. /// </summary> /// <param name="strategy">Strategy as a State computation</param> /// <param name="pid">Process ID that failed</param> /// <param name="sender">Process that sent the message that cause the failure</param> /// <param name="parent">Supervisor of the failed Process</param> /// <param name="siblings">The siblings of the failed Process</param> /// <param name="ex">Exception</param> /// <param name="msg">Message that caused the failure</param> /// <returns>State computation that can be invoked by passing it /// an object of StrategyState. This will result in a StateResult that contains /// the mutated StrategyState and a StrategyDecision. The StrategyDecision /// contains all the information needed to decide the fate of a Process (and /// related processes)</returns> public static State<StrategyState, StrategyDecision> Failure( this State<StrategyContext, Unit> strategy, ProcessId pid, ProcessId sender, ProcessId parent, IEnumerable<ProcessId> siblings, Exception ex, object msg ) { return stateInst => { var now = DateTime.UtcNow; var state = strategy(StrategyContext.Empty.With( Global: stateInst.With(Failures: stateInst.Failures + 1), FailedProcess: pid, ParentProcess: parent, Sender: sender, Siblings: siblings, Exception: ex, Message: msg)).State; var decision = new StrategyDecision( state.Directive.IfNone(Directive.Restart), state.MessageDirective.IfNone(MessageDirective.ForwardToDeadLetters), state.Affects, state.Pause ); return StateResult.Return(state.Global.With(LastFailure: now), decision); }; }
void RunProcessDirective( ProcessId pid, ProcessId sender, Exception e, object message, StrategyDecision decision ) { var directive = decision.ProcessDirective; // Find out the processes that this strategy affects and apply foreach (var cpid in decision.Affects.Filter(x => x != pid)) { switch (directive.Type) { case DirectiveType.Escalate: case DirectiveType.Resume: unpause(cpid); break; case DirectiveType.Restart: restart(cpid); break; case DirectiveType.Stop: kill(cpid); break; } } unpause(pid); switch (directive.Type) { case DirectiveType.Escalate: tellSystem(Parent.Actor.Id, SystemMessage.ChildFaulted(pid, sender, e, message), Self); break; case DirectiveType.Resume: // Do nothing break; case DirectiveType.Restart: Restart(); break; case DirectiveType.Stop: ShutdownProcess(false); break; } }