PageRenderTime 33ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/src/MassTransit/Automatonymous/Activities/CompleteRequestActivity.cs

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