/// <summary> /// Actual taskletstep execution. /// </summary> /// <param name="stepExecution"></param> /// <exception cref="Exception"> </exception> protected override void DoExecute(StepExecution stepExecution) { stepExecution.ExecutionContext.Put(TaskletTypeKey, _tasklet.GetType().Name); stepExecution.ExecutionContext.Put(StepConstants.StepTypeKey, GetType().Name); _stream.Update(stepExecution.ExecutionContext); JobRepository.UpdateExecutionContext(stepExecution); JobRepository.UpdateExecutionContext(stepExecution.JobExecution); // Shared semaphore per step execution, so other step executions can run // in parallel without needing the lock Semaphore semaphore = CreateSemaphore(); _stepOperations.Iterate(StepContextRepeatCallback.GetRepeatCallback(stepExecution, (context, chunkContext) => { StepExecution lStepExecution = chunkContext.StepContext.StepExecution; _interruptionPolicy.CheckInterrupted(lStepExecution); ChunkTransactionCallback callback = new ChunkTransactionCallback(chunkContext, semaphore, this); RepeatStatus result; using (var scope = TransactionScopeManager.CreateScope()) { TransactionScopeManager.RegisterTransactionSynchronization(scope, callback); try { result = callback.DoInTransaction(); } catch (Exception e) { //Log and rethrow Logger.Error(e, "Transaction will be rollbacked because of an unexpected exception."); throw; // throw to ensure rollback will occur (no complete) } scope.Complete(); } // Release connections since the transaction has ended ConnectionUtil.ReleaseConnections(); Thread.Sleep(stepExecution.DelayConfig); _interruptionPolicy.CheckInterrupted(stepExecution); return(result); } )); }