using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Logging; using Quadarax.Foundation.Core.Business.Enums; using Quadarax.Foundation.Core.Business.Interface; using Quadarax.Foundation.Core.Data.Interface.Domain; using Quadarax.Foundation.Core.Data.Interface.Repository; using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Thread; namespace Quadarax.Foundation.Core.Business { public abstract class AbstractWorkerService : AbstractRepositoryService where TRepository: IRepository { #region *** Private fields *** private IList> _workers = new List>(); private IList _descriptors = new List(); private object _lockTransient = null; #endregion #region *** Properties *** #endregion #region *** Constructors *** protected AbstractWorkerService(TRepository repository, IContext currentContext, IQLogger logger) : base(repository, currentContext, logger) { State = ServiceStateEnum.Initializing; InitInternal(); } #endregion #region *** Public Operations *** public void Start() { lock (_lockTransient) { _lockTransient = new object(); ResetDescriptorsOrdinal(); foreach (var desc in _descriptors) { for(var a=0;a(info, wrk)); wrk?.Start(); info.SetStart(); info.SetIterations(wrk.CurrentThreadId, wrk.IterationCount); } } _lockTransient = null; State = ServiceStateEnum.Online; } } public void Stop() { lock (_lockTransient) { _lockTransient = new object(); foreach (var wrk in _workers) { wrk.Item2.Stop(); wrk.Item1.SetStop(); wrk.Item1.SetIterations(wrk.Item2.CurrentThreadId, wrk.Item2.IterationCount); } _lockTransient = null; State = ServiceStateEnum.Offline; } } #endregion #region *** Private Operations *** protected void RegisterWorker(IWorkerSettings settings) where TWorker : AbstractWorker { if (settings == null) throw new ArgumentNullException(nameof(settings)); State = ServiceStateEnum.Initializing; lock (_lockTransient) { _lockTransient = new object(); _descriptors.Add(new WorkerDescriptor(typeof(TWorker),settings)); Log.Log(LogSeverityEnum.Debug, $"Worker type '{typeof(TWorker).Name}' was registered."); _lockTransient = null; } } private void InitInternal() { _workers.Clear(); OnBuildWorkers(); } private void ResetDescriptorsOrdinal() { foreach (var desc in _descriptors) desc.ResetOrdinal(); } protected AbstractWorker BuildWorker(WorkerDescriptor descriptor) { var worker = (AbstractWorker)Activator.CreateInstance(descriptor.WorkerType,descriptor.CurrentWorkerName, descriptor.WorkerSettings, Logger); descriptor.IncrementOrdinal(); return worker; } protected abstract void OnBuildWorkers(); #endregion #region *** Nested Classes *** protected class WorkerDescriptor { public Type WorkerType { get; } public IWorkerSettings WorkerSettings { get; } public int CurrentOrdinalNumber { get; set; } public string CurrentWorkerName { get { var prefix = string.IsNullOrEmpty(WorkerSettings.WorkerNamePrefix) ? "Worker" : WorkerSettings.WorkerNamePrefix; return prefix + "#" + CurrentOrdinalNumber; } } public WorkerDescriptor(Type workerType, IWorkerSettings settings) { WorkerType = workerType ?? throw new ArgumentNullException(nameof(workerType)); WorkerSettings = settings ?? throw new ArgumentNullException(nameof(settings)); ResetOrdinal(); } public void IncrementOrdinal() { CurrentOrdinalNumber++; } public void ResetOrdinal() { CurrentOrdinalNumber = 0; } } #endregion } public abstract class AbstractWorkerService : AbstractWorkerService where TRepository : IRepository where TRepository1 : IRepository { protected TRepository1 Repository1 { get; } protected AbstractWorkerService(TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository, currentContext, logger) { Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1)); } } public abstract class AbstractWorkerService : AbstractWorkerService where TRepository : IRepository where TRepository1 : IRepository where TRepository2 : IRepository { protected TRepository2 Repository2 { get; } protected AbstractWorkerService(TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository1, repository, currentContext, logger) { Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2)); } } public abstract class AbstractWorkerService : AbstractWorkerService where TRepository : IRepository where TRepository1 : IRepository where TRepository2 : IRepository where TRepository3 : IRepository { protected TRepository3 Repository3 { get; } protected AbstractWorkerService(TRepository3 repository3, TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository2, repository1, repository, currentContext, logger) { Repository3 = repository3 ?? throw new ArgumentNullException(nameof(repository3)); } } public abstract class AbstractWorkerService : AbstractWorkerService where TRepository : IRepository where TRepository1 : IRepository where TRepository2 : IRepository where TRepository3 : IRepository where TRepository4 : IRepository { protected TRepository4 Repository4 { get; } protected AbstractWorkerService(TRepository4 repository4, TRepository3 repository3, TRepository2 repository2, TRepository1 repository1, TRepository repository, IContext currentContext, IQLogger logger) : base(repository3,repository2,repository1, repository, currentContext, logger) { Repository4 = repository4 ?? throw new ArgumentNullException(nameof(repository4)); } } }