Exemplo n.º 1
0
        public static Message DeserialiseMsg(RemoteMessageDTO msg, ProcessId actorId)
        {
            var sender = String.IsNullOrEmpty(msg.Sender) ? ProcessId.NoSender : new ProcessId(msg.Sender);
            var replyTo = String.IsNullOrEmpty(msg.ReplyTo) ? ProcessId.NoSender : new ProcessId(msg.ReplyTo);

            switch ((Message.TagSpec)msg.Tag)
            {
                case Message.TagSpec.UserReply:
                    var content = DeserialiseMsgContent(msg);
                    return new ActorResponse(content, content.GetType().AssemblyQualifiedName, actorId, sender, msg.RequestId, msg.Exception == "RESPERR");

                case Message.TagSpec.UserAsk:           return new ActorRequest(DeserialiseMsgContent(msg), actorId, replyTo, msg.RequestId);
                case Message.TagSpec.User:              return new UserMessage(DeserialiseMsgContent(msg), sender, replyTo);
                case Message.TagSpec.UserTerminated:    return (TerminatedMessage)DeserialiseMsgContent(msg);

                case Message.TagSpec.GetChildren:       return UserControlMessage.GetChildren;
                case Message.TagSpec.StartupProcess:    return SystemMessage.StartupProcess;
                case Message.TagSpec.ShutdownProcess:   return (ShutdownProcessMessage)DeserialiseMsgContent(msg);

                case Message.TagSpec.Restart:           return SystemMessage.Restart;
                case Message.TagSpec.Pause:             return SystemMessage.Pause;
                case Message.TagSpec.Unpause:           return SystemMessage.Unpause;

                case Message.TagSpec.DispatchWatch:    return (SystemDispatchWatchMessage)DeserialiseMsgContent(msg);
                case Message.TagSpec.DispatchUnWatch:  return (SystemDispatchUnWatchMessage)DeserialiseMsgContent(msg);
                case Message.TagSpec.Watch:            return (SystemAddWatcherMessage)DeserialiseMsgContent(msg);
                case Message.TagSpec.UnWatch:          return (SystemRemoveWatcherMessage)DeserialiseMsgContent(msg);
            }

            throw new Exception($"Unknown Message Tag: {msg.Tag}");
        }
Exemplo n.º 2
0
        public static ProcessId Inbox(ProcessId hub, RelayMsg msg)
        {
            try
            {
                switch (msg.Tag)
                {
                    case RelayMsg.MsgTag.Connected:
                        SpawnConnection(msg, hub);
                        break;

                    case RelayMsg.MsgTag.Disconnected:
                        kill(Self[msg.ConnectionId]);
                        break;

                    case RelayMsg.MsgTag.Inbound:
                    case RelayMsg.MsgTag.Subscribe:
                    case RelayMsg.MsgTag.Unsubscribe:
                        fwd(SpawnConnection(msg, hub), msg);
                        break;
                }
            }
            catch (Exception e)
            {
                tell(Errors, e);
            }
            return hub;
        }
Exemplo n.º 3
0
 public SystemChildFaultedMessage(ProcessId child, ProcessId sender, Exception exception, object message)
 {
     Child = child;
     Sender = sender;
     Exception = exception;
     Message = message;
 }
Exemplo n.º 4
0
 public ActorRequest(object message, ProcessId to, ProcessId replyTo, long requestId)
 {
     Message = message;
     To = to;
     ReplyTo = replyTo;
     RequestId = requestId;
 }
Exemplo n.º 5
0
        StrategyContext(
            StrategyState global,
            Exception exception,
            object message,
            ProcessId sender,
            ProcessId failedProcess,
            ProcessId parentProcess,
            IEnumerable<ProcessId> siblings,
            IEnumerable<ProcessId> affects,
            Time pause,
            Option<Directive> directive,
            Option<MessageDirective> messageDirective
            )
        {
            bool isStop = directive == LanguageExt.Directive.Stop;

            Global = isStop ? StrategyState.Empty : global;
            Exception = exception;
            Message = message;
            Sender = sender;
            Self = failedProcess;
            ParentProcess = parentProcess;
            Siblings = siblings ?? Siblings;
            Affects = affects ?? Affects;
            Pause = isStop ? 0 * s : pause;
            Directive = directive;
            MessageDirective = messageDirective;
        }
