public BatchEngine(IBatchStore store, IDependencyResolver resolver = null, ILogger logger = null, BatchSettings batchSettings = null) { _store = store; _jobExecutor = new DependencyInjectionJobExecutor(resolver); _logger = logger; _settings = batchSettings ?? new BatchSettings(); }
public BatchEngine(IBatchStore store, IDependencyResolver resolver, ILogger logger, BatchSettings batchSettings) { _store = store; _logger = logger; _settings = batchSettings ?? new BatchSettings(); _resolver = resolver; }
public BatchResult[] GenerateBatch(BatchSettings settings) { var results = new List <BatchResult>(); var logoSettings = settings.ItemSettings.Select( i => new LogoSettings( settings.SvgPath, i.Width, i.Height, i.Scale ?? settings.Scale, i.BackgroundColor ?? settings.BackgroundColor, i.OutputPath, settings.SaveOutputFiles)); foreach (var s in logoSettings) { try { var bitmap = Generate(s); results.Add(new BatchResult(bitmap)); } catch (Exception e) { results.Add(new BatchResult(e)); } } return(results.ToArray()); }
public async Task Heart_Neat_Failed_Should_Log_Error() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 500, HeartBeatFrequency = 50, }; _store.HeartBeatAsync(Environment.MachineName, 1, 500, 50) .Throws(x => new Exception("Some error")); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(150); } //Assert await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 500, 50); _logger.Received().Log( LogLevel.Error, Arg.Any <EventId>(), Arg.Is <object>(o => o.ToString().StartsWith("Error while sending heartbeat, System.Exception: Some error")), null, Arg.Any <Func <object, Exception, string> >()); }
public async Task WorkItem_Throws_Exception_When_Logger_Is_Null_Should_Swallow_Exception() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 50, HeartBeatFrequency = 5000, }; var job = CreateJobWithException(); _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null)); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, null, settings)) { engine.Start(); await Task.Delay(10); } //Assert AssertNoErrorsLogged(); }
/// <summary> /// Initializes a new instance of the <see cref="QueueMessageSerializer" /> class. /// </summary> /// <param name="batchSettings">The batch settings.</param> /// <param name="messageSerializer">The message serializer.</param> public QueueMessageSerializer( [NotNull] BatchSettings batchSettings, [NotNull] IMessageSerializer messageSerializer) { this.batchSettings = batchSettings; this.messageSerializer = messageSerializer; }
public BatchEngine() { if (MinionConfiguration.Configuration.HeartBeatFrequency <= 0) { throw new ArgumentOutOfRangeException( nameof(MinionConfiguration.Configuration.HeartBeatFrequency), "Heartbeat frequency must be more than 0"); } if (MinionConfiguration.Configuration.NumberOfParallelJobs <= 0) { throw new ArgumentOutOfRangeException( nameof(MinionConfiguration.Configuration.NumberOfParallelJobs), "Number of parallel jobs must be more than 0"); } if (MinionConfiguration.Configuration.PollingFrequency <= 0) { throw new ArgumentOutOfRangeException( nameof(MinionConfiguration.Configuration.PollingFrequency), "Polling frequency must be more than 0"); } _store = MinionConfiguration.Configuration.Store; _logger = MinionConfiguration.Configuration.Logger; _settings = new BatchSettings { HeartBeatFrequency = MinionConfiguration.Configuration.HeartBeatFrequency, NumberOfParallelJobs = MinionConfiguration.Configuration.NumberOfParallelJobs, PollingFrequency = MinionConfiguration.Configuration.PollingFrequency, }; _resolver = MinionConfiguration.Configuration.DependencyResolver; }
public async Task Heart_Beat_Failed_When_Logger_Is_Null_Should_Swallow_Error() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 500, HeartBeatFrequency = 50, }; _store.HeartBeatAsync(Environment.MachineName, 1, 500, 50) .Throws(x => new Exception("Some error")); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, null, settings)) { engine.Start(); await Task.Delay(150); } //Assert await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 500, 50); AssertNoErrorsLogged(); }
BatchSettings GetBatchSettings() { var mediaColor = DefaultBackgroundColor.SelectedColor ?? Colors.Transparent; var color = Color.FromArgb(mediaColor.A, mediaColor.R, mediaColor.G, mediaColor.B); var batchSettings = new BatchSettings(SvgPath.Text, DefaultScale.Value ?? 1.0f, color, true, _items.Select(i => i.Settings).ToArray()); return(batchSettings); }
void EnableBatch(bool enabled) { _batchSettings = new ConfigurationBatchSettings() { Enabled = enabled, MessageLimit = 100, SizeLimit = 200000, Timeout = TimeSpan.FromMilliseconds(3) }; }
public async Task ProcessBufferAsync_WhenMessagesOnBuffer_ExpectSentToQueue() { // Arrange const SerializerType SerializerType = SerializerType.Json; var queueWrapper = new MockQueueWrapper(); var batchSettings = new BatchSettings { MaxQueueMessagesPerSchedule = 10, MaxMessagesPerQueueMessage = 10 }; var serializerSettings = new SerializerSettings { SerializerType = SerializerType }; var messageSerializer = new MessageSerializer(serializerSettings); var queueMessageSerializer = new QueueMessageSerializer(batchSettings, messageSerializer); var buffer = new Buffer(this.LoggerFactory, queueWrapper, queueMessageSerializer); // Act var stopwatch = Stopwatch.StartNew(); buffer.AddMessage(new TestEntity { Data = "d1" }); buffer.AddMessage(new TestEntity { Data = "d2" }); buffer.AddMessage(new TestEntity { Data = "d3" }); await buffer.ProcessBufferAsync(CancellationToken.None).ConfigureAwait(false); stopwatch.Stop(); // Assert this.WriteTimeElapsed(stopwatch); var cloudQueueMessage = queueWrapper.Get(); Assert.That(cloudQueueMessage, Is.Not.Null); var asString = cloudQueueMessage.AsString; var batchedVersionedMessage = asString.Deserialize <BatchedVersionedMessage>(SerializerType); Assert.That(batchedVersionedMessage, Is.Not.Null); var messages = batchedVersionedMessage.Messages.ToList(); Assert.That(messages.Count, Is.EqualTo(3)); Assert.That(messages.All(r => r.Version == new DtoVersion(typeof(TestEntity), 1, 0, 0)), Is.True); }
public void Validate() { if (Batch == null) { Batch = new BatchSettings(); } Batch.Validate(); if (Consumers < 1) { throw new EndpointConfigurationException("Consumers must be greater or equal to 1."); } }
protected override void OnLoad(object sender, EventArgs eventArgs) { new LayoutManager(this) .Bind(groupboxScanConfig, groupboxOutput, panelSaveSeparator, panelSaveTo, panelSaveType, panelScanDetails, panelScanType, comboProfile, txtFilePath, lblStatus) .WidthToForm() .Bind(btnEditProfile, btnAddProfile, btnStart, btnCancel, btnChooseFolder) .RightToForm() .Activate(); ConditionalControls.LockHeight(this); BatchSettings = userConfigManager.Config.LastBatchSettings ?? new BatchSettings(); UpdateUIFromSettings(); }
protected Batcher() { _settings = ClientContextBatchSettings.GetBatchSettings(); var channelOptions = new BoundedChannelOptions(_settings.MessageLimit) { AllowSynchronousContinuations = false, FullMode = BoundedChannelFullMode.Wait, SingleReader = true, SingleWriter = false }; _channel = Channel.CreateBounded <BatchEntry <TEntry> >(channelOptions); _executor = new ChannelExecutor(2, _settings.BatchLimit); _batchTask = Task.Run(WaitForBatch); }
/// <summary> /// Creates this instance. /// </summary> /// <param name="queueConfiguration">The queue configuration.</param> /// <param name="loggerFactory">The logger factory.</param> /// <returns> /// The <see cref="IQueue" /> /// </returns> public static IQueue Create( QueueConfiguration queueConfiguration, ILoggerFactory loggerFactory = null) { var logger = loggerFactory ?? new LoggerFactory(); var queueEndpoint = new QueueEndpoint { ConnectionString = queueConfiguration.QueueConnectionString, QueueName = queueConfiguration.QueueName }; var serializerSettings = new SerializerSettings { SerializerType = queueConfiguration.SerializerType }; var batchSettings = new BatchSettings { MaxQueueMessagesPerSchedule = queueConfiguration.MaxQueueMessagesPerSchedule, MaxMessagesPerQueueMessage = queueConfiguration.MaxMessagesPerQueueMessage }; var scheduleSettings = new ScheduleSettings { ThrottleTime = queueConfiguration.ThrottleTime }; var queueWrapper = new QueueWrapper(queueEndpoint); var messageSerializer = new MessageSerializer(serializerSettings); var queueMessageSerializer = new QueueMessageSerializer(batchSettings, messageSerializer); var buffer = new Buffer(logger, queueWrapper, queueMessageSerializer); var stopwatchFactory = new StopwatchFactory(); var delayCalculator = new DelayCalculator(); var pumpProcessor = new PumpProcessor( logger, buffer, stopwatchFactory, delayCalculator, scheduleSettings); var queuePump = new QueuePump(buffer, pumpProcessor); return(new Queue(queuePump)); }
public async Task Semaphore_Released_After_Done_Executing() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 50, HeartBeatFrequency = 5000, }; var job1 = Task.FromResult(CreateJob(1)); var job2 = Task.FromResult(CreateJob(2)); _store.AcquireJobAsync().Returns(job1, job2, Task.FromResult((JobDescription)null)); var service = Substitute.For <ITestService>(); _dependencyResolver.Resolve(typeof(ITestService), out _).Returns(x => { x[1] = service; return(true); }); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(150); } //Assert Received.InOrder(() => { service.DoSomethingAsync(1); service.DoSomethingAsync(2); }); await _store.Received().AcquireJobAsync(); await service.Received(2).DoSomethingAsync(Arg.Any <int>()); AssertNoErrorsLogged(); }
public async Task Successful_Job_Should_Release_With_Given_Result() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 50, HeartBeatFrequency = 5000, }; var data = new TestJobWithReturnData.TestData { State = ExecutionState.Halted, StatusInfo = "info", DueTime = new DateTime(2018, 1, 2, 3, 4, 5) }; var job = CreateJobWithReturnData(data); job.Id = Guid.NewGuid(); _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null)); JobResult result = null; await _store.ReleaseJobAsync(job.Id, Arg.Do <JobResult>(x => result = x)); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(10); } //Assert Assert.Equal(data.State, result.State); Assert.Equal(data.StatusInfo, result.StatusInfo); Assert.Equal(data.DueTime, result.DueTime); await _store.Received(1).ReleaseJobAsync(job.Id, result); AssertNoErrorsLogged(); }
public static void Main(string[] args) { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddUserSecrets <Program>(); if (args != null) { builder.AddCommandLine(args); } _configuration = builder.Build(); _dbSettings = LoadDbSettings(); _twilioSecrets = LoadTwilioSecrets(); _batchSettings = LoadBatchSettings(); ReadBatchoFMesssages(); }
public BatchPublisher(ChannelExecutor executor, IModel model, BatchSettings settings, PendingConfirmationCollection confirmations) { _executor = executor; _model = model; _settings = settings; _confirmations = confirmations; _immediatePublisher = new ImmediatePublisher(executor, model, confirmations); var channelOptions = new BoundedChannelOptions(settings.MessageLimit) { AllowSynchronousContinuations = false, FullMode = BoundedChannelFullMode.Wait, SingleReader = true, SingleWriter = false }; _publishChannel = Channel.CreateBounded <BatchPublish>(channelOptions); _publishTask = Task.Run(WaitForBatch); }
static void Main(string[] args) { //Setup var dateService = new UtcDateService(); var store = new InMemoryStorage(dateService); var resolver = new SimpleResolver(dateService); ILogger logger = null; var settings = new BatchSettings { HeartBeatFrequency = 2000, NumberOfParallelJobs = 2, PollingFrequency = 500 }; var scheduler = new JobScheduler(store, dateService); //Add a sequence of jobs var sequence = new Sequence(); sequence.Add <SimpleJob>(); sequence.Add <JobWithInput, JobWithInput.Input>(new JobWithInput.Input { Text = "this is awesome!" }); //Queue the sequence scheduler.QueueAsync(sequence).Wait(); //Add a single job scheduler.QueueAsync <RecurringJob>(); //Start the engine using (var engine = new BatchEngine(store, resolver, logger, settings)) { Console.WriteLine("Starting ..."); engine.Start(); Console.ReadKey(); } }
public void Start_Without_Store() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 1000, HeartBeatFrequency = 50, }; InvalidOperationException ex; //Act using (var engine = new BatchEngine(null, null, null, settings)) { ex = Assert.Throws <InvalidOperationException>(() => engine.Start()); } //Assert Assert.Equal("Cannot start without storage.", ex.Message); }
public async Task Job_Throws_Exception_Should_Release_With_Error_State() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 50, HeartBeatFrequency = 5000, }; var job = CreateJobWithException(); _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null)); JobResult result = null; await _store.ReleaseJobAsync(job.Id, Arg.Do <JobResult>(x => result = x)); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(10); } //Assert Assert.Equal(ExecutionState.Error, result.State); Assert.StartsWith("System.NotImplementedException: Method not implemented.", result.StatusInfo); Assert.Equal(job.DueTime, result.DueTime); await _store.Received(1).ReleaseJobAsync(job.Id, result); _logger.Received(1).Log( LogLevel.Error, Arg.Any <EventId>(), Arg.Is <object>(x => x.ToString().StartsWith("Error while processing work item, ")), null, Arg.Any <Func <object, Exception, string> >()); }
public async Task Batch_Engine_Should_Send_Heart_Beat() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 1000, HeartBeatFrequency = 50, }; //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(150); } //Assert await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 1000, 50); AssertNoErrorsLogged(); }
public async Task Should_Wait_For_Executing_Job_To_Finish_Before_Shut_Down() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 50, HeartBeatFrequency = 5000, }; var job = Task.FromResult(CreateDelayedJob(300)); _store.AcquireJobAsync().Returns(job, Task.FromResult((JobDescription)null)); var service = Substitute.For <ITestService>(); _dependencyResolver.Resolve(typeof(ITestService), out _).Returns(x => { x[1] = service; return(true); }); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(10); } //Assert await service.Received(1).DoSomethingAsync(300); AssertNoErrorsLogged(); }
public async Task Polling_Frequency_Zero_Should_Release_Semaphore() { //Arrange var settings = new BatchSettings { NumberOfParallelJobs = 1, PollingFrequency = 0, HeartBeatFrequency = 5000, }; var data = new TestJobWithReturnData.TestData { State = ExecutionState.Waiting, StatusInfo = "info", DueTime = new DateTime(2018, 1, 2, 3, 4, 5) }; var job = CreateJobWithReturnData(data); job.Id = Guid.NewGuid(); _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null), Task.FromResult(job), Task.FromResult((JobDescription)null)); //Act using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings)) { engine.Start(); await Task.Delay(200); } //Assert await _store.Received(2).ReleaseJobAsync(job.Id, Arg.Any <JobResult>()); AssertNoErrorsLogged(); }
protected async Task <AllGenerationsResult> Generate( GeneratorConfig config, BatchSettings batchSettings, CancellationToken ct = default) { if (config == null) { throw new ArgumentNullException(nameof(config)); } if (batchSettings == null) { throw new ArgumentNullException(nameof(batchSettings)); } try { config.Validate(); batchSettings.Validate(); } catch (ValidationException ve) { _logger.Fatal(ve, "Cannot start generation, configuration is invalid"); throw; } if (batchSettings.RestartIisBeforeBatch) { try { using (StopwatchLoggerFactory.ForceLogDispose(_logger, LogLevel.Debug, "iisreset completed")) { IisManager.Instance.RestartIis(); } } catch (Exception e) { _logger.Error(e, "Cannot restart IIS. Perhaps application was batched without administrator rights"); } } if (batchSettings.CollectGarbageBeforeBatch) { if (_logger.IsDebugEnabled) { _logger.Debug("Memory before GC.Collect: {byte:N0}", GC.GetTotalMemory(false)); GC.Collect(); _logger.Debug("Memory after GC.Collect: {byte:N0}", GC.GetTotalMemory(true)); } else { GC.Collect(); } } var generatationResults = new List <GenerationResult>(); var batch = batchSettings.CompileBatch(); bool stopProcessing = false; using (StopwatchLoggerFactory.ForceLogStartDispose( _logger, "Start generation all settings for batch, Settings count = {count}, Id = {id}", "Generation all settings for batch completed, Settings count = {count}, Id = {id}", Params.ToArray <object>(batch.AvailableCount, batchSettings.Id, batchSettings), callback: time => LogHelper.ResultsLogger.Info("Batch, Time: {time} ({time-sec} sec)", time, time.TotalSeconds))) { foreach (var settings in batch) { GenerationResult result; try { ct.ThrowIfCancellationRequested(); if (settings is IBatchDependent bd) { bd.Inject(batch); } var runner = settings.GetGenerationRunner(config.ApiConnectionConfig); config.SubscriptionManager?.SubscribeGenerationRunner(runner); await runner.RunGeneration(ct).ConfigureAwait(false); result = new GenerationResult(settings); } catch (OperationCanceledException oce) { _logger.Fatal(oce, "Operation was canceled"); throw; } catch (GenerationException ge) { _logger.Error(ge, "Generation failed"); result = new GenerationResult(settings, ge); if (batchSettings.StopProcessingAtException) { stopProcessing = true; } } catch (ValidationException ve) { _logger.Error(ve, "Generation not started because of invalid configuration"); result = new GenerationResult(settings, ve); } // this should not happen catch (Exception e) { _logger.Fatal(e, "Generation failed with unexpected error"); result = new GenerationResult(settings, e); if (batchSettings.StopProcessingAtException) { stopProcessing = true; } } generatationResults.Add(result); if (stopProcessing) { break; } } } return(new AllGenerationsResult(generatationResults, stopProcessing)); }
public virtual void StartBtnCommandBatchAction(Object param) { Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); IVsThreadedWaitDialog2 aDialog = null; bool aDialogStarted = false; if (this.DialogFactory != null) { this.DialogFactory.CreateInstance(out aDialog); if (aDialog != null) { aDialogStarted = aDialog.StartWaitDialog("Generation started", "VS is Busy", "Please wait", null, "Generation started", 0, false, true) == VSConstants.S_OK; } } StringBuilder sb = new StringBuilder(); try { sb.AppendLine("Json parsing started"); BatchSettings batchSettings = BatchSettingsHelper.ReadBatchSettingsFromString(CurrentBatchSetting); if (batchSettings == null) { throw new Exception("Could not Deserialize Object"); } sb.AppendLine("Json parsing finished"); if (batchSettings.BatchItems == null) { throw new Exception("Batch Items is empty"); } sb.AppendLine("Batch Items processing started"); foreach (BatchItem batchItem in batchSettings.BatchItems) { ModelViewSerializable currentSerializableModel = SerializableModel; if (!string.IsNullOrEmpty(batchItem.ViewModel)) { currentSerializableModel = SerializableDbContext.ModelViews.Where(m => m.ViewName == batchItem.ViewModel).FirstOrDefault(); if (currentSerializableModel == null) { throw new Exception("Could not find [" + batchItem.ViewModel + "] of the Batch Item = " + batchItem.GeneratorType); } } sb.AppendLine("Processing Batch Item: [DestinationFolder]=[" + batchItem.DestinationFolder + "]"); sb.AppendLine(" [GeneratorType]=[" + batchItem.GeneratorType + "]"); sb.AppendLine(" [GeneratorSript]=[" + batchItem.GeneratorSript + "]"); string tmpltPath = Path.Combine(T4RootFolder, batchItem.GeneratorType, batchItem.GeneratorSript); string FileName = ""; if (currentSerializableModel.ViewName == ContextItemViewName) { FileName = BatchSettingsHelper.TrimPrefix(Path.GetFileNameWithoutExtension(batchItem.GeneratorType)); } else { FileName = currentSerializableModel.ViewName + BatchSettingsHelper.TrimPrefix(Path.GetFileNameWithoutExtension(batchItem.GeneratorType)); } FileName = BatchSettingsHelper.GetHyphenedName(FileName); sb.AppendLine(" Batch Item: Creating Shallow Copy"); ModelViewSerializable ShallowCopy = null; if (currentSerializableModel.ViewName == SerializableModel.ViewName) { ShallowCopy = BatchSettingsHelper.GetSelectedModelCommonShallowCopy(currentSerializableModel, UIFormProperties, UIListProperties, DestinationProjectName, DefaultProjectNameSpace, DestinationFolder, batchItem.DestinationFolder, batchItem.GeneratorType, FileName); } else { ShallowCopy = BatchSettingsHelper.GetSelectedModelCommonShallowCopy(currentSerializableModel, null, null, DestinationProjectName, DefaultProjectNameSpace, DestinationFolder, batchItem.DestinationFolder, batchItem.GeneratorType, FileName); } sb.AppendLine(" Batch Item: Generating Code"); GeneratorBatchStep generatorBatchStep = BatchSettingsHelper.DoGenerateViewModel(Dte, TextTemplating, tmpltPath, SerializableDbContext, ShallowCopy, DefaultProjectNameSpace); if (!string.IsNullOrEmpty(generatorBatchStep.GenerateError)) { throw new Exception(generatorBatchStep.GenerateError); } sb.AppendLine(" Batch Item: Adding Generated file to project and Updating Wizard's Context Repository"); BatchSettingsHelper.UpdateDbContext(Dte, DestinationProject, SelectedDbContext, SerializableDbContext, ShallowCopy, ContextItemViewName, batchItem.GeneratorType, DestinationProjectRootFolder, DestinationFolder, batchItem.DestinationFolder, FileName, generatorBatchStep.FileExtension, generatorBatchStep.GenerateText); currentSerializableModel.CommonStaffs = ShallowCopy.CommonStaffs; sb.AppendLine("Batch Item Processing finished"); } sb.AppendLine("Batch Items processing finished"); } catch (Exception e) { LastError = "Exception thrown: " + e.Message; return; } finally { if (aDialogStarted) { int iOut; aDialog.EndWaitDialog(out iOut); } ReportText = sb.ToString(); } }
/// <summary> /// Constructor to initialize properties /// </summary> /// <param name="configuration"></param> public BatchService(IConfigurationService configuration) { _settings = configuration.Settings.Batch; }