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)); }
/// <summary> /// Support for unit testing message serialisation /// </summary> public static Validation <string, Msg> WillMyMessageSerialise <Msg>(Msg msg) { try { var json = JsonConvert.SerializeObject(msg, ActorSystemConfig.Default.JsonSerializerSettings); try { var msg2 = (Msg)Deserialise.Object(json, typeof(Msg)); if (msg2 == null) { return(Fail <string, Msg>($"{typeof(Msg)} failed to deserialise")); } else { return(Success <string, Msg>(msg2)); } } catch (Exception e2) { return(Fail <string, Msg>($"{typeof(Msg)} failed to deserialise: {e2.Message}")); } } catch (Exception e1) { return(Fail <string, Msg>($"{typeof(Msg)} failed to serialise: {e1.Message}")); } }
public static Either <string, object> IsMessageValidForProcess(object message, Type[] inboxDeclaredType) { if (message == null) { return(Left <string, object>("Message invalid (null)")); } var result = IsMessageValidForProcess(message.GetType(), inboxDeclaredType); if (result.IsRight && result.IfLeft(false)) { return(result.Map(_ => message)); } else { if (message is string) { foreach (var type in inboxDeclaredType) { var value = Deserialise.Object((string)message, type); if (value != null) { return(Right <string, object>(value)); } } return(Left <string, object>("Message-type (" + message.GetType().FullName + ") is string, but couldn't convert it to any inbox supported type: " + String.Join(", ", inboxDeclaredType.Map(x => x.FullName)))); } else { return(Left <string, object>("Message-type (" + message.GetType().FullName + ") doesn't match inbox declared type: " + String.Join(", ", inboxDeclaredType.Map(x => x.FullName)))); } } }
static S ProxyMsgInbox <S>(S process, ProxyMsg msg) { var types = msg.ArgTypes.Map(Type.GetType).ToArray(); var args = msg.Args.Map((i, x) => Deserialise.Object(x, types[i])).ToArray(); var method = process.GetType().GetTypeInfo().GetMethod(msg.Method, types); var result = method.Invoke(process, args); if (msg.ReturnType != "System.Void" && notnull(result)) { replyOrTellSender(result); } return(process); }
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); }
public static Tuple <long, Dictionary <long, AskActorReq> > Inbox(Tuple <long, Dictionary <long, AskActorReq> > state, object msg) { var reqId = state.Item1; var dict = state.Item2; if (msg is AskActorReq) { reqId++; var req = (AskActorReq)msg; ActorContext.System(req.To).Ask(req.To, new ActorRequest(req.Message, req.To, Self, reqId), Self); dict.Add(reqId, req); } else { var res = (ActorResponse)msg; if (dict.ContainsKey(res.RequestId)) { var req = dict[res.RequestId]; try { if (res.IsFaulted) { Exception ex = null; // Let's be reeeally safe here and do everything we can to get some valid information out of // the response to report to the process doing the 'ask'. try { var msgtype = req.ReplyType; if (msgtype == res.Message.GetType() && typeof(Exception).GetTypeInfo().IsAssignableFrom(msgtype.GetTypeInfo())) { // Type is fine, just return it as an error ex = (Exception)res.Message; } else { if (res.Message is string) { ex = (Exception)Deserialise.Object(res.Message.ToString(), msgtype); } else { ex = (Exception)Deserialise.Object(JsonConvert.SerializeObject(res.Message), msgtype); } } } catch { ex = new Exception(res.Message?.ToString() ?? $"An unknown error was thrown by {req.To}"); } req.Complete(new AskActorRes(new ProcessException($"Process issue: {ex.Message}", req.To.Path, req.ReplyTo.Path, ex), req.ReplyType)); } else { req.Complete(new AskActorRes(res.Message, req.ReplyType)); } } catch (Exception e) { req.Complete(new AskActorRes(new ProcessException($"Process issue: {e.Message}", req.To.Path, req.ReplyTo.Path, e), req.ReplyType)); logSysErr(e); } finally { dict.Remove(res.RequestId); } } else { logWarn($"Request ID doesn't exist: {res.RequestId}"); } } return(new Tuple <long, Dictionary <long, AskActorReq> >(reqId, dict)); }