Exemplo n.º 6
0
        /// <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);
            };
        }
 public ActorResponse(ProcessId replyTo, object message, ProcessId replyFrom, long requestId)
 {
     Message = message;
     ReplyTo = replyTo;
     ReplyFrom = replyFrom;
     RequestId = requestId;
 }
Exemplo n.º 8
0
 public AskActorReq(object msg, Subject<object> subject, ProcessId to, ProcessId replyTo)
 {
     Message = msg;
     Subject = subject;
     To = to;
     ReplyTo = replyTo;
 }
 internal static RemoteMessageDTO Create(object message, ProcessId to, ProcessId sender, Message.Type type, Message.TagSpec tag, Option<SessionId> sessionId) =>
     map(message as ActorRequest, req =>
         req == null
             ? map(message as ActorResponse, res =>
                 res == null
                     ? CreateMessage(message, to, sender, type, tag, sessionId)
                     : CreateResponse(res, to, sender, sessionId))
             : CreateRequest(req, to, sender, sessionId));
Exemplo n.º 10
0
 private DeadLetter(ProcessId sender, ProcessId recipient, Exception ex, string reason, object message)
 {
     Sender = sender;
     Recipient = recipient;
     Exception = Optional(ex);
     Reason = Optional(reason);
     Message = Optional(message);
 }
Exemplo n.º 11
0
 void SpawnResolver()
 {
     resolver = spawn<Map<ProcessId, BallState>, Tuple<ProcessId, BallState>>(
         "resolver",
         () => Map<ProcessId, BallState>(),
         Resolver.Inbox
     );
 }
Exemplo n.º 12
0
 public ActorResponse(object message, string responseMessageType, ProcessId replyTo, ProcessId replyFrom, long requestId, bool isFaulted = false)
 {
     Message = message;
     ResponseMessageType = responseMessageType;
     ReplyTo = replyTo;
     ReplyFrom = replyFrom;
     RequestId = requestId;
     IsFaulted = isFaulted;
 }
Exemplo n.º 13
0
 /// <summary>
 /// Shutdown the process log
 /// </summary>
 public static Unit shutdown()
 {
     if (processId.IsValid)
     {
         kill(processId);
         processId = ProcessId.None;
     }
     return unit;
 }
Exemplo n.º 14
0
        public static ProcessId ConnectionInbox(ProcessId hub, RelayMsg rmsg)
        {
            switch (rmsg.Tag)
            {
                case RelayMsg.MsgTag.Inbound:
                    var inmsg = rmsg as InboundRelayMsg;
                    if (rmsg.IsAsk)
                    {
                        // Ask not supported
                        tell(Errors, "'ask' not supported from JS to server.");
                    }
                    else
                    {
                        tell(rmsg.To, inmsg.Message, rmsg.Sender.IsValid ? Self.Append(rmsg.Sender) : ProcessId.NoSender);
                    }
                    break;

                case RelayMsg.MsgTag.Outbound:
                    fwd(hub, rmsg);
                    break;

                case RelayMsg.MsgTag.Subscribe:
                    var pid          = rmsg.To;
                    var subscriber   = rmsg.Sender;
                    var connectionId = rmsg.ConnectionId;

                    ActorContext.SelfProcess.Actor.AddSubscription(
                        rmsg.To,
                        ActorContext.Observe<object>(pid).Subscribe(x =>
                            tell(hub, 
                                 new OutboundRelayMsg(
                                     connectionId,
                                     new RemoteMessageDTO {
                                        MessageId   = Guid.NewGuid(),
                                        Content     = JsonConvert.SerializeObject(x),
                                        Sender      = pid.Path,
                                        To          = subscriber.Path,
                                        ContentType = x.GetType().AssemblyQualifiedName,
                                        ReplyTo     = pid.Path,
                                        Tag         = (int)Message.TagSpec.User,
                                        Type        = (int)Message.Type.User
                                     },
                                     subscriber,
                                     pid,
                                     false),
                                 pid)));
                    break;

                case RelayMsg.MsgTag.Unsubscribe:
                    ActorContext.SelfProcess.Actor.RemoveSubscription(rmsg.To);
                    break;
            }
            return hub;
        }
