Unit DoScheduleNoIO(object message, ProcessId sender, Schedule schedule, Message.Type type, Message.TagSpec tag)
        {
            var inboxKey = ActorInboxCommon.ClusterScheduleKey(ProcessId);
            var id       = schedule.Key ?? Guid.NewGuid().ToString();
            var current  = Cluster.GetHashField <RemoteMessageDTO>(inboxKey, id);

            message = current.Match(
                Some: last =>
            {
                var a = MessageSerialiser.DeserialiseMsg(last, ProcessId) as UserMessage;
                var m = a == null
                        ? message
                        : schedule.Fold(a.Content, message);
                return(m);
            },
                None: () => schedule.Fold(schedule.Zero, message));

            ValidateMessageType(message, sender);

            var dto = RemoteMessageDTO.Create(message, ProcessId, sender, type, tag, SessionId, schedule.Due.Ticks);

            tell(ProcessId.Take(1).Child("system").Child("scheduler"), Scheduler.Msg.AddToSchedule(inboxKey, id, dto));

            //Cluster.HashFieldAddOrUpdate(inboxKey, id, dto);
            return(unit);
        }
 public Unit TellSystem(SystemMessage message, ProcessId sender) =>
 transactionalIO
         ? ignore(Cluster.PublishToChannel(
                      ActorInboxCommon.ClusterSystemInboxNotifyKey(ProcessId),
                      RemoteMessageDTO.Create(message, ProcessId, sender, Message.Type.System, message.Tag, SessionId, 0)))
         : ProcessOp.IO(() =>
 {
     var clientsReached = Cluster.PublishToChannel(
         ActorInboxCommon.ClusterSystemInboxNotifyKey(ProcessId),
         RemoteMessageDTO.Create(message, ProcessId, sender, Message.Type.System, message.Tag, SessionId, 0));
     return(unit);
 });
        Unit TellNoIO(object message, ProcessId sender, string inbox, Message.Type type, Message.TagSpec tag)
        {
            ValidateMessageType(message, sender);
            var dto            = RemoteMessageDTO.Create(message, ProcessId, sender, type, tag, SessionId, 0);
            var inboxKey       = ActorInboxCommon.ClusterInboxKey(ProcessId, inbox);
            var inboxNotifyKey = ActorInboxCommon.ClusterInboxNotifyKey(ProcessId, inbox);

            Cluster.Enqueue(inboxKey, dto);
            var clientsReached = Cluster.PublishToChannel(inboxNotifyKey, dto.MessageId);

            return(unit);
        }
        static RemoteMessageDTO FixupPathsSystemPrefix(RemoteMessageDTO dto, SystemName system)
        {
            if (dto == null)
            {
                return(null);
            }

            // Fix up the paths so we know what system they belong to.
            dto.ReplyTo = String.IsNullOrEmpty(dto.ReplyTo) || dto.ReplyTo.StartsWith("//") ? dto.ReplyTo : $"//{system}{dto.ReplyTo}";
            dto.Sender  = String.IsNullOrEmpty(dto.Sender) || dto.Sender.StartsWith("//") ? dto.Sender : $"//{system}{dto.Sender}";
            dto.To      = String.IsNullOrEmpty(dto.To) || dto.To.StartsWith("//") ? dto.To : $"//{system}{dto.To}";
            return(dto);
        }
Beispiel #5
0
        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);
                msg.SessionId = dto.SessionId;
            }
            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)));
        }
        public static Message DeserialiseMsg(RemoteMessageDTO msg, ProcessId actorId)
        {
            var sys = actorId.System;

            msg = FixupPathsSystemPrefix(msg, sys);

            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, actorId, sender, msg.RequestId, content.GetType().AssemblyQualifiedName, msg.Exception == "RESPERR"));

            case Message.TagSpec.UserAsk:           return(new ActorRequest(DeserialiseMsgContent(msg), actorId, replyTo.SetSystem(sys), msg.RequestId));

            case Message.TagSpec.User:              return(new UserMessage(DeserialiseMsgContent(msg), sender.SetSystem(sys), replyTo.SetSystem(sys)));

            case Message.TagSpec.UserTerminated:    return(((TerminatedMessage)DeserialiseMsgContent(msg)).SetSystem(sys));

            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}");
        }
        private static object DeserialiseMsgContent(RemoteMessageDTO msg)
        {
            object content = null;

            if (msg.Content == null)
            {
                throw new Exception($"Message content is null from {msg.Sender}");
            }
            else
            {
                var contentType = Type.GetType(msg.ContentType);
                if (contentType == null)
                {
                    throw new Exception($"Can't resolve type: {msg.ContentType}");
                }

                content = Deserialise.Object(msg.Content, contentType);
            }

            return(content);
        }
Beispiel #8
0
        /// <summary>
        /// TODO: This is a combination of code in ActorCommon.GetNextMessage and
        ///       CheckRemoteInbox.  Some factoring is needed.
        /// </summary>
        void SysInbox(RemoteMessageDTO dto)
        {
            try
            {
                if (dto == null)
                {
                    // Failed to deserialise properly
                    return;
                }
                if (dto.Tag == 0 && dto.Type == 0)
                {
                    // Message is bad
                    tell(ActorContext.System(actor.Id).DeadLetters, DeadLetter.create(dto.Sender, actor.Id, null, "Failed to deserialise message: ", dto));
                    return;
                }
                var msg = MessageSerialiser.DeserialiseMsg(dto, actor.Id);

                try
                {
                    lock (sync)
                    {
                        ActorInboxCommon.SystemMessageInbox(actor, this, (SystemMessage)msg, parent);
                    }
                }
                catch (Exception e)
                {
                    var session = msg.SessionId == null
                        ? None
                        : Some(new SessionId(msg.SessionId));

                    ActorContext.System(actor.Id).WithContext(new ActorItem(actor, this, actor.Flags), parent, dto.Sender, msg as ActorRequest, msg, session, () => replyErrorIfAsked(e));
                    tell(ActorContext.System(actor.Id).DeadLetters, DeadLetter.create(dto.Sender, actor.Id, e, "Remote message inbox.", msg));
                    logSysErr(e);
                }
            }
            catch (Exception e)
            {
                logSysErr(e);
            }
        }
Beispiel #9
0
 public State Add(string key, string innerKey, RemoteMessageDTO msg) =>
 new State(Scheduled.Map(s => s.AddOrUpdate(key, innerKey, msg)));
Beispiel #10
0
 public AddToScheduleMsg(string inboxKey, string id, RemoteMessageDTO message)
 {
     InboxKey = inboxKey;
     Id       = id;
     Message  = message;
 }
Beispiel #11
0
 public static Msg AddToSchedule(string inboxKey, string id, RemoteMessageDTO message) =>
 new AddToScheduleMsg(inboxKey, id, message);
Beispiel #12
0
 public OutboundRelayMsg(ClientConnectionId connectionId, RemoteMessageDTO msg, ProcessId to, ProcessId sender, bool isAsk)
     :
     base(MsgTag.Outbound, connectionId, to, sender, isAsk)
 {
     Message = msg;
 }