PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/MassTransit/Automatonymous/Activities/FaultRequestActivity.cs

http://github.com/MassTransit/MassTransit
C# | 187 lines | 139 code | 48 blank | 0 comment | 11 complexity | 7bbf3c4b53ee6d8e04b8dd896de9da73 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. namespace Automatonymous.Activities
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Xml.Linq;
  10. using Contracts;
  11. using GreenPipes;
  12. using MassTransit;
  13. using MassTransit.Serialization;
  14. using Newtonsoft.Json;
  15. using Newtonsoft.Json.Linq;
  16. using Requests;
  17. public class FaultRequestActivity :
  18. Activity<RequestState, RequestFaulted>
  19. {
  20. public void Probe(ProbeContext context)
  21. {
  22. context.CreateScope("faultRequest");
  23. }
  24. public void Accept(StateMachineVisitor visitor)
  25. {
  26. visitor.Visit(this);
  27. }
  28. public async Task Execute(BehaviorContext<RequestState, RequestFaulted> context, Behavior<RequestState, RequestFaulted> next)
  29. {
  30. ConsumeEventContext<RequestState, RequestFaulted> consumeContext = context.CreateConsumeContext();
  31. if (!context.Instance.ExpirationTime.HasValue || context.Instance.ExpirationTime.Value > DateTime.UtcNow)
  32. {
  33. string body = GetResponseBody(consumeContext, context.Instance);
  34. IPipe<SendContext> pipe = new FaultedMessagePipe(context.GetPayload<ConsumeContext>(), context.Instance, body);
  35. var endpoint = await context.GetSendEndpoint(context.Instance.ResponseAddress).ConfigureAwait(false);
  36. var scheduled = new FaultedEvent();
  37. await endpoint.Send(scheduled, pipe).ConfigureAwait(false);
  38. }
  39. await next.Execute(context).ConfigureAwait(false);
  40. }
  41. public Task Faulted<TException>(BehaviorExceptionContext<RequestState, RequestFaulted, TException> context,
  42. Behavior<RequestState, RequestFaulted> next)
  43. where TException : Exception
  44. {
  45. return next.Faulted(context);
  46. }
  47. static string GetResponseBody(ConsumeContext context, RequestState requestState)
  48. {
  49. string body = Encoding.UTF8.GetString(context.ReceiveContext.GetBody());
  50. var mediaType = context.ReceiveContext.ContentType?.MediaType;
  51. if (JsonMessageSerializer.JsonContentType.MediaType.Equals(mediaType, StringComparison.OrdinalIgnoreCase))
  52. return TranslateJsonBody(body, requestState);
  53. if (XmlMessageSerializer.XmlContentType.MediaType.Equals(mediaType, StringComparison.OrdinalIgnoreCase))
  54. return TranslateXmlBody(body, requestState);
  55. throw new InvalidOperationException("Only JSON and XML messages can be scheduled");
  56. }
  57. static string TranslateJsonBody(string body, RequestState requestState)
  58. {
  59. JObject envelope = JObject.Parse(body);
  60. envelope["destinationAddress"] = requestState.ResponseAddress.ToString();
  61. JToken message = envelope["message"];
  62. JToken payload = message["payload"];
  63. JToken payloadType = message["payloadType"];
  64. envelope["message"] = payload;
  65. envelope["messageType"] = payloadType;
  66. if (requestState.ConversationId.HasValue)
  67. envelope["conversationId"] = requestState.ConversationId.Value.ToString("D");
  68. envelope["sourceAddress"] = requestState.SagaAddress.ToString();
  69. envelope["requestId"] = requestState.CorrelationId.ToString("D");
  70. if (requestState.FaultAddress != null)
  71. envelope["faultAddress"] = requestState.FaultAddress.ToString();
  72. return JsonConvert.SerializeObject(envelope, Formatting.Indented);
  73. }
  74. static string TranslateXmlBody(string body, RequestState requestState)
  75. {
  76. using (var reader = new StringReader(body))
  77. {
  78. XDocument document = XDocument.Load(reader);
  79. XElement envelope = (from e in document.Descendants("envelope") select e).Single();
  80. XElement destinationAddress = (from a in envelope.Descendants("destinationAddress") select a).Single();
  81. XElement message = (from m in envelope.Descendants("message") select m).Single();
  82. IEnumerable<XElement> messageType = (from mt in envelope.Descendants("messageType") select mt);
  83. XElement payload = (from p in message.Descendants("payload") select p).Single();
  84. IEnumerable<XElement> payloadType = (from pt in message.Descendants("payloadType") select pt);
  85. message.Remove();
  86. messageType.Remove();
  87. if (requestState.ConversationId.HasValue)
  88. {
  89. XElement conversationId = (from a in envelope.Descendants("conversationId") select a).Single();
  90. conversationId.Value = requestState.ConversationId.Value.ToString("D");
  91. }
  92. destinationAddress.Value = requestState.ResponseAddress.ToString();
  93. XElement sourceAddress = (from a in envelope.Descendants("sourceAddress") select a).Single();
  94. sourceAddress.Value = requestState.SagaAddress.ToString();
  95. message = new XElement("message");
  96. message.Add(payload.Descendants());
  97. envelope.Add(message);
  98. envelope.Add(payloadType.Select(x => new XElement("messageType", x.Value)));
  99. envelope.Add(new XElement("requestId", requestState.CorrelationId.ToString("D")));
  100. if (requestState.FaultAddress != null)
  101. envelope.Add(new XElement("faultAddress", requestState.FaultAddress.ToString()));
  102. return document.ToString(SaveOptions.DisableFormatting);
  103. }
  104. }
  105. class FaultedEvent
  106. {
  107. }
  108. class FaultedMessagePipe :
  109. IPipe<SendContext>
  110. {
  111. readonly ConsumeContext _context;
  112. readonly RequestState _instance;
  113. readonly string _body;
  114. public FaultedMessagePipe(ConsumeContext context, RequestState instance, string body)
  115. {
  116. _context = context;
  117. _instance = instance;
  118. _body = body;
  119. }
  120. void IProbeSite.Probe(ProbeContext context)
  121. {
  122. }
  123. public async Task Send(SendContext context)
  124. {
  125. context.DestinationAddress = _instance.ResponseAddress;
  126. context.SourceAddress = _instance.SagaAddress;
  127. context.FaultAddress = _instance.FaultAddress;
  128. context.RequestId = _instance.CorrelationId;
  129. if (_instance.ExpirationTime.HasValue)
  130. {
  131. var timeToLive = DateTime.UtcNow - _instance.ExpirationTime.Value;
  132. context.TimeToLive = timeToLive > TimeSpan.Zero ? timeToLive : TimeSpan.FromSeconds(1);
  133. }
  134. var bodySerializer = new StringMessageSerializer(_context.ReceiveContext.ContentType, _body);
  135. context.Serializer = bodySerializer;
  136. }
  137. }
  138. }
  139. }