PageRenderTime 46ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Agatha.Common/ResponseReceiver.cs

https://github.com/michaelaird/Agatha
C# | 172 lines | 143 code | 26 blank | 3 comment | 43 complexity | ccaf8c26c451c98c016a88749771ae1e MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Agatha.Common.Caching;
  5. namespace Agatha.Common
  6. {
  7. /// <summary>
  8. /// Originally written by Tom Ceulemans
  9. /// </summary>
  10. public class ResponseReceiver
  11. {
  12. private readonly Action<ReceivedResponses> responseReceivedCallback;
  13. private readonly Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccuredCallback;
  14. private readonly Action<ExceptionInfo> exceptionOccurredCallback;
  15. private readonly Dictionary<string, int> keyToResultPositions;
  16. private readonly ICacheManager cacheManager;
  17. public ResponseReceiver(Action<ReceivedResponses> responseReceivedCallback, Action<ExceptionInfo> exceptionOccurredCallback,
  18. Dictionary<string, int> keyToResultPositions, ICacheManager cacheManager)
  19. {
  20. if (responseReceivedCallback == null) throw new ArgumentNullException("responseReceivedCallback");
  21. if (exceptionOccurredCallback == null) throw new ArgumentNullException("exceptionOccurredCallback");
  22. this.responseReceivedCallback = responseReceivedCallback;
  23. this.exceptionOccurredCallback = exceptionOccurredCallback;
  24. this.keyToResultPositions = keyToResultPositions;
  25. this.cacheManager = cacheManager;
  26. }
  27. public ResponseReceiver(
  28. Action<ReceivedResponses> responseReceivedCallback,
  29. Action<ExceptionInfo, ExceptionType> exceptionAndTypeOccuredCallback,
  30. Dictionary<string, int> keyToResultPositions, ICacheManager cacheManager)
  31. {
  32. if (responseReceivedCallback == null) throw new ArgumentNullException("responseReceivedCallback");
  33. if (exceptionAndTypeOccuredCallback == null) throw new ArgumentNullException("exceptionAndTypeOccuredCallback");
  34. this.responseReceivedCallback = responseReceivedCallback;
  35. this.exceptionAndTypeOccuredCallback = exceptionAndTypeOccuredCallback;
  36. this.keyToResultPositions = keyToResultPositions;
  37. this.cacheManager = cacheManager;
  38. }
  39. public void ReceiveResponses(ProcessRequestsAsyncCompletedArgs args, Response[] tempResponseArray, Request[] requestsToSendAsArray)
  40. {
  41. if (args == null)
  42. {
  43. responseReceivedCallback(new ReceivedResponses(tempResponseArray, keyToResultPositions));
  44. }
  45. else
  46. {
  47. if (HasException(args))
  48. {
  49. HandleException(args);
  50. }
  51. else
  52. {
  53. var disposable = responseReceivedCallback.Target as Disposable;
  54. if (disposable == null || !disposable.IsDisposed)
  55. {
  56. var receivedResponses = args.Result;
  57. AddCacheableResponsesToCache(receivedResponses, requestsToSendAsArray);
  58. PutReceivedResponsesInTempResponseArray(tempResponseArray, receivedResponses);
  59. responseReceivedCallback(new ReceivedResponses(tempResponseArray, keyToResultPositions));
  60. }
  61. }
  62. }
  63. }
  64. private void AddCacheableResponsesToCache(Response[] receivedResponses, Request[] requestsToSend)
  65. {
  66. if (cacheManager == null) return; //cacheManager should only be null during unit tests!
  67. for (int i = 0; i < receivedResponses.Length; i++)
  68. {
  69. if (receivedResponses[i].ExceptionType == ExceptionType.None && cacheManager.IsCachingEnabledFor(requestsToSend[i].GetType()))
  70. {
  71. cacheManager.StoreInCache(requestsToSend[i], receivedResponses[i]);
  72. }
  73. }
  74. }
  75. private void PutReceivedResponsesInTempResponseArray(Response[] tempResponseArray, Response[] receivedResponses)
  76. {
  77. int takeIndex = 0;
  78. for (int i = 0; i < tempResponseArray.Length; i++)
  79. {
  80. if (tempResponseArray[i] == null)
  81. {
  82. tempResponseArray[i] = receivedResponses[takeIndex++];
  83. }
  84. }
  85. }
  86. private void HandleException(ProcessRequestsAsyncCompletedArgs args)
  87. {
  88. var disposable = responseReceivedCallback.Target as Disposable;
  89. if (disposable == null || !disposable.IsDisposed)
  90. {
  91. var exception = GetException(args);
  92. if (exceptionOccurredCallback != null)
  93. {
  94. exceptionOccurredCallback(exception);
  95. }
  96. else if (exceptionAndTypeOccuredCallback != null)
  97. {
  98. var exceptionType = GetExceptionType(args);
  99. exceptionAndTypeOccuredCallback(exception, exceptionType);
  100. }
  101. else
  102. {
  103. responseReceivedCallback(new ReceivedResponses(args.Result, keyToResultPositions));
  104. }
  105. }
  106. }
  107. private static bool HasException(ProcessRequestsAsyncCompletedArgs args)
  108. {
  109. if (args.Error == null)
  110. {
  111. return args.Result.Any(r => r.Exception != null);
  112. }
  113. return true;
  114. }
  115. private static ExceptionInfo GetException(ProcessRequestsAsyncCompletedArgs args)
  116. {
  117. if (args.Error == null)
  118. {
  119. var responseWithException = GetFirstException(args.Result);
  120. if (responseWithException != null)
  121. {
  122. return responseWithException.Exception;
  123. }
  124. return null;
  125. }
  126. return new ExceptionInfo(args.Error);
  127. }
  128. private static ExceptionType GetExceptionType(ProcessRequestsAsyncCompletedArgs args)
  129. {
  130. if (args.Error == null)
  131. {
  132. var responseWithException = GetFirstException(args.Result);
  133. if (responseWithException != null)
  134. {
  135. return responseWithException.ExceptionType;
  136. }
  137. return ExceptionType.Unknown;
  138. }
  139. return ExceptionType.Unknown;
  140. }
  141. private static Response GetFirstException(IEnumerable<Response> responsesToCheck)
  142. {
  143. return responsesToCheck.FirstOrDefault(r => r.Exception != null);
  144. }
  145. }
  146. }