You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

98 lines
3.3 KiB

  1. using System;
  2. using System.Diagnostics;
  3. using System.Threading.Tasks;
  4. using DotNetCore.CAP.Models;
  5. using DotNetCore.CAP.Processor;
  6. using DotNetCore.CAP.Processor.States;
  7. using Microsoft.Extensions.Logging;
  8. namespace DotNetCore.CAP
  9. {
  10. public abstract class BasePublishQueueExecutor : IQueueExecutor
  11. {
  12. private readonly IStateChanger _stateChanger;
  13. private readonly ILogger _logger;
  14. protected BasePublishQueueExecutor(IStateChanger stateChanger,
  15. ILogger<BasePublishQueueExecutor> logger)
  16. {
  17. _stateChanger = stateChanger;
  18. _logger = logger;
  19. }
  20. public abstract Task<OperateResult> PublishAsync(string keyName, string content);
  21. public async Task<OperateResult> ExecuteAsync(IStorageConnection connection, IFetchedMessage fetched)
  22. {
  23. var message = await connection.GetPublishedMessageAsync(fetched.MessageId);
  24. try
  25. {
  26. var sp = Stopwatch.StartNew();
  27. await _stateChanger.ChangeStateAsync(message, new ProcessingState(), connection);
  28. if (message.Retries > 0)
  29. {
  30. _logger.JobRetrying(message.Retries);
  31. }
  32. var result = await PublishAsync(message.Name, message.Content);
  33. sp.Stop();
  34. var newState = default(IState);
  35. if (!result.Succeeded)
  36. {
  37. var shouldRetry = await UpdateMessageForRetryAsync(message, connection);
  38. if (shouldRetry)
  39. {
  40. newState = new ScheduledState();
  41. _logger.JobFailedWillRetry(result.Exception);
  42. }
  43. else
  44. {
  45. newState = new FailedState();
  46. _logger.JobFailed(result.Exception);
  47. }
  48. }
  49. else
  50. {
  51. newState = new SucceededState();
  52. }
  53. await _stateChanger.ChangeStateAsync(message, newState, connection);
  54. fetched.RemoveFromQueue();
  55. if (result.Succeeded)
  56. {
  57. _logger.JobExecuted(sp.Elapsed.TotalSeconds);
  58. }
  59. return OperateResult.Success;
  60. }
  61. catch (Exception ex)
  62. {
  63. _logger.ExceptionOccuredWhileExecutingJob(message?.Name, ex);
  64. return OperateResult.Failed(ex);
  65. }
  66. }
  67. private async Task<bool> UpdateMessageForRetryAsync(CapPublishedMessage message, IStorageConnection connection)
  68. {
  69. var retryBehavior = RetryBehavior.DefaultRetry;
  70. var now = DateTime.Now;
  71. var retries = ++message.Retries;
  72. if (retries >= retryBehavior.RetryCount)
  73. {
  74. return false;
  75. }
  76. var due = message.Added.AddSeconds(retryBehavior.RetryIn(retries));
  77. message.ExpiresAt = due;
  78. using (var transaction = connection.CreateTransaction())
  79. {
  80. transaction.UpdateMessage(message);
  81. await transaction.CommitAsync();
  82. }
  83. return true;
  84. }
  85. }
  86. }