public InboxDirective ProcessTerminated(ProcessId pid) { if (termFn == null) { return(InboxDirective.Default); } lock (sync) { var savedReq = ActorContext.CurrentRequest; var savedFlags = ActorContext.ProcessFlags; var savedMsg = ActorContext.CurrentMsg; try { ActorContext.CurrentRequest = null; ActorContext.ProcessFlags = flags; ActorContext.CurrentMsg = pid; //ActorContext.AssertSession(); var stateIn = GetState(); var stateOut = termFn(GetState(), pid); state = stateOut; try { if (notnull(stateOut) && !state.Equals(stateIn)) { stateSubject.OnNext(stateOut); } } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } strategyState = strategyState.With( Failures: 0, LastFailure: DateTime.MaxValue, BackoffAmount: 0 * seconds ); ActorContext.RunContextOps(); } catch (Exception e) { return(DefaultErrorHandler(pid, e)); } finally { ActorContext.CurrentRequest = savedReq; ActorContext.ProcessFlags = savedFlags; ActorContext.CurrentMsg = savedMsg; } return(InboxDirective.Default); } }
S InitState() { S state; try { SetupRemoteSubscriptions(cluster, flags); if (cluster.IsSome && ((flags & ProcessFlags.PersistState) == ProcessFlags.PersistState)) { try { logInfo($"Restoring state: {StateKey}"); state = cluster.LiftUnsafe().Exists(StateKey) ? cluster.LiftUnsafe().GetValue <S>(StateKey) : setupFn(this); } catch (Exception e) { logSysErr(e); state = setupFn(this); } } else { state = setupFn(this); } ActorContext.RunContextOps(); } catch (Exception e) { throw new ProcessSetupException(Id.Path, e); } try { stateSubject.OnNext(state); } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } return(state); }
InboxDirective DefaultErrorHandler(object message, Exception e) { // Wipe all transactional outputs because of the error ActorContext.Context = ActorContext.Context.SetOps(ProcessOpTransaction.Start(Id)); var directive = RunStrategy( Id, Parent.Actor.Id, Sender, Parent.Actor.Children.Values.Map(n => n.Actor.Id).Filter(x => x != Id), e, message, Parent.Actor.Strategy ); if (!(e is ProcessKillException)) { tell(ActorContext.Errors, e); } // Run any transactional outputs caused by the strategy computation ActorContext.RunContextOps(); return(directive); }
/// <summary> /// Process an inbox message /// </summary> /// <param name="message"></param> /// <returns></returns> public InboxDirective ProcessMessage(object message) { lock (sync) { var savedReq = ActorContext.CurrentRequest; var savedFlags = ActorContext.ProcessFlags; var savedMsg = ActorContext.CurrentMsg; try { ActorContext.CurrentRequest = null; ActorContext.ProcessFlags = flags; ActorContext.CurrentMsg = message; if (typeof(T) != typeof(string) && message is string) { state = PreProcessMessageContent(message).Match( Some: tmsg => { var stateIn = GetState(); var stateOut = actorFn(stateIn, tmsg); try { if (notnull(stateOut) && !stateOut.Equals(stateIn)) { stateSubject.OnNext(stateOut); } } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } return(stateOut); }, None: () => state ); } else if (message is T) { var stateIn = GetState(); var stateOut = actorFn(GetState(), (T)message); state = stateOut; try { if (notnull(stateOut) && !state.Equals(stateIn)) { stateSubject.OnNext(stateOut); } } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } } else if (message is Message) { ProcessSystemMessage((Message)message); } else { logErr($"Can't tell {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {message}"); return(InboxDirective.Default); } strategyState = strategyState.With( Failures: 0, LastFailure: DateTime.MaxValue, BackoffAmount: 0 * seconds ); ActorContext.RunContextOps(); } catch (Exception e) { return(DefaultErrorHandler(message, e)); } finally { ActorContext.CurrentRequest = savedReq; ActorContext.ProcessFlags = savedFlags; ActorContext.CurrentMsg = savedMsg; } return(InboxDirective.Default); } }
public InboxDirective ProcessAsk(ActorRequest request) { lock (sync) { var savedMsg = ActorContext.CurrentMsg; var savedFlags = ActorContext.ProcessFlags; var savedReq = ActorContext.CurrentRequest; try { ActorContext.CurrentRequest = request; ActorContext.ProcessFlags = flags; ActorContext.CurrentMsg = request.Message; //ActorContext.AssertSession(); if (typeof(T) != typeof(string) && request.Message is string) { state = PreProcessMessageContent(request.Message).Match( Some: tmsg => { var stateIn = GetState(); var stateOut = actorFn(stateIn, tmsg); try { if (notnull(stateOut) && !stateOut.Equals(stateIn)) { stateSubject.OnNext(stateOut); } } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } return(stateOut); }, None: () => { replyError(new AskException($"Can't ask {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {request.Message}")); return(state); } ); } else if (request.Message is T) { var msg = (T)request.Message; var stateIn = GetState(); var stateOut = actorFn(stateIn, msg); try { if (notnull(stateOut) && !stateOut.Equals(stateIn)) { stateSubject.OnNext(stateOut); } } catch (Exception ue) { // Not our errors, so just log and move on logErr(ue); } state = stateOut; } else if (request.Message is Message) { ProcessSystemMessage((Message)request.Message); } else { // Failure to deserialise is not our problem, its the sender's // so we don't throw here. replyError(new AskException($"Can't ask {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {request.Message}")); return(InboxDirective.Default); } strategyState = strategyState.With( Failures: 0, LastFailure: DateTime.MaxValue, BackoffAmount: 0 * seconds ); ActorContext.RunContextOps(); } catch (Exception e) { replyError(e); return(DefaultErrorHandler(request, e)); } finally { ActorContext.CurrentMsg = savedMsg; ActorContext.ProcessFlags = savedFlags; ActorContext.CurrentRequest = savedReq; } return(InboxDirective.Default); } }