Exemplo n.º 15
0
 internal static ProcessId WatchWorkers(ProcessId router, IEnumerable<ProcessId> workers, RouterOption option)
 {
     if ((option & RouterOption.RemoveLocalWorkerWhenTerminated) == RouterOption.RemoveLocalWorkerWhenTerminated)
     {
         workers.Where(w => ActorContext.IsLocal(w)).Iter(w => watch(router, w));
     }
     if ((option & RouterOption.RemoveRemoteWorkerWhenTerminated) == RouterOption.RemoveRemoteWorkerWhenTerminated)
     {
         workers.Where(w => !ActorContext.IsLocal(w)).Iter(w => watch(router, w));
     }
     return router;
 }
Exemplo n.º 16
0
 public static Unit RemoveFromStore(ProcessId id)
 {
     lock (storeLock)
     {
         var path = id.Value;
         if (Store.ContainsKey(path))
         {
             Store = Store.Remove(path);
         }
     }
     return unit;
 }
Exemplo n.º 17
0
 public static Unit AddToStore(ProcessId id, IProcess process)
 {
     lock (storeLock)
     {
         var path = id.Value;
         if (Store.ContainsKey(path))
         {
             Store[path].Dispose();
             Store = Store.Remove(path);
         }
         Store = Store.Add(path, process);
     }
     return unit;
 }
Exemplo n.º 18
0
 internal static RemoteMessageDTO CreateRequest(ActorRequest req, ProcessId to, ProcessId sender) =>
     new RemoteMessageDTO()
     {
         Type        = (int)Message.Type.User,
         Tag         = (int)Message.TagSpec.UserAsk,
         Child       = null,
         Exception   = null,
         To          = to.Path,
         RequestId   = req.RequestId,
         MessageId   = Guid.NewGuid(),
         Sender      = sender.ToString(),
         ReplyTo     = req.ReplyTo.ToString(),
         ContentType = req.Message.GetType().AssemblyQualifiedName,
         Content     = JsonConvert.SerializeObject(req.Message, ActorConfig.Default.JsonSerializerSettings)
     };
Exemplo n.º 19
0
 public ActorRequestContext(
     ActorItem self,
     ProcessId sender,
     ActorItem parent,
     object currentMsg,
     ActorRequest currentRequest,
     ProcessFlags processFlags
     )
 {
     Self = self;
     Sender = sender;
     Parent = parent;
     CurrentMsg = currentMsg;
     CurrentRequest = currentRequest;
     ProcessFlags = processFlags;
 }
Exemplo n.º 20
0
        /// <summary>
        /// Start up the process log
        /// </summary>
        /// <param name="processNameOverride">Override the default process name</param>
        /// <param name="logViewMax">Size of the log 'window'</param>
        public static Unit startup(Option<ProcessName> processNameOverride, int logViewMax = 200)
        {
            if (processId.IsValid) return unit;
            lock (sync)
            {
                if (processId.IsValid) return unit;

                processName = processNameOverride.IfNone("process-log");
                processId = spawn<State, ProcessLogItem>(processName, () => setup(logViewMax), inbox);

                deadLetterSub = subscribe<DeadLetter>(DeadLetters, msg => tellWarning(msg.ToString()));
                errorSub = subscribe<Exception>(Errors, e => tellError(e));
            }

            return unit;
        }
Exemplo n.º 21
0
 internal static RemoteMessageDTO CreateMessage(object message, ProcessId to, ProcessId sender, Message.Type type, Message.TagSpec tag) =>
     new RemoteMessageDTO
     {
         Type        = (int)type,
         Tag         = (int)tag,
         To          = to.Path,
         RequestId   = -1,
         MessageId   = Guid.NewGuid(),
         Sender      = sender.ToString(),
         ReplyTo     = sender.ToString(),
         ContentType = message == null
                         ? null
                         : message.GetType().AssemblyQualifiedName,
         Content     = message == null
                         ? null
                         : JsonConvert.SerializeObject(message, ActorSystemConfig.Default.JsonSerializerSettings)
     };
