ProcessingWorker.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using Quadarax.Application.QLiberace.Base.Services;
  2. using Quadarax.Application.QLiberace.Common.Executor;
  3. using Quadarax.Application.QLiberace.Processor.Entities;
  4. using Quadarax.Application.QLiberace.Processor.Enums;
  5. using Quadarax.Application.QLiberace.Processor.Executor;
  6. using Quadarax.Application.QLiberace.Processor.Repositories;
  7. using Quadarax.Application.QLiberace.Processor.Settings;
  8. using Quadarax.Foundation.Core.Business;
  9. using Quadarax.Foundation.Core.Logging;
  10. using Quadarax.Foundation.Core.Thread;
  11. namespace Quadarax.Application.QLiberace.Processor.Workers
  12. {
  13. internal class ProcessingWorker : QlbrcProcessorWorker
  14. {
  15. #region *** Private fields ***
  16. // TODO: may be shift to ProcessorSetting
  17. private const int CN_ITEMS_PER_CYCLE = 1;
  18. #endregion
  19. #region *** Properties ***
  20. #endregion
  21. #region *** Constructor ***
  22. public ProcessingWorker(IWorkerContext context, SettingsService? srvSettings, IQLogger logger) : base(context, srvSettings, srvSettings?.GetSettings<ProcessorSetting>(Base.Constants.Modules.Processor.Code)?.Value?.ProcessingWorkerPwi!, logger)
  23. {
  24. }
  25. #endregion
  26. #region *** Private Operations ***
  27. protected override async Task DoIteration(IWorkerContext context)
  28. {
  29. var ctx = (RepoWorkerContext)context;
  30. // Get worker name
  31. var workerName = GetName(Settings.ProcessingWorkerPwi);
  32. var repoProcessing = ctx.GetRepository<RepoProcessingQueue>();
  33. var repoData = ctx.GetRepository<RepoQueueData>();
  34. var repoDone = ctx.GetRepository<RepoDoneQueue>();
  35. // 1. Continue to work on already processing entries in ProcessQ (paused, tryout failed)
  36. // 2. If still available packet, lock pending entries in PendingQ
  37. // 3. Move locked entries to ProcessQ
  38. var processing = FetchFromQueue(ctx.GetRepository<RepoPendingQueue>(), ctx.GetRepository<RepoProcessingQueue>());
  39. foreach (var processItem in processing)
  40. {
  41. processItem.Started = DateTime.Now;
  42. processItem.AffinityWorker = workerName;
  43. processItem.AttemptLeft -= 1;
  44. processItem.Status = QueueStatusEnum.Working;
  45. repoProcessing.Set(processItem);
  46. var dataList = repoData.GetQueueData(processItem.Id).ToArray();
  47. var paramList = dataList.Select(x => (ParameterExecutorValue)x.ToParametrizedValue()).ToArray();
  48. var exe = new ExecutorInternal(processItem, paramList);
  49. var result = exe.Execute(Timeout, _logger);
  50. if (result.IsSuccess)
  51. {
  52. //success
  53. //update modified output values (from Execute)
  54. foreach (var parOutput in paramList.Where(x => x.IsOutput))
  55. {
  56. repoData.UpdateQueueData(processItem.Id, parOutput.Code, parOutput.Value);
  57. }
  58. var done = repoDone.NewFromProcessing(processItem);
  59. done.Status = QueueStatusEnum.Success;
  60. processItem.Status = QueueStatusEnum.Deleted;
  61. }
  62. else
  63. {
  64. //failed
  65. if (processItem.AttemptLeft == 0)
  66. {
  67. //move to failed
  68. }
  69. else
  70. {
  71. // next tryout
  72. processItem.Status = QueueStatusEnum.Assigned;
  73. }
  74. }
  75. }
  76. }
  77. private IEnumerable<ProcessingQueue> FetchFromQueue(RepoPendingQueue repoPending, RepoProcessingQueue repoProcessing)
  78. {
  79. if (repoPending == null) throw new ArgumentNullException(nameof(repoPending));
  80. if (repoProcessing == null) throw new ArgumentNullException(nameof(repoProcessing));
  81. // Get worker name
  82. var workerName = GetName(Settings.ProcessingWorkerPwi);
  83. // Get from pending queue
  84. var pendings = repoPending.GetPending(CN_ITEMS_PER_CYCLE).ToArray();
  85. // Assign pending
  86. foreach (var pending in pendings)
  87. {
  88. // Set Assigned
  89. pending.Status = QueueStatusEnum.Assigned;
  90. pending.AffinityWorker = workerName;
  91. // Create processing entry from pending entry
  92. var processing = repoProcessing.NewFromPending(pending);
  93. // Delete pending (mark it)
  94. pending.Status = QueueStatusEnum.Deleted;
  95. repoPending.Set(pending);
  96. }
  97. // Try to load forgot items from previous start
  98. var processings = repoProcessing.GetAssignedOrWorking(workerName, CN_ITEMS_PER_CYCLE).ToArray();
  99. return processings;
  100. }
  101. #endregion
  102. }
  103. }