public Option <T> PreProcessMessageContent(object message) { if (message == null) { tell(sys.DeadLetters, DeadLetter.create(Sender, Self, $"Message is null for tell (expected {typeof(T)})", message)); return(None); } if (typeof(T) != typeof(string) && message is string) { try { // This allows for messages to arrive from JS and be dealt with at the endpoint // (where the type is known) rather than the gateway (where it isn't) return(Some(Deserialise.Object <T>((string)message))); } catch { tell(sys.DeadLetters, DeadLetter.create(Sender, Self, $"Invalid message type for tell (expected {typeof(T)})", message)); return(None); } } if (!(message is T)) { tell(sys.DeadLetters, DeadLetter.create(Sender, Self, $"Invalid message type for tell (expected {typeof(T)})", message)); return(None); } return(Some((T)message)); }
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: if (!(e is ProcessKillException)) { tell(sys.DeadLetters, DeadLetter.create(sender, pid, e, "Process error: ", message)); } return(InboxDirective.Default); } }
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 req) { 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)})"), sender, self, req.RequestId, typeof(Exception).AssemblyQualifiedName, true ), self ); return(None); } return(Optional((UserControlMessage)message)); } return(new UserMessage(message, sender, sender)); }
/// <summary> /// Forward the current message to dead-letters (and wrap it in a contextual dead-letter /// structre) /// </summary> /// <param name="ex">Exception that caused the dead-letter</param> public static Unit dead(Exception ex, SystemName system = default(SystemName)) => tell( ActorContext.System(system).DeadLetters, DeadLetter.create( Sender, Self, ex, ActorContext.Request.CurrentMsg ));
/// <summary> /// Forward the current message to dead-letters (and wrap it in a contextual dead-letter /// structre) /// </summary> /// <param name="reason">Reason for the dead-letter</param> public static Unit dead(string reason, SystemName system = default(SystemName)) => tell( ActorContext.System(system).DeadLetters, DeadLetter.create( Sender, Self, reason, ActorContext.Request.CurrentMsg ));
/// <summary> /// Forward a message to dead-letters (and wrap it in a contextual dead-letter /// structre) /// </summary> /// <param name="message">Dead letter message</param> /// <param name="ex">Exception that caused the dead-letter</param> public static Unit dead(object message, Exception ex, SystemName system = default(SystemName)) => tell( ActorContext.System(system).DeadLetters, DeadLetter.create( Sender, Self, ex, message ));
/// <summary> /// Forward a message to dead-letters (and wrap it in a contextual dead-letter /// structre) /// </summary> /// <param name="message">Dead letter message</param> /// <param name="reason">Reason for the dead-letter</param> public static Unit dead(object message, string reason, SystemName system = default(SystemName)) => tell( ActorContext.System(system).DeadLetters, DeadLetter.create( Sender, Self, reason, message ));
void CheckRemoteInbox(string key, bool pausable) { var inbox = this; var count = cluster?.QueueLength(key) ?? 0; while (count > 0 && (!pausable || !IsPaused)) { var directive = InboxDirective.Default; ActorInboxCommon.GetNextMessage(cluster, actor.Id, key).IfSome( x => iter(x, (dto, msg) => { try { switch (msg.MessageType) { case Message.Type.User: directive = ActorInboxCommon.UserMessageInbox(actor, inbox, (UserControlMessage)msg, parent); break; case Message.Type.UserControl: directive = ActorInboxCommon.UserMessageInbox(actor, inbox, (UserControlMessage)msg, parent); break; } } catch (Exception e) { var session = msg.SessionId == null ? None : Some(new SessionId(msg.SessionId)); ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, 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); } finally { if ((directive & InboxDirective.Pause) != 0) { IsPaused = true; directive = directive & (~InboxDirective.Pause); } if (directive == InboxDirective.Default) { cluster?.Dequeue <RemoteMessageDTO>(key); } } })); if (directive == InboxDirective.Default) { count--; } } }
public static Option <UserControlMessage> PreProcessMessage <T>(ProcessId sender, ProcessId self, object message, Option <SessionId> sessionId) { 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); } UserControlMessage rmsg = null; if (message is ActorRequest req) { 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)})"), sender, self, req.RequestId, typeof(Exception).AssemblyQualifiedName, true ), Schedule.Immediate, self ); return(None); } rmsg = message as UserControlMessage; } else { rmsg = new UserMessage(message, sender, sender); } if (rmsg != null && rmsg.SessionId == null && sessionId.IsSome) { rmsg.SessionId = sessionId.Map(x => x.Value).IfNoneUnsafe((string)null); } return(Optional(rmsg)); }
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))); }
/// <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); } }