Exemplo n.º 22
0
        static BallState Detect(ProcessId pidA, BallState stateA, ProcessId pidB, BallState stateB, BallState lastStateB)
        {
            if (pidA == pidB) return stateB;

            var a = new Point2(stateA.X, stateA.Y);
            var b = new Point2(stateB.X, stateB.Y);

            var avel = new Vector2(stateA.VelX.MetresPerSecond, stateA.VelY.MetresPerSecond);
            var bvel = new Vector2(stateB.VelX.MetresPerSecond, stateB.VelY.MetresPerSecond);

            Vector2 collision = a - b;
            double distance = collision.Length;
            if (distance == 0.0)
            {              
                // hack to avoid div by zero
                collision = new Vector2(1.0, 0.0);
                distance = 1.0;
            }
            if (distance > stateA.BallSize && distance > stateB.BallSize)
            {
                return stateB;
            }

            // Get the components of the velocity vectors which are parallel to the collision.
            // The perpendicular component remains the same for both fish
            collision = collision / distance;
            double aci = Vector2.Dot(avel, collision);
            double bci = Vector2.Dot(bvel, collision);

            // Solve for the new velocities using the 1-dimensional elastic collision equations.
            // Turns out it's really simple when the masses are the same.
            double acf = bci;
            double bcf = aci;

            // Replace the collision velocity components with the new ones
            var navel = avel + collision * (acf - aci);
            var nbvel = bvel + collision * (bcf - bci);

            SetPosAndVelMsg.Tell(pidA, a.X, a.Y, navel.DX*m/s, navel.DY*m/s);
            SetPosAndVelMsg.Tell(pidB, lastStateB.X, lastStateB.Y, nbvel.DX*m/s, nbvel.DY*m/s);

            return lastStateB;
        }
Exemplo n.º 23
0
        public static Message DeserialiseMsg(RemoteMessageDTO msg, ProcessId actorId)
        {
            var sender = String.IsNullOrEmpty(msg.Sender) ? ProcessId.NoSender : new ProcessId(msg.Sender);
            var replyTo = String.IsNullOrEmpty(msg.ReplyTo) ? ProcessId.NoSender : new ProcessId(msg.ReplyTo);

            switch ((Message.TagSpec)msg.Tag)
            {
                case Message.TagSpec.UserReply:
                    var content = DeserialiseMsgContent(msg);
                    return new ActorResponse(content, content.GetType().AssemblyQualifiedName, actorId, sender, msg.RequestId, msg.Exception == "RESPERR");

                case Message.TagSpec.UserAsk:           return new ActorRequest(DeserialiseMsgContent(msg), actorId, replyTo, msg.RequestId);
                case Message.TagSpec.User:              return new UserMessage(DeserialiseMsgContent(msg), sender, replyTo);

                case Message.TagSpec.GetChildren:       return UserControlMessage.GetChildren;
                case Message.TagSpec.ShutdownProcess:   return SystemMessage.ShutdownProcess;

                case Message.TagSpec.Restart:           return SystemMessage.Restart;
            }

            throw new Exception("Unknown Message Type: " + msg.Type);
        }
 public ActorRequestContext(
     ActorSystem system,
     ActorItem self,
     ProcessId sender,
     ActorItem parent,
     object currentMsg,
     ActorRequest currentRequest,
     ProcessFlags processFlags,
     ProcessOpTransaction ops,
     SessionVector session
     )
 {
     Self = self;
     Sender = sender;
     Parent = parent;
     CurrentMsg = currentMsg;
     CurrentRequest = currentRequest;
     ProcessFlags = processFlags;
     Ops = ops;
     System = system;
     Session = session;
 }
Exemplo n.º 25
0
        public StrategyContext With(
            StrategyState Global = null,
            Exception Exception = null,
            object Message = null,
            ProcessId? Sender = null,
            ProcessId? FailedProcess = null,
            ProcessId? ParentProcess = null,
            IEnumerable<ProcessId> Siblings = null,
            IEnumerable<ProcessId> Affects = null,
            Time? Pause = null,
            Option<Directive> Directive = default(Option<Directive>),
            Option<MessageDirective> MessageDirective = default(Option<MessageDirective>)
        ) =>
            new StrategyContext(
                Global ?? this.Global,
                Exception ?? this.Exception,
                Message ?? this.Message,
                Sender ?? this.Sender,
                FailedProcess ?? this.Self,
                ParentProcess ?? this.ParentProcess,
                Siblings ?? this.Siblings,
                Affects ?? this.Affects,
                Pause ?? this.Pause,

                // The following may look like bugs, but it's intentional that when
                // a Directive or MessageDirective is set, they stay set to their first
                // concrete value.  That means the State strategy expression that runs 
                // has the equivalent of an 'early out'.  The whole expression is still
                // processed, but you can't override the earlier value.
                this.Directive.IsSome
                    ? this.Directive
                    : Directive,
                this.MessageDirective.IsSome
                    ? this.MessageDirective
                    : MessageDirective
            );
