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); }
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); }
/// <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); } }
public State Add(string key, string innerKey, RemoteMessageDTO msg) => new State(Scheduled.Map(s => s.AddOrUpdate(key, innerKey, msg)));
public AddToScheduleMsg(string inboxKey, string id, RemoteMessageDTO message) { InboxKey = inboxKey; Id = id; Message = message; }
public static Msg AddToSchedule(string inboxKey, string id, RemoteMessageDTO message) => new AddToScheduleMsg(inboxKey, id, message);
public OutboundRelayMsg(ClientConnectionId connectionId, RemoteMessageDTO msg, ProcessId to, ProcessId sender, bool isAsk) : base(MsgTag.Outbound, connectionId, to, sender, isAsk) { Message = msg; }