AbstractWorkerService.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Extensions.Logging;
  5. using Quadarax.Foundation.Core.Business.Enums;
  6. using Quadarax.Foundation.Core.Business.Interface;
  7. using Quadarax.Foundation.Core.Data.Interface.Domain;
  8. using Quadarax.Foundation.Core.Data.Interface.Repository;
  9. using Quadarax.Foundation.Core.Logging;
  10. using Quadarax.Foundation.Core.Thread;
  11. namespace Quadarax.Foundation.Core.Business
  12. {
  13. public abstract class AbstractWorkerService<TRepository> : AbstractRepositoryService<TRepository>
  14. where TRepository: IRepository
  15. {
  16. #region *** Private fields ***
  17. private IList<Tuple<WorkerStatusInfo, AbstractWorker>> _workers = new List<Tuple<WorkerStatusInfo,AbstractWorker>>();
  18. private IList<WorkerDescriptor> _descriptors = new List<WorkerDescriptor>();
  19. private object _lockTransient = null;
  20. #endregion
  21. #region *** Properties ***
  22. #endregion
  23. #region *** Constructors ***
  24. protected AbstractWorkerService(TRepository repository, IContext currentContext, IQLogger logger) : base(repository, currentContext, logger)
  25. {
  26. State = ServiceStateEnum.Initializing;
  27. InitInternal();
  28. }
  29. #endregion
  30. #region *** Public Operations ***
  31. public void Start()
  32. {
  33. lock (_lockTransient)
  34. {
  35. _lockTransient = new object();
  36. ResetDescriptorsOrdinal();
  37. foreach (var desc in _descriptors)
  38. {
  39. for(var a=0;a<desc.WorkerSettings.WorkerCount;a++)
  40. {
  41. var wrk = BuildWorker(desc);
  42. var info = new WorkerStatusInfo(wrk?.Name);
  43. _workers.Add(new Tuple<WorkerStatusInfo, AbstractWorker>(info, wrk));
  44. wrk?.Start();
  45. info.SetStart();
  46. info.SetIterations(wrk.CurrentThreadId, wrk.IterationCount);
  47. }
  48. }
  49. _lockTransient = null;
  50. State = ServiceStateEnum.Online;
  51. }
  52. }
  53. public void Stop()
  54. {
  55. lock (_lockTransient)
  56. {
  57. _lockTransient = new object();
  58. foreach (var wrk in _workers)
  59. {
  60. wrk.Item2.Stop();
  61. wrk.Item1.SetStop();
  62. wrk.Item1.SetIterations(wrk.Item2.CurrentThreadId, wrk.Item2.IterationCount);
  63. }
  64. _lockTransient = null;
  65. State = ServiceStateEnum.Offline;
  66. }
  67. }
  68. #endregion
  69. #region *** Private Operations ***
  70. protected void RegisterWorker<TWorker>(IWorkerSettings settings) where TWorker : AbstractWorker
  71. {
  72. if (settings == null) throw new ArgumentNullException(nameof(settings));
  73. State = ServiceStateEnum.Initializing;
  74. lock (_lockTransient)
  75. {
  76. _lockTransient = new object();
  77. _descriptors.Add(new WorkerDescriptor(typeof(TWorker),settings));
  78. Log.Log(LogSeverityEnum.Debug, $"Worker type '{typeof(TWorker).Name}' was registered.");
  79. _lockTransient = null;
  80. }
  81. }
  82. private void InitInternal()
  83. {
  84. _workers.Clear();
  85. OnBuildWorkers();
  86. }
  87. private void ResetDescriptorsOrdinal()
  88. {
  89. foreach (var desc in _descriptors)
  90. desc.ResetOrdinal();
  91. }
  92. protected AbstractWorker BuildWorker(WorkerDescriptor descriptor)
  93. {
  94. var worker = (AbstractWorker)Activator.CreateInstance(descriptor.WorkerType,descriptor.CurrentWorkerName,
  95. descriptor.WorkerSettings, Logger);
  96. descriptor.IncrementOrdinal();
  97. return worker;
  98. }
  99. protected abstract void OnBuildWorkers();
  100. #endregion
  101. #region *** Nested Classes ***
  102. protected class WorkerDescriptor
  103. {
  104. public Type WorkerType { get; }
  105. public IWorkerSettings WorkerSettings { get; }
  106. public int CurrentOrdinalNumber { get; set; }
  107. public string CurrentWorkerName
  108. {
  109. get
  110. {
  111. var prefix = string.IsNullOrEmpty(WorkerSettings.WorkerNamePrefix)
  112. ? "Worker"
  113. : WorkerSettings.WorkerNamePrefix;
  114. return prefix + "#" + CurrentOrdinalNumber;
  115. }
  116. }
  117. public WorkerDescriptor(Type workerType, IWorkerSettings settings)
  118. {
  119. WorkerType = workerType ?? throw new ArgumentNullException(nameof(workerType));
  120. WorkerSettings = settings ?? throw new ArgumentNullException(nameof(settings));
  121. ResetOrdinal();
  122. }
  123. public void IncrementOrdinal()
  124. {
  125. CurrentOrdinalNumber++;
  126. }
  127. public void ResetOrdinal()
  128. {
  129. CurrentOrdinalNumber = 0;
  130. }
  131. }
  132. #endregion
  133. }
  134. public abstract class AbstractWorkerService<TRepository, TRepository1> : AbstractWorkerService<TRepository>
  135. where TRepository : IRepository
  136. where TRepository1 : IRepository
  137. {
  138. protected TRepository1 Repository1 { get; }
  139. protected AbstractWorkerService(TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository, currentContext, logger)
  140. {
  141. Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
  142. }
  143. }
  144. public abstract class AbstractWorkerService<TRepository, TRepository1, TRepository2> : AbstractWorkerService<TRepository, TRepository1>
  145. where TRepository : IRepository
  146. where TRepository1 : IRepository
  147. where TRepository2 : IRepository
  148. {
  149. protected TRepository2 Repository2 { get; }
  150. protected AbstractWorkerService(TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository1, repository, currentContext, logger)
  151. {
  152. Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
  153. }
  154. }
  155. public abstract class AbstractWorkerService<TRepository, TRepository1, TRepository2, TRepository3> : AbstractWorkerService<TRepository, TRepository1, TRepository2>
  156. where TRepository : IRepository
  157. where TRepository1 : IRepository
  158. where TRepository2 : IRepository
  159. where TRepository3 : IRepository
  160. {
  161. protected TRepository3 Repository3 { get; }
  162. protected AbstractWorkerService(TRepository3 repository3, TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository2, repository1, repository, currentContext, logger)
  163. {
  164. Repository3 = repository3 ?? throw new ArgumentNullException(nameof(repository3));
  165. }
  166. }
  167. public abstract class AbstractWorkerService<TRepository, TRepository1, TRepository2, TRepository3, TRepository4> : AbstractWorkerService<TRepository, TRepository1, TRepository2, TRepository3>
  168. where TRepository : IRepository
  169. where TRepository1 : IRepository
  170. where TRepository2 : IRepository
  171. where TRepository3 : IRepository
  172. where TRepository4 : IRepository
  173. {
  174. protected TRepository4 Repository4 { get; }
  175. protected AbstractWorkerService(TRepository4 repository4, TRepository3 repository3, TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository3,repository2,repository1, repository, currentContext, logger)
  176. {
  177. Repository4 = repository4 ?? throw new ArgumentNullException(nameof(repository4));
  178. }
  179. }
  180. }