Exemplo n.º 26
0
 public Unit DispatchUnWatch(ProcessId watching) =>
 TellSystem(SystemMessage.DispatchUnWatch(watching), watching);
Exemplo n.º 27
0
 /// <summary>
 /// Create a new dead letter
 /// </summary>
 public static DeadLetter create(ProcessId sender, ProcessId recipient, object message) =>
     new DeadLetter(sender, recipient, null, null, message);
Exemplo n.º 28
0
 public TerminatedMessage(ProcessId id)
 {
     Id = id;
 }
Exemplo n.º 29
0
 public Unit Tell(object message, ProcessId sender, Message.TagSpec tag) =>
 Tell(message, sender, "user", Message.Type.User, tag);
Exemplo n.º 30
0
 /// <summary>
 /// Subscribe to the process publish stream.  When a process calls 'publish' it emits
 /// messages that can be consumed using this method.
 /// </summary>
 /// <remarks>
 /// The process can publish any number of types, any published messages not of type T will be ignored.
 ///
 /// Because this call is asychronous it could allow access to the message loop, therefore
 /// you can't call it from within a process message loop.
 /// </remarks>
 /// <returns>IDisposable, call IDispose to end the subscription</returns>
 public static IDisposable subscribe <T>(ProcessId pid, Action <T> onNext, Action onComplete) =>
 InMessageLoop
         ? raiseDontUseInMessageLoopException <IDisposable>(nameof(subscribe))
         : observe <T>(pid).Subscribe(onNext, ex => { }, onComplete);
Exemplo n.º 31
0
 public Unit Tell(object message, ProcessId sender, string inbox, Message.Type type, Message.TagSpec tag) =>
 ProcessOp.IO(() => TellNoIO(message, sender, inbox, type, tag));
Exemplo n.º 32
0
 /// <summary>
 /// Subscribe to the process publish stream.  When a process calls 'publish' it emits
 /// messages that can be consumed using this method.
 /// </summary>
 /// <remarks>
 /// The process can publish any number of types, any published messages not of type T will be ignored.
 ///
 /// Because this call is asychronous it could allow access to the message loop, therefore
 /// you can't call it from within a process message loop.
 /// </remarks>
 /// <returns>IDisposable, call IDispose to end the subscription</returns>
 public static IDisposable subscribe <T>(ProcessId pid, IObserver <T> observer) =>
 InMessageLoop
         ? raiseDontUseInMessageLoopException <IDisposable>(nameof(subscribe))
         : observe <T>(pid).Subscribe(observer);
Exemplo n.º 33
0
 /// <summary>
 /// Subscribes our inbox to another process publish stream.  When it calls 'publish' it will
 /// arrive in our inbox.
 /// </summary>
 /// <param name="pid">Process to subscribe to</param>
 /// <remarks>
 /// The process can publish any number of types, any published messages not of type T will be ignored.
 ///
 /// This should be used from within a process' message loop only
 /// </remarks>
 /// <returns>IDisposable, call IDispose to end the subscription</returns>
 public static Unit subscribe(ProcessId pid) =>
 InMessageLoop
         ? ActorContext.SelfProcess.Actor.AddSubscription(pid, ActorContext.Observe <object>(pid).Subscribe(x => tell(Self, x, pid)))
         : raiseUseInMsgLoopOnlyException <Unit>(nameof(subscribe));
Exemplo n.º 34
0
 public Unit UnWatch(ProcessId pid) =>
 TellSystem(SystemMessage.UnWatch(pid), pid);
Exemplo n.º 35
0
        /// <summary>
        /// Spawn an update process that sends a time message to the ball
        /// process (via state subscription) every 60th of a second
        /// </summary>
        void SpawnUpdate()
        {
            update = spawn<DateTime, DateTime>("update", 
                () => DateTime.Now, 
                (state,time) => {
                    tellSelf(DateTime.Now, 1 * second / 60);
                    return time;
                });

            // Go!
            tell(update, DateTime.Now);
        }
Exemplo n.º 36
0
 /// <summary>
 /// Create a new dead letter
 /// </summary>
 public static DeadLetter create(ProcessId sender, ProcessId recipient, Exception ex, string reason, object message) =>
 new DeadLetter(sender, recipient, ex, reason, message);
Exemplo n.º 37
0
 public TerminatedMessage(ProcessId id)
 {
     Id = id;
 }
Exemplo n.º 38
0
 public UserMessage(object message, ProcessId sender, ProcessId replyTo)
 {
     Content = message;
     Sender  = sender;
     ReplyTo = replyTo;
 }
Exemplo n.º 39
0
 internal static RemoteMessageDTO CreateResponse(ActorResponse res, ProcessId to, ProcessId sender, Option <SessionId> sessionId) =>
 new RemoteMessageDTO
 {
     Type      = (int)Message.Type.User,
     Tag       = (int)Message.TagSpec.UserReply,
     Child     = null,
     Exception = res.IsFaulted
                         ? "RESPERR"
                         : null,
     To          = to.ToString(),
     RequestId   = res.RequestId,
     MessageId   = Guid.NewGuid(),
     Sender      = res.ReplyFrom.ToString(),
     ReplyTo     = res.ReplyTo.ToString(),
     ContentType = res.Message.GetType().AssemblyQualifiedName,
     Content     = JsonConvert.SerializeObject(res.Message, ActorSystemConfig.Default.JsonSerializerSettings),
     SessionId   = sessionId.Map(s => s.Value).IfNoneUnsafe(() => null)
 };
Exemplo n.º 40
0
 /// <summary>
 /// Ctor
 /// </summary>
 public ProcessInboxFullException(ProcessId pid, int maximumSize, string type)
     :
     base("Process (" + pid + ") " + type + " inbox is full (Maximum items: " + maximumSize + ")")
 {
 }
Exemplo n.º 41
0
 /// <summary>
 /// Ask a process for a reply
 /// </summary>
 /// <param name="pid">Process to ask</param>
 /// <param name="message">Message to send</param>
 /// <returns>The response to the request</returns>
 public static T ask <T>(ProcessId pid, object message) =>
 ActorContext.Ask <T>(pid, message);
 public static string ClusterMetaDataKey(ProcessId pid) =>
 ClusterKey(pid) + "-metadata";
Exemplo n.º 43
0
 /// <summary>
 /// Unsubscribe from a process's publications
 /// </summary>
 /// <param name="pid">Process to unsub from</param>
 public static Unit unsubscribe(ProcessId pid) =>
 InMessageLoop
         ? ActorContext.SelfProcess.Actor.RemoveSubscription(pid)
         : raiseUseInMsgLoopOnlyException <Unit>(nameof(unsubscribe));
 public static string ClusterSystemInboxNotifyKey(ProcessId pid) =>
 ClusterInboxNotifyKey(pid, "system");
Exemplo n.º 45
0
 /// <summary>
 /// Get an IObservable for a process's state stream.  When a process state updates at the end of its
 /// message loop it announces it on the stream returned from this method.  You should use this for
 /// notification only.  Never modify the state object belonging to a process.  Best practice is to make
 /// the state type immutable.
 /// </summary>
 /// <remarks>
 /// The process can publish any number of types, any published messages not of type T will be ignored.
 ///
 /// Because this call is asychronous it could allow access to the message loop, therefore
 /// you can't call it from within a process message loop.
 /// </remarks>
 /// <returns>IObservable T</returns>
 public static IObservable <T> observeState <T>(ProcessId pid) =>
 InMessageLoop
         ? raiseDontUseInMessageLoopException <IObservable <T> >(nameof(observeState))
         : ActorContext.ObserveState <T>(pid);
 public static string ClusterUserInboxNotifyKey(ProcessId pid) =>
 ClusterInboxNotifyKey(pid, "user");
Exemplo n.º 47
0
 /// <summary>
 /// Subscribe to the process publish stream.  When a process calls 'publish' it emits
 /// messages that can be consumed using this method.
 /// </summary>
 /// <remarks>
 /// The process can publish any number of types, any published messages not of type T will be ignored.
 ///
 /// Because this call is asychronous it could allow access to the message loop, therefore
 /// you can't call it from within a process message loop.
 /// </remarks>
 public static IDisposable subscribe <T>(ProcessId pid, Action <T> onNext, Action <Exception> onError) =>
 InMessageLoop
         ? raiseDontUseInMessageLoopException <IDisposable>(nameof(subscribe))
         : observe <T>(pid).Subscribe(onNext, onError, () => { });
 public static string ClusterInboxNotifyKey(ProcessId pid, string type) =>
 ClusterInboxKey(pid, type) + "-notify";
Exemplo n.º 49
0
 public Unit TellSystem(SystemMessage message, ProcessId sender) =>
 ProcessOp.IO(() =>
 {
     var dto            = RemoteMessageDTO.Create(message, ProcessId, sender, Message.Type.System, message.Tag, SessionId);
     var clientsReached = Cluster.PublishToChannel(ActorInboxCommon.ClusterSystemInboxNotifyKey(ProcessId), dto);
 });
 public static string ClusterInboxKey(ProcessId pid, string type) =>
 ClusterKey(pid) + "-" + type + "-inbox";
Exemplo n.º 51
0
 public Unit TellUserControl(UserControlMessage message, ProcessId sender) =>
 Tell(message, sender, "user", Message.Type.UserControl, message.Tag);
 public static string ClusterSettingsKey(ProcessId pid) =>
 ClusterKey(pid) + "@settings";
Exemplo n.º 53
0
 public ActorDispatchRemote(ProcessId pid, ICluster cluster, Option <SessionId> sessionId)
 {
     ProcessId = pid;
     Cluster   = cluster;
     SessionId = sessionId;
 }
 public static string ClusterKey(ProcessId pid) =>
 pid.Path;
Exemplo n.º 55
0
 /// <summary>
 /// Create a new dead letter
 /// </summary>
 public static DeadLetter create(ProcessId sender, ProcessId recipient, Exception ex, string reason, object message) =>
     new DeadLetter(sender, recipient, ex, reason, message);
        public static Option <Tuple <RemoteMessageDTO, Message> > GetNextMessage(ICluster cluster, ProcessId self, string key)
        {
            if (cluster == null)
            {
                return(None);
            }
            Message          msg = null;
            RemoteMessageDTO dto = null;

            dto = null;
            do
            {
                dto = cluster.Peek <RemoteMessageDTO>(key);
                if (dto == null)
                {
                    // Queue is empty
                    return(None);
                }
                if (dto.Tag == 0 && dto.Type == 0)
                {
                    // Message is bad
                    cluster.Dequeue <RemoteMessageDTO>(key);
                    tell(ActorContext.System(self).DeadLetters, DeadLetter.create(dto.Sender, self, null, "Failed to deserialise message: ", dto));
                    if (cluster.QueueLength(key) == 0)
                    {
                        return(None);
                    }
                }
            }while (dto == null || dto.Tag == 0 || dto.Type == 0);

            try
            {
                msg = MessageSerialiser.DeserialiseMsg(dto, self);
            }
            catch (Exception e)
            {
                // Message can't be deserialised
                cluster.Dequeue <RemoteMessageDTO>(key);
                tell(ActorContext.System(self).DeadLetters, DeadLetter.create(dto.Sender, self, e, "Failed to deserialise message: ", msg));
                return(None);
            }

            return(Some(Tuple(dto, msg)));
        }
Exemplo n.º 57
0
 private static string ProcessFmt(ProcessId pid) =>
     pid.IsValid
         ? pid.ToString()
         : "no-sender";
        public static Option <UserControlMessage> PreProcessMessage <T>(ProcessId sender, ProcessId self, object message)
        {
            if (message == null)
            {
                var emsg = $"Message is null for tell (expected {typeof(T)})";
                tell(ActorContext.System(self).DeadLetters, DeadLetter.create(sender, self, emsg, message));
                return(None);
            }

            if (message is ActorRequest)
            {
                var req = (ActorRequest)message;
                if (!(req.Message is T) && !(req.Message is Message))
                {
                    var emsg = $"Invalid message type for ask (expected {typeof(T)})";
                    tell(ActorContext.System(self).DeadLetters, DeadLetter.create(sender, self, emsg, message));

                    ActorContext.System(self).Tell(
                        sender,
                        new ActorResponse(new Exception($"Invalid message type for ask (expected {typeof(T)})"),
                                          typeof(Exception).AssemblyQualifiedName,
                                          sender,
                                          self,
                                          req.RequestId,
                                          true
                                          ),
                        self
                        );

                    return(None);
                }
                return(Optional((UserControlMessage)message));
            }

            return(new UserMessage(message, sender, sender));
        }
Exemplo n.º 59
0
 /// <summary>
 /// Create a new dead letter
 /// </summary>
 public static DeadLetter create(ProcessId sender, ProcessId recipient, object message) =>
 new DeadLetter(sender, recipient, null, null, message);
 public static string ClusterStatePubSubKey(ProcessId pid) =>
 ClusterKey(pid) + "-state-pubsub";