예제 #1
0
        /// <summary>
        /// Registers a context with the current thread - always put a matching
        /// <see cref="Close"/> call in a finally block to ensure that the correct
        /// context is available in the enclosing block.
        /// </summary>
        /// <param name="stepExecution">the step context to register</param>
        /// <returns>a new StepContext or the current one if it has the same StepExecution</returns>
        public static StepContext Register(StepExecution stepExecution)
        {
            var context = Manager.Register(stepExecution);

            StepScopeSynchronization.ResetInstances();
            return(context);
        }
        /// <summary>
        /// Calls the registered listeners in reverse order, respecting and
        /// prioritizing those that hold an order metadata information.
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <returns></returns>
        public ExitStatus AfterStep(StepExecution stepExecution)
        {
            if (Logger.IsTraceEnabled)
            {
                Logger.Trace("CompositeStepExecutionListener :: Entering AfterStep");
            }
            IEnumerator <IStepExecutionListener> enumerator = _list.Reverse();

            while (enumerator.MoveNext())
            {
                if (Logger.IsTraceEnabled)
                {
                    Logger.Trace("CompositeStepExecutionListener :: Before Executing AfterStep - stepExecution.ExitStatus ={0}", stepExecution.ExitStatus);
                }
                IStepExecutionListener listener = enumerator.Current;
                ExitStatus             close    = listener.AfterStep(stepExecution);
                stepExecution.ExitStatus = stepExecution.ExitStatus.And(close);
                if (Logger.IsTraceEnabled)
                {
                    Logger.Trace("CompositeStepExecutionListener :: After Executing AfterStep - stepExecution.ExitStatus ={0}", stepExecution.ExitStatus);
                }
            }

            if (Logger.IsTraceEnabled)
            {
                Logger.Trace("CompositeStepExecutionListener :: Exiting AfterStep");
            }

            return(stepExecution.ExitStatus);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <returns></returns>
        private ExitStatus HandleExecution(StepExecution stepExecution)
        {
            _stepExecutionListener.BeforeStep(stepExecution);
            Open(stepExecution.ExecutionContext);
            try
            {
                DoExecute(stepExecution);
            }
            catch (RepeatException e)
            {
                throw e.InnerException;
            }
            var exitStatus = ExitStatus.Completed.And(stepExecution.ExitStatus);

            // Check if someone is trying to stop us
            if (stepExecution.TerminateOnly)
            {
                throw new JobInterruptedException("JobExecution interrupted.");
            }

            // Need to upgrade here not set, in case the execution was stopped
            stepExecution.UpgradeStatus(BatchStatus.Completed);
            Logger.Debug("Step execution success: id= {0}", stepExecution.Id);
            return(exitStatus);
        }
        /// <summary>
        /// @see AbstractPartitionHandler#DoHandle .
        /// </summary>
        /// <param name="masterStepExecution"></param>
        /// <param name="partitionStepExecutions"></param>
        /// <returns></returns>
        protected override ICollection<StepExecution> DoHandle(StepExecution masterStepExecution, ICollection<StepExecution> partitionStepExecutions)
        {
            Assert.NotNull(Step, "A Step must be provided.");
            HashSet<Task<StepExecution>> tasks = new HashSet<Task<StepExecution>>();
            HashSet<StepExecution> result = new HashSet<StepExecution>();

            foreach (StepExecution stepExecution in partitionStepExecutions)
            {
                Task<StepExecution> task = CreateTask(Step, stepExecution);
                try
                {
                    _taskExecutor.Execute(task);
                    tasks.Add(task);
                }
                catch (TaskRejectedException)
                {
                    // couldn't execute one of the tasks
                    ExitStatus exitStatus = ExitStatus.Failed.AddExitDescription("TaskExecutor rejected the task for this step.");
                    
                    // Set the status in case the caller is tracking it through the
                    // JobExecution.                    
                    stepExecution.BatchStatus = BatchStatus.Failed;
                    stepExecution.ExitStatus = exitStatus;
                    result.Add(stepExecution);
                }
            }

            foreach (Task<StepExecution> task in tasks)
            {
                // Accessing Result is blocking (waits for asynchronous execution to complete)
                result.Add(task.Result);
            }

            return result;
        }
        /// <summary>
        /// Launch Worker method in the controlThread.
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <param name="threadWait"></param>
        public void Worker(StepExecution stepExecution, AutoResetEvent threadWait)
        {
            // workerStartedMessage includes stepname and worker id
            string workerStartedMessage = stepExecution.StepName + dot + stepExecution.remoteChunking.WorkerID.ToString();

            // worker send workerStartedMessage in the workerStarted queue for master job to check
            stepExecution.remoteChunking._workerStartedQueue.Send(workerStartedMessage);
            int maxMasterWaitWorkerSecond = stepExecution.remoteChunking.MaxMasterWaitWorkerSecond;
            int _workerTimerseconds       = maxMasterWaitWorkerSecond * 1000;
            // start a timer to let master check worker is still alive or not in every defualt seconds
            Timer timer       = new Timer(WorkerTimerMethod, stepExecution, 0, _workerTimerseconds);
            bool  Isterminate = false;

            while (!Isterminate)
            {
                // send back signal to the afterStep and stop timer when batch failed
                ControlQueue workerCompletedQueue = stepExecution.remoteChunking._workerCompletedQueue;
                if ("FAILED".Equals(stepExecution.ExitStatus.ExitCode))
                {
                    timer.Dispose();
                    Isterminate = true;
                }
                // when batch completed send back signal to the afterStep and stop timer after send completedmessage to message queue
                else if ("COMPLETED".Equals(stepExecution.ExitStatus.ExitCode))
                {
                    string workerCompletedMessage = stepExecution.JobExecution.JobInstance.JobName + dot + stepExecution.remoteChunking.WorkerID + dot + "COMPLETED";
                    workerCompletedQueue.Send(workerCompletedMessage);
                    timer.Dispose();
                    threadWait.Set();
                    Isterminate = true;
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Execute the job provided by delegating to the <see cref="IJobLauncher"/>to
        /// prevent duplicate executions. The job parameters will be generated by the
        /// <see cref="IJobParametersExtractor"/>provided (if any), otherwise empty. On a
        /// restart, the job parameters will be the same as the last (failed) execution.
        /// </summary>
        /// <param name="stepExecution"></param>
        protected override void DoExecute(StepExecution stepExecution)
        {
            ExecutionContext executionContext = stepExecution.ExecutionContext;

            executionContext.Put(StepConstants.StepTypeKey, GetType().Name);
            JobParameters jobParameters;

            if (executionContext.ContainsKey(JobParametersKey))
            {
                jobParameters = (JobParameters)executionContext.Get(JobParametersKey);
            }
            else
            {
                jobParameters = _jobParametersExtractor.GetJobParameters(Job, stepExecution);
                executionContext.Put(JobParametersKey, jobParameters);
            }

            JobExecution jobExecution = JobLauncher.Run(Job, jobParameters);

            if (jobExecution.Status.IsUnsuccessful())
            {
                // AbstractStep will take care of the step execution status
                throw new UnexpectedJobExecutionException("Step failure: the delegate Job failed in JobStep.");
            }
        }
 public void Initialize()
 {
     _jobInstance    = new JobInstance(1, "testJob");
     _jobExecution   = new JobExecution(_jobInstance, new JobParameters());
     _stepExecution1 = new StepExecution("testStep1", _jobExecution, 1);
     _stepExecution2 = new StepExecution("testStep2", _jobExecution, 2);
 }
예제 #8
0
        private void When_customer_adds_it_to_the_basket()
        {
            var product = "product";

            StepExecution.Comment(string.Format("Transferring '{0}' to the basket", product));
            _transferResult = _stock.TransferToBasket(_basket, product);
        }
        /// <summary>
        /// Logic launched after the step. Will launch the postprocessor.
        /// @see IStepExecutionListener#AfterStep
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <returns></returns>
        public virtual ExitStatus AfterStep(StepExecution stepExecution)
        {
            ExitStatus returnStatus = stepExecution.ExitStatus;

            if (!"FAILED".Equals(returnStatus.ExitCode))
            {
                MethodInfo post = this.GetType().GetMethod("Postprocess", BindingFlags.Instance | BindingFlags.NonPublic);
                if (post.DeclaringType != typeof(AbstractExecutionListener))
                {
                    using (var scope = TransactionScopeManager.CreateScope())
                    {
                        try
                        {
                            returnStatus = Postprocess();
                        }
                        catch (Exception e)
                        {
                            // Need to catch exception to log and set status to FAILED, while
                            // Spring batch would only log and keep the status COMPLETED
                            Logger.Error(e, "Exception during postprocessor");
                            stepExecution.UpgradeStatus(BatchStatus.Failed);
                            throw;
                        }
                        scope.Complete();
                    }
                }
            }
            return(returnStatus);
        }
        /// <summary>
        /// @see IStepExecutionDao#SaveStepExecution.
        /// </summary>
        /// <param name="stepExecution"></param>
        public void SaveStepExecution(StepExecution stepExecution)
        {
            Assert.IsTrue(stepExecution.Id == null);
            Assert.IsTrue(stepExecution.Version == null);
            var jobExecutionId = stepExecution.GetJobExecutionId();

            if (jobExecutionId == null)
            {
                throw new ArgumentException("The corresponding job execution must have already been saved.");
            }

            IDictionary <long?, StepExecution> executions;

            if (!_executionsByJobExecutionId.TryGetValue(jobExecutionId, out executions))
            {
                executions = new Dictionary <long?, StepExecution>();
                _executionsByJobExecutionId[jobExecutionId] = executions;
            }

            stepExecution.Id = Interlocked.Increment(ref _currentId);
            stepExecution.IncrementVersion();
            StepExecution copy = Copy(stepExecution);

            executions[stepExecution.Id] = copy;
            _executionsByStepExecutionId[stepExecution.Id] = copy;
        }
예제 #11
0
        private void Given_product_is_in_stock()
        {
            var product = "product";

            _stock.Add(product);
            StepExecution.Comment(string.Format("Added '{0}' to the stock", product));
        }
        /// <summary>
        /// @see AbstractPartitionHandler#DoHandle .
        /// </summary>
        /// <param name="masterStepExecution"></param>
        /// <param name="partitionStepExecutions"></param>
        /// <returns></returns>
        protected override ICollection <StepExecution> DoHandle(StepExecution masterStepExecution, ICollection <StepExecution> partitionStepExecutions)
        {
            Assert.NotNull(Step, "A Step must be provided.");
            HashSet <Task <StepExecution> > tasks  = new HashSet <Task <StepExecution> >();
            HashSet <StepExecution>         result = new HashSet <StepExecution>();

            foreach (StepExecution stepExecution in partitionStepExecutions)
            {
                Task <StepExecution> task = CreateTask(Step, stepExecution);
                try
                {
                    _taskExecutor.Execute(task);
                    tasks.Add(task);
                }
                catch (TaskRejectedException)
                {
                    // couldn't execute one of the tasks
                    ExitStatus exitStatus = ExitStatus.Failed.AddExitDescription("TaskExecutor rejected the task for this step.");

                    // Set the status in case the caller is tracking it through the
                    // JobExecution.
                    stepExecution.BatchStatus = BatchStatus.Failed;
                    stepExecution.ExitStatus  = exitStatus;
                    result.Add(stepExecution);
                }
            }

            foreach (Task <StepExecution> task in tasks)
            {
                // Accessing Result is blocking (waits for asynchronous execution to complete)
                result.Add(task.Result);
            }

            return(result);
        }
 /// <summary>
 /// Checks if step execution has been interrupted. Throws a JobInterrupdeException in that case.
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <exception cref="JobInterruptedException">&nbsp;</exception>
 public void CheckInterrupted(StepExecution stepExecution)
 {
     if (IsInterrupted(stepExecution))
     {
         throw new JobInterruptedException("Job interrupted status detected.");
     }
 }
예제 #14
0
 /// <summary>
 /// Creates a row mapper that for step executions.
 /// </summary>
 /// <param name="jobExecution">the job execution to use when creating the step executions</param>
 /// <returns>a row mapper</returns>
 private static RowMapper <StepExecution> GetStepExecutionRowMapper(JobExecution jobExecution)
 {
     return((dataRecord, i) =>
     {
         var wrapper = new DataRecordWrapper(dataRecord);
         var stepExecution = new StepExecution(wrapper.Get <string>((1)), jobExecution, wrapper.Get <long>((0)))
         {
             StartTime = wrapper.Get <DateTime>((2)),
             EndTime = wrapper.Get <DateTime>((3)),
             BatchStatus = BatchStatus.ValueOf(wrapper.Get <string>((4))),
             CommitCount = wrapper.Get <int>((5)),
             ReadCount = wrapper.Get <int>((6)),
             FilterCount = wrapper.Get <int>((7)),
             WriteCount = wrapper.Get <int>((8)),
             ExitStatus = new ExitStatus(wrapper.Get <string>((9)), wrapper.Get <string>(10)),
             ReadSkipCount = wrapper.Get <int>((11)),
             WriteSkipCount = wrapper.Get <int>((12)),
             ProcessSkipCount = wrapper.Get <int>((13)),
             RollbackCount = wrapper.Get <int>((14)),
             LastUpdated = wrapper.Get <DateTime?>(15),
             Version = wrapper.Get <int?>((16))
         };
         return stepExecution;
     });
 }
예제 #15
0
            public ExitStatus AfterStep(StepExecution stepExecution)
            {
                JobExecution job     = stepExecution.JobExecution;
                var          jobName = job.JobInstance.JobName;

                var      filePathName = Path.Combine(TestDataDirectoryLogs, "1_" + jobName + "_" + job.StartTime.Value.Ticks + ".log");
                FileInfo fInfo        = new FileInfo(filePathName);

                using (StreamWriter logSW = new StreamWriter(fInfo.FullName, true))
                {
                    logSW.WriteLine("Job Name: " + jobName + ", Id: " + job.Id + " ended with BatchError.");
                    for (int i = job.StepExecutions.Count - 1; i > 0; i--)
                    {
                        var stepName    = job.StepExecutions.ElementAt(i).StepName;
                        var exitCode    = job.StepExecutions.ElementAt(i).ExitStatus.ExitCode;
                        var batchStatus = job.StepExecutions.ElementAt(i).BatchStatus;
                        var summary     = job.StepExecutions.ElementAt(i).GetSummary();
                        ICollection <Exception> exceptions = job.StepExecutions.ElementAt(i).GetFailureExceptions();

                        logSW.WriteLine(summary);
                        logSW.WriteLine("Step: " + stepName + ", Batch Status: " + batchStatus + ", Exit Status: " + exitCode);
                        for (int j = 0; j < exceptions.Count; j++)
                        {
                            logSW.WriteLine("Exception @ Step[" + stepName + "]: " + exceptions.ElementAt(j).InnerException);
                        }
                    }
                }

                return(ExitStatus.Completed);
            }
예제 #16
0
        /// <summary>
        /// Creates the parameters for inserting a new step execution in the database.
        /// </summary>
        /// <param name="stepExecution">the step execution to insert</param>
        /// <returns>an array containing the parameters</returns>
        private IDictionary <string, object> BuildStepExecutionParameters(StepExecution stepExecution)
        {
            Assert.NotNull(stepExecution, "the step execution must not be null");
            Assert.NotNull(stepExecution.StepName, "the step execution name must not be null");
            Assert.IsNull(stepExecution.Id, "the step execution must not already have an id");
            Assert.IsNull(stepExecution.Version, "the step execution must not already have a version");

            stepExecution.Id = _stepExecutionIncrementer.NextLong();
            stepExecution.IncrementVersion();

            var exitDescription = TruncateExitDescription(stepExecution.ExitStatus.ExitDescription);
            var parameters      = new Dictionary <string, object>
            {
                { "id", stepExecution.Id }, { "version", stepExecution.Version }, { "stepName", stepExecution.StepName },
                { "jobId", stepExecution.GetJobExecutionId() }, { "startTime", stepExecution.StartTime },
                { "endTime", (object)stepExecution.EndTime ?? DBNull.Value }, { "status", stepExecution.BatchStatus.ToString() },
                { "commitCount", stepExecution.CommitCount }, { "readCount", stepExecution.ReadCount }, { "filterCount", stepExecution.FilterCount },
                { "writeCount", stepExecution.FilterCount }, { "exitCode", stepExecution.ExitStatus.ExitCode }, { "exitMessage", exitDescription },
                { "readSkipCount", stepExecution.ReadSkipCount }, { "writeSkipCount", stepExecution.WriteSkipCount },
                { "processSkipCount", stepExecution.ProcessSkipCount }, { "rollbackCount", stepExecution.RollbackCount },
                { "lastUpdated", (object)stepExecution.LastUpdated ?? DBNull.Value }
            };

            return(parameters);
        }
예제 #17
0
 /// <summary>
 /// Gets execution dependencies for a given StepExecution.
 /// </summary>
 /// <param name="stepExecution"></param>
 private void GetStepExecutionDependencies(StepExecution stepExecution)
 {
     if (stepExecution != null)
     {
         stepExecution.ExecutionContext = _executionContextDao.GetExecutionContext(stepExecution);
     }
 }
예제 #18
0
        /// <summary>
        /// Verifies that the <see cref="ProgressControllerStep"/> was initialized correctly
        /// </summary>
        /// <param name="testSubject">The step to verify</param>
        /// <param name="attributes">Step attributes</param>
        /// <param name="displayText">Step display text</param>
        public static void VerifyInitialized(ProgressControllerStep testSubject, StepAttributes attributes, string displayText = null)
        {
            StepExecution expectedExecution         = (attributes & StepAttributes.BackgroundThread) != 0 ? StepExecution.BackgroundThread : StepExecution.ForegroundThread;
            bool          expectedHidden            = (attributes & StepAttributes.Hidden) != 0 ? true : false;
            bool          expectedCancellable       = (attributes & StepAttributes.NonCancellable) != 0 ? false : true;
            bool          expectedImpactingProgress = (attributes & StepAttributes.NoProgressImpact) != 0 ? false : true;
            bool          expectedIndeterminate     = (attributes & StepAttributes.Indeterminate) != 0 ? true : false;

            CheckState(testSubject, StepExecutionState.NotStarted);
            Assert.AreEqual(displayText, testSubject.DisplayText, "Unexpected display text");
            Assert.AreEqual(expectedCancellable, testSubject.Cancellable, "Cancellable: Unexpected post initialization value");
            Assert.AreEqual(expectedIndeterminate, testSubject.Indeterminate, "Indeterminate: Unexpected post initialization value");
            Assert.AreEqual(expectedExecution, testSubject.Execution, "Execution: Unexpected post initialization value");
            Assert.AreEqual(expectedHidden, testSubject.Hidden, "Hidden: Unexpected post initialization value");
            Assert.AreEqual(expectedImpactingProgress, testSubject.ImpactsProgress, "ImpactingProgress: Unexpected post initialization value");

            if (expectedIndeterminate)
            {
                Assert.IsTrue(ProgressControllerHelper.IsIndeterminate(testSubject.Progress), "Progess: Should be Indeterminate");
            }
            else
            {
                Assert.AreEqual(0, testSubject.Progress, "Progress: Unexpected post initialization value");
            }
        }
        /// <summary>
        /// registers both job and step contexts.
        /// </summary>
        /// <param name="stepExecution"></param>
        private void RegisterContexts(StepExecution stepExecution)
        {
            JobExecution jobExecution = stepExecution.JobExecution;

            JobContextManager.Context  = jobExecution.ExecutionContext;
            StepContextManager.Context = stepExecution.ExecutionContext;
        }
        /// <summary>
        /// Launch Master timer method in the controlThread.
        /// </summary>
        /// <param name="stepExectuionObject"></param>
        private void MasterTimerMethod(object stepExectuionObject)
        {
            StepExecution stepExecution = (StepExecution)stepExectuionObject;

            Logger.Debug("-------------------------------------------- Master Timer --------------------------------------------");
            string       stepName             = stepExecution.StepName;
            ControlQueue masterLifeLineQueue  = stepExecution.remoteChunking._masterLifeLineQueue;
            string       masterNoAliveMessage = stepName + dot + bool.FalseString;

            // stop timer when batch failed
            if ("FAILED".Equals(stepExecution.ExitStatus.ExitCode))
            {
                masterLifeLineQueue.Send(masterNoAliveMessage);
                return;
            }
            else // continue update workerMap in the stepExecution and check workers alive
            {
                Dictionary <string, bool> workerMap    = stepExecution.remoteChunking._workerMap;
                List <string>             workerIDList = stepExecution.remoteChunking._workerStartedQueue.GetWorkerIDByMasterName(stepExecution.StepName);
                foreach (string workerID in workerIDList)
                {
                    if (!workerMap.ContainsKey(workerID))
                    {
                        workerMap[workerID] = true;
                    }
                }
                ControlQueue  workerLifeLineQueue = stepExecution.remoteChunking._workerLifeLineQueue;
                List <string> workerIDs           = new List <string>(workerMap.Keys);
                workerLifeLineQueue.CheckMessageExistAndConsumeAll(workerIDs, workerMap);
            }
        }
예제 #21
0
 /// <summary>
 /// Comments currently executed step with a <paramref name="comment"/> text.
 /// The comment would be included in progress notification, as well as in execution reports.
 /// <para>This feature has to be enabled in <see cref="LightBddConfiguration"/> via <see cref="CommentingConfigurationExtensions.EnableStepCommenting"/>() prior to usage.</para>
 /// </summary>
 /// <param name="execution">Current step execution instance.</param>
 /// <param name="comment">Comment to add. If comment is <c>null</c> or empty, it will not be added.</param>
 public static void Comment(this StepExecution execution, string comment)
 {
     if (!string.IsNullOrWhiteSpace(comment))
     {
         ScenarioExecutionContext.Current.Get <CurrentStepProperty>().Step.Comment(comment);
     }
 }
예제 #22
0
 /// <summary>
 /// Adds StepExecution.
 /// </summary>
 /// <param name="stepExecution"></param>
 public void Add(StepExecution stepExecution)
 {
     ValidateStepExecution(stepExecution);
     stepExecution.LastUpdated = DateTime.Now;
     _stepExecutionDao.SaveStepExecution(stepExecution);
     _executionContextDao.SaveExecutionContext(stepExecution);
 }
예제 #23
0
        /// <summary>
        ///  Handler of steps sequentially as provided, checking each one for success
        /// before moving to the next. Returns the last StepExecution
        /// successfully processed if it exists, and null if none were processed.
        /// </summary>
        /// <param name="execution"></param>
        protected override void DoExecute(JobExecution execution)
        {
            StepExecution stepExecution = null;

            foreach (IStep step in _steps)
            {
                stepExecution = HandleStep(step, execution);
                if (stepExecution.BatchStatus != BatchStatus.Completed)
                {
                    break;
                }
            }

            //
            // Update the job status to be the same as the last step
            //
            if (stepExecution != null)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug("Upgrading JobExecution status: {0}", stepExecution);
                }
                execution.UpgradeStatus(stepExecution.BatchStatus);
                execution.ExitStatus = stepExecution.ExitStatus;
            }
        }
예제 #24
0
        /// <summary>
        /// Template method for step execution logic - calls abstract methods for resource initialization (
        /// Open), execution Logic (DoExecute) and resource closing (Close).
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <exception cref="JobInterruptedException">&nbsp;</exception>
        /// <exception cref="UnexpectedJobExecutionException">&nbsp;</exception>
        public void Execute(StepExecution stepExecution)
        {
            Logger.Debug("Executing: id={0}", stepExecution.Id);
            stepExecution.StartTime   = DateTime.Now;
            stepExecution.BatchStatus = BatchStatus.Started;
            stepExecution.DelayConfig = DelayConfig;
            JobRepository.Update(stepExecution);

            // Start with a default value that will be trumped by anything
            ExitStatus exitStatus = ExitStatus.Executing;

            DoExecutionRegistration(stepExecution);

            try
            {
                exitStatus = HandleExecution(stepExecution);
            }
            catch (Exception e)
            {
                exitStatus = HandleExecutionException(stepExecution, e, exitStatus);
            }
            finally
            {
                exitStatus = HandleListener(stepExecution, exitStatus);
                exitStatus = HandleUpdateExecutionContext(stepExecution, exitStatus);
                HandleUpdateStepExecution(stepExecution, exitStatus);
                HandleCloseAndRelease(stepExecution);
                stepExecution.ExecutionContext.Put("batch.executed", true);
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug("Step execution complete:{0}", stepExecution.GetSummary());
                }
            }
        }
예제 #25
0
        /// <summary>
        /// Given a step and configuration, return true if the step should start,
        /// false if it should not, and throw an exception if the job should finish.
        /// </summary>
        /// <param name="lastStepExecution"></param>
        /// <param name="jobExecution"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        /// <exception cref="JobRestartException">&nbsp;</exception>
        /// <exception cref="StartLimitExceededException">&nbsp;</exception>
        protected bool ShouldStart(StepExecution lastStepExecution, JobExecution jobExecution, IStep step)
        {
            var stepStatus = lastStepExecution == null ? BatchStatus.Starting : lastStepExecution.BatchStatus;

            if (stepStatus == BatchStatus.Unknown)
            {
                throw new JobRestartException("Cannot restart step from UNKNOWN status. "
                                              + "The last execution ended with a failure that could not be rolled back, "
                                              + "so it may be dangerous to proceed. Manual intervention is probably necessary.");
            }

            if (stepStatus == BatchStatus.Completed &&
                (step.AllowStartIfComplete != null && !step.AllowStartIfComplete.Value) ||
                stepStatus == BatchStatus.Abandoned)
            {
                // step is complete, false should be returned, indicating that the
                // step should not be started
                Logger.Info("Step already complete or not restartable, so no action to execute: {0}", lastStepExecution);
                return(false);
            }

            if (JobRepository.GetStepExecutionCount(jobExecution.JobInstance, step.Name) < step.StartLimit)
            {
                // step start count is less than start max, return true
                return(true);
            }
            else
            {
                // start max has been exceeded, throw an exception.

                throw new StartLimitExceededException(
                          string.Format("Maximum start limit exceeded for step: {0} StartMax: {1}",
                                        step.Name, step.StartLimit));
            }
        }
예제 #26
0
 /// <summary>
 /// Custom constructor
 /// </summary>
 /// <param name="chunkContext"></param>
 /// <param name="semaphore"></param>
 /// <param name="owner"></param>
 public ChunkTransactionCallback(ChunkContext chunkContext, Semaphore semaphore, TaskletStep owner)
 {
     _chunkContext  = chunkContext;
     _stepExecution = chunkContext.StepContext.StepExecution;
     _semaphore     = semaphore;
     _ownerStep     = owner;
 }
예제 #27
0
        /// <summary>
        /// Performs the actual check and returns the code "EMPTY" or "NOT_EMPTY" accordingly
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <returns>"EMPTY" or "NOT_EMPTY"</returns>
        public ExitStatus AfterStep(StepExecution stepExecution)
        {
            string exitCode = Empty;

            try
            {
                FileInfo file = FileToCheck.GetFileInfo();

                if (file.Exists && (file.Attributes & FileAttributes.Directory) != FileAttributes.Directory &&
                    file.Length > 0)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("File [{0}] is not empty ! length =[{1}]", file.FullName, file.Length);
                    }
                    exitCode = NotEmpty;
                }
                else
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("File [{0}] is empty .", file.FullName);
                    }
                }
            }
            catch (IOException)
            {
                Logger.Error("Error accessing file " + FileToCheck.GetFilename());
            }

            return(new ExitStatus(exitCode));
        }
        /// <summary>
        /// Tests if step execution should start.
        /// </summary>
        /// <param name="allowStartIfComplete"></param>
        /// <param name="stepExecution"></param>
        /// <param name="lastStepExecution"></param>
        /// <returns></returns>
        /// <exception cref="JobExecutionException"></exception>
        private bool ShouldStart(bool allowStartIfComplete, StepExecution stepExecution, StepExecution lastStepExecution)
        {
            if (lastStepExecution == null)
            {
                return(true);
            }
            BatchStatus stepStatus = lastStepExecution.BatchStatus;

            //unknown status handling
            HandleUnknownStatus(stepStatus);

            //Completed status handling
            if (stepStatus == BatchStatus.Completed)
            {
                return(allowStartIfComplete || IsSameJobExecution(stepExecution, lastStepExecution));
            }

            //Stopped or failed permits restart
            if (HandleStoppedOrFailedStatus(stepStatus))
            {
                return(true);
            }

            //other statuses should not allow restart.
            PreventFromRestarting(stepStatus);

            throw new JobExecutionException(
                      string.Format("Cannot restart step from {0} status.  "
                                    + "We believe the old execution was abandoned and therefore has been marked as un-restartable.",
                                    stepStatus));
        }
        /// <summary>
        /// @see IStepExecutionDao#UpdateStepExecution.
        /// </summary>
        /// <param name="stepExecution"></param>
        public void UpdateStepExecution(StepExecution stepExecution)
        {
            IDictionary <long?, StepExecution> executions;
            StepExecution persisted;
            var           jobExecutionId = stepExecution.GetJobExecutionId();

            if (jobExecutionId == null || !_executionsByJobExecutionId.TryGetValue(jobExecutionId, out executions) ||
                stepExecution.Id == null || !_executionsByStepExecutionId.TryGetValue(stepExecution.Id, out persisted))
            {
                throw new ArgumentException("The step execution must have already been saved.");
            }

            lock (stepExecution)
            {
                if (persisted.Version != stepExecution.Version)
                {
                    throw new ArgumentException(string.Format("Attempt to update step execution (id={0}) with version {1}, but current version is {2}.",
                                                              stepExecution.Id, stepExecution.Version, persisted.Version));
                }
                stepExecution.IncrementVersion();
                StepExecution copy = Copy(stepExecution);
                executions[stepExecution.Id] = copy;
                _executionsByStepExecutionId[stepExecution.Id] = copy;
            }
        }
예제 #30
0
 /// <summary>
 /// Checks if step execution has been interrupted. Throws a JobInterrupdeException in that case.
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <exception cref="JobInterruptedException"></exception>
 public void CheckInterrupted(StepExecution stepExecution)
 {
     if (IsInterrupted(stepExecution))
     {
         throw new JobInterruptedException("Job interrupted status detected.");
     }
 }
        /// <summary>
        /// Logic launched before the step. Will register the contexts and launch the preprocessor.
        /// @see IStepExecutionListener#BeforeStep
        /// </summary>
        /// <param name="stepExecution"></param>
        public virtual void BeforeStep(StepExecution stepExecution)
        {
            RegisterContexts(stepExecution);


            if (stepExecution.remoteChunking != null)
            {
                AutoResetEvent threadWait = new AutoResetEvent(false);

                // master step create control thread
                if (stepExecution.remoteChunking._master)
                {
                    // controlthread with callback method
                    Thread thread = new Thread((ThreadStart)(() => Master(stepExecution, threadWait)));
                    stepExecution.remoteChunking.controlThread = thread;
                    stepExecution.remoteChunking.threadWait    = threadWait;
                    thread.Start();
                    TimeSpan _maxMasterWaitWorkerSecond = TimeSpan.FromSeconds(stepExecution.remoteChunking.MaxMasterWaitWorkerSecond);
                    int      _maxMasterWaitWorkerRetry  = stepExecution.remoteChunking.MaxMasterWaitWorkerRetry;
                    // wait for Master method send back workerStarted signal
                    if (threadWait.WaitOne(_maxMasterWaitWorkerSecond * _maxMasterWaitWorkerRetry))
                    {
                        Logger.Info("Worker is started.");
                    }
                    else
                    {
                        // clean all message queues when no work job provided
                        Exception e = new JobExecutionException("No worker job provided");
                        Logger.Error(e, "Clean message in the Queue.");
                        stepExecution.remoteChunking.CleanAllQueue();
                        throw e;
                    }
                }
                else // worker step create control thread
                {
                    Thread thread = new Thread((ThreadStart)(() => Worker(stepExecution, threadWait)));
                    stepExecution.remoteChunking.controlThread = thread;
                    stepExecution.remoteChunking.threadWait    = threadWait;
                    thread.Start();
                }
            }
            if (!stepExecution.ExecutionContext.ContainsKey(PreProcessor))
            {
                stepExecution.ExecutionContext.Put(PreProcessor, true);
            }

            if (!stepExecution.ExecutionContext.ContainsKey(Restart) || (stepExecution.ExecutionContext.ContainsKey(PreProcessor) && (bool)stepExecution.ExecutionContext.Get(PreProcessor)))
            {
                try
                {
                    Preprocess();
                    stepExecution.ExecutionContext.Put(PreProcessor, false);
                }
                catch (Exception e)
                {
                    throw;
                }
            }
        }
 private void When_I_clear_it(ScenarioContext ctx)
 {
     foreach (var contact in ctx.ContactBook.Contacts.ToArray())
     {
         ctx.ContactBook.Remove(contact.Name);
     }
     StepExecution.Bypass("Contact book clearing is not implemented yet. Contacts are removed one by one.");
 }
예제 #33
0
 /// <summary>
 /// Check to determine whether or not the JobExecution that is the parent of
 /// the provided StepExecution has been interrupted. If, after synchronizing
 /// the status with the database, the status has been updated to STOPPING,
 /// then the job has been interrupted.
 /// </summary>
 /// <param name="stepExecution"></param>
 private void CheckForInterruption(StepExecution stepExecution)
 {
     JobExecution jobExecution = stepExecution.JobExecution;
     _jobExecutionDao.SynchronizeStatus(jobExecution);
     if (jobExecution.IsStopping())
     {
         _logger.Info("Parent JobExecution is stopped, so passing message on to StepExecution");
         stepExecution.SetTerminateOnly();
     }
 }
 /// <summary>
 /// Test for api or applicative interruption.
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <returns></returns>
 private bool IsInterrupted(StepExecution stepExecution)
 {
     bool interrupted = ThreadUtils.IsCurrentThreadInterrupted();
     if (interrupted)
     {
         Logger.Info("Step interrupted through Thread API");
     }
     else
     {
         interrupted = stepExecution.TerminateOnly;
         if (interrupted)
         {
             Logger.Info("Step interrupted through StepExecution");
         }
     }
     return interrupted;
 }
 /// <summary>
 /// Aggregates the input executions into the result <see cref="StepExecution"/>.
 /// The aggregated fields are:
 /// <list type="table">
 ///     <item>
 ///         <term>BatchStatus</term>
 ///         <description>using the highest value using <see cref="BatchStatus.Max"/></description>
 ///     </item>
 ///     <item>
 ///         <term>ExitStatus</term>
 ///         <description>using <see cref="ExitStatus.And"/></description>
 ///     </item>
 ///     <item>
 ///         <term>counters (e.g., CommitCount, RollbackCount)</term>
 ///         <description>by arithmetic sum</description>
 ///     </item>
 /// </list>
 /// </summary>
 /// <param name="result">the result to overwrite</param>
 /// <param name="executions">the inputs</param>
 public void Aggregate(StepExecution result, ICollection<StepExecution> executions)
 {
     Assert.NotNull(result, "To aggregate into a result it must be non-null.");
     if (executions == null)
     {
         return;
     }
     foreach (var stepExecution in executions)
     {
         result.BatchStatus = BatchStatus.Max(result.BatchStatus, stepExecution.BatchStatus);
         result.ExitStatus = result.ExitStatus.And(stepExecution.ExitStatus);
         result.FilterCount = result.FilterCount + stepExecution.FilterCount;
         result.ProcessSkipCount = result.ProcessSkipCount + stepExecution.ProcessSkipCount;
         result.CommitCount = result.CommitCount + stepExecution.CommitCount;
         result.RollbackCount = result.RollbackCount + stepExecution.RollbackCount;
         result.ReadCount = result.ReadCount + stepExecution.ReadCount;
         result.ReadSkipCount = result.ReadSkipCount + stepExecution.ReadSkipCount;
         result.WriteCount = result.WriteCount + stepExecution.WriteCount;
         result.WriteSkipCount = result.WriteSkipCount + stepExecution.WriteSkipCount;
     }
 }
        /// <summary>
        /// @see IJobParametersExtractor#GetJobParameters(Job, StepExecution).
        /// </summary>
        /// <param name="job"></param>
        /// <param name="stepExecution"></param>
        /// <returns></returns>
        public JobParameters GetJobParameters(IJob job, StepExecution stepExecution)
        {
            JobParametersBuilder builder = new JobParametersBuilder();
            IDictionary<string, JobParameter> jobParameters = stepExecution.GetJobParameters().GetParameters();
            ExecutionContext executionContext = stepExecution.ExecutionContext;
            if (_useAllParentParameters)
            {
                foreach (string key in jobParameters.Keys)
                {
                    builder.AddParameter(key, jobParameters[key]);
                }
            }
            foreach (string akey in _keys)
            {
                string key = akey;
                if (key.EndsWith("(long)") || key.EndsWith("(int)"))
                {
                    HandleLongOrIntKey(key, executionContext, builder, jobParameters);
                }
                else if (key.EndsWith("(double)"))
                {
                    HandleDoubleKey(key, executionContext, builder, jobParameters);
                }
                else if (key.EndsWith("(string)"))
                {
                    HandleStringKey(key, executionContext, builder, jobParameters);
                }
                else if (key.EndsWith("(date)"))
                {
                    HandleDateKey(key, executionContext, builder, jobParameters);
                }
                else
                {
                    DefaultHandle(executionContext, key, builder, jobParameters);
                }
            }
            return builder.ToJobParameters();

        }
예제 #37
0
        /// <summary>
        /// @see IStepExecutionDao#SaveStepExecution.
        /// </summary>
        /// <param name="stepExecution"></param>
        public void SaveStepExecution(StepExecution stepExecution)
        {
            Assert.IsTrue(stepExecution.Id == null);
            Assert.IsTrue(stepExecution.Version == null);
            var jobExecutionId = stepExecution.GetJobExecutionId();
            if (jobExecutionId == null)
            {
                throw new ArgumentException("The corresponding job execution must have already been saved.");
            }

            IDictionary<long?, StepExecution> executions;
            if (!_executionsByJobExecutionId.TryGetValue(jobExecutionId, out executions))
            {
                executions = new ConcurrentDictionary<long?, StepExecution>();
                _executionsByJobExecutionId[jobExecutionId] = executions;
            }

            stepExecution.Id = Interlocked.Increment(ref _currentId);
            stepExecution.IncrementVersion();
            StepExecution copy = Copy(stepExecution);
            executions[stepExecution.Id] = copy;
            _executionsByStepExecutionId[stepExecution.Id] = copy;
        }
        /// <summary>
        /// Manage the StepContext lifecycle. Business processing should be
        /// delegated to #DoInChunkContext(RepeatContext, ChunkContext). This
        /// is to ensure that the current thread has a reference to the context, even
        /// if the callback is executed in a pooled thread. Handles the registration
        /// and unregistration of the step context, so clients should not duplicate
        /// those calls.
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <param name="doInChunkContext"></param>
        /// <returns></returns>
        public static RepeatCallback GetRepeatCallback(StepExecution stepExecution, DoInChunkContext doInChunkContext)
        {
            BlockingCollection<ChunkContext> attributeQueue = new BlockingCollection<ChunkContext>();
            return context =>
            {
                // The StepContext has to be the same for all chunks,
                // otherwise step-scoped beans will be re-initialised for each chunk.
                StepContext stepContext = StepSynchronizationManager.Register(stepExecution);
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug("Preparing chunk execution for StepContext: {0}",
                                 ObjectUtils.IdentityToString(stepContext));
                }

                ChunkContext chunkContext;
                attributeQueue.TryTake(out chunkContext);
                if (chunkContext == null)
                {
                    chunkContext = new ChunkContext(stepContext);
                }
                try
                {
                    Logger.Debug("Chunk execution starting: queue size= {0}", attributeQueue.Count);
                    return doInChunkContext(context, chunkContext); //Delegation
                }
                finally
                {
                    // Still some stuff to do with the data in this chunk,
                    // pass it back.
                    if (!chunkContext.Complete)
                    {
                        attributeQueue.Add(chunkContext);
                    }
                    StepSynchronizationManager.Close();
                }
            };
        }
예제 #39
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <returns></returns>
        private ExitStatus HandleExecution(StepExecution stepExecution)
        {
            _stepExecutionListener.BeforeStep(stepExecution);
            Open(stepExecution.ExecutionContext);
            try
            {
                DoExecute(stepExecution);
            }
            catch (RepeatException e)
            {
                throw e.InnerException;
            }
            var exitStatus = ExitStatus.Completed.And(stepExecution.ExitStatus);

            // Check if someone is trying to stop us
            if (stepExecution.TerminateOnly)
            {
                throw new JobInterruptedException("JobExecution interrupted.");
            }

            // Need to upgrade here not set, in case the execution was stopped
            stepExecution.UpgradeStatus(BatchStatus.Completed);
            Logger.Debug("Step execution success: id= {0}", stepExecution.Id);
            return exitStatus;
        } 
예제 #40
0
 /// <summary>
 /// Gets execution dependencies for a given StepExecution.
 /// </summary>
 /// <param name="stepExecution">the given step execution</param>
 private void GetStepExecutionDependencies(StepExecution stepExecution)
 {
     if (stepExecution != null)
     {
         stepExecution.ExecutionContext = _executionContextDao.GetExecutionContext(stepExecution);
     }
 }
예제 #41
0
 /// <summary>
 /// Extension point for subclasses to execute business logic. Subclasses should set the ExitStatus on the
 /// StepExecution before returning.
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <exception cref="Exception"></exception>
 protected abstract void DoExecute(StepExecution stepExecution);
예제 #42
0
 /// <summary>
 /// Rollback StepExecution
 /// </summary>
 /// <param name="stepExecution"></param>
 private void Rollback(StepExecution stepExecution)
 {
     if (!_rolledBack)
     {
         stepExecution.IncrementRollbackCount();
         _rolledBack = true;
     }
 }
예제 #43
0
 /// <summary>
 /// Copy from source StepExecution to target StepExecution
 /// </summary>
 /// <param name="source"></param>
 /// <param name="target"></param>
 private void Copy(StepExecution source, StepExecution target)
 {
     target.Version = source.Version;
     target.WriteCount = source.WriteCount;
     target.FilterCount = source.FilterCount;
     target.CommitCount = source.CommitCount;
     target.ExecutionContext = new ExecutionContext(source.ExecutionContext);
 }
예제 #44
0
        /// <summary>
        /// Given a step and configuration, return true if the step should start,
        /// false if it should not, and throw an exception if the job should finish.	 
        /// </summary>
        /// <param name="lastStepExecution"></param>
        /// <param name="jobExecution"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        /// <exception cref="JobRestartException"></exception>
        /// <exception cref="StartLimitExceededException"></exception>
        protected bool ShouldStart(StepExecution lastStepExecution, JobExecution jobExecution, IStep step)
        {
            var stepStatus = lastStepExecution == null ? BatchStatus.Starting : lastStepExecution.BatchStatus;

            if (stepStatus == BatchStatus.Unknown)
            {
                throw new JobRestartException("Cannot restart step from UNKNOWN status. "
                        + "The last execution ended with a failure that could not be rolled back, "
                        + "so it may be dangerous to proceed. Manual intervention is probably necessary.");
            }

            if (stepStatus == BatchStatus.Completed && 
                ( step.AllowStartIfComplete !=null && !step.AllowStartIfComplete.Value)
                    || stepStatus == BatchStatus.Abandoned)
            {
                // step is complete, false should be returned, indicating that the
                // step should not be started
                Logger.Info("Step already complete or not restartable, so no action to execute: {0}",lastStepExecution);
                return false;
            }

            if (JobRepository.GetStepExecutionCount(jobExecution.JobInstance, step.Name) < step.StartLimit)
            {
                // step start count is less than start max, return true
                return true;
            }
            else
            {
                // start max has been exceeded, throw an exception.
                
                throw new StartLimitExceededException(
                    string.Format("Maximum start limit exceeded for step: {0} StartMax: {1}", 
                        step.Name, step.StartLimit));
            }
        }
예제 #45
0
        /// <summary>
        /// Template method for step execution logic - calls abstract methods for resource initialization (
        /// Open), execution Logic (DoExecute) and resource closing (Close).
        /// </summary>
        /// <param name="stepExecution"></param>
        /// <exception cref="JobInterruptedException"></exception>
        /// <exception cref="UnexpectedJobExecutionException"></exception>
        public void Execute(StepExecution stepExecution)
        {
            Logger.Debug("Executing: id={0}", stepExecution.Id);
            stepExecution.StartTime = DateTime.Now;
            stepExecution.BatchStatus = BatchStatus.Started;
            JobRepository.Update(stepExecution);

            // Start with a default value that will be trumped by anything
            ExitStatus exitStatus = ExitStatus.Executing;
            DoExecutionRegistration(stepExecution);

            try
            {
                exitStatus = HandleExecution(stepExecution);
            }
            catch (Exception e)
            {
                exitStatus = HandleExecutionException(stepExecution, e, exitStatus);
            }
            finally
            {
                exitStatus = HandleListener(stepExecution, exitStatus);
                exitStatus = HandleUpdateExecutionContext(stepExecution, exitStatus);
                HandleUpdateStepExecution(stepExecution, exitStatus);
                HandleCloseAndRelease(stepExecution);

                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug("Step execution complete:{0}", stepExecution.GetSummary());
                }
            }
        }
예제 #46
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="stepExecution"></param>
        private void HandleCloseAndRelease(StepExecution stepExecution)
        {
            try
            {
                Close(stepExecution.ExecutionContext);
            }
            catch (Exception e)
            {
                Logger.Error(e, "Exception while closing step execution resources in step {0} in job {1}", Name,
                    stepExecution.JobExecution.JobInstance.JobName);
                stepExecution.AddFailureException(e);
            }

            DoExecutionRelease();
        }
예제 #47
0
 /// <summary>
 /// Handle restartability if needed.
 /// </summary>
 /// <param name="lastStepExecution"></param>
 /// <param name="currentStepExecution"></param>
 private void HandleRestart(StepExecution lastStepExecution, StepExecution currentStepExecution)
 {
     bool isRestart = (lastStepExecution != null && !lastStepExecution.BatchStatus.Equals(BatchStatus.Completed));
     if (isRestart)
     {
         currentStepExecution.ExecutionContext = lastStepExecution.ExecutionContext;
         if (lastStepExecution.ExecutionContext.ContainsKey("batch.executed"))
         {
             currentStepExecution.ExecutionContext.Remove("batch.executed");
         }
     }
     else
     {
         currentStepExecution.ExecutionContext = new ExecutionContext(_executionContext);
     }
 }
 /// <summary>
 /// @see IStepExecutionListener#BeforeStep .
 /// </summary>
 /// <param name="stepExecution"></param>
 public virtual void BeforeStep(StepExecution stepExecution)
 {
 }
예제 #49
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <param name="e"></param>
 /// <param name="exitStatus"></param>
 /// <returns></returns>
 private ExitStatus HandleExecutionException(StepExecution stepExecution, Exception e, ExitStatus exitStatus)
 {
     stepExecution.UpgradeStatus(DetermineBatchStatus(e));
     ExitStatus returnedExitStatus = exitStatus.And(GetDefaultExitStatusForFailure(e));
     stepExecution.AddFailureException(e);
     if (stepExecution.BatchStatus == BatchStatus.Stopped)
     {
         Logger.Info("Encountered interruption executing step {0} in job {1} : {2}",
             Name, stepExecution.JobExecution.JobInstance.JobName, e.Message);
         if (Logger.IsDebugEnabled)
         {
             Logger.Debug(e, "Full exception");
         }
     }
     else
     {
         Logger.Error(e, "Encountered an error executing step {0} in job {1} :", Name,
             stepExecution.JobExecution.JobInstance.JobName);
     }
     return returnedExitStatus;
 }
예제 #50
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <param name="exitStatus"></param>
 /// <returns></returns>
 private ExitStatus HandleListener(StepExecution stepExecution, ExitStatus exitStatus)
 {
     ExitStatus returnedExitStatus = exitStatus;
     try
     {
         // Update the step execution to the latest known value so the
         // listeners can act on it
         returnedExitStatus = returnedExitStatus.And(stepExecution.ExitStatus);
         stepExecution.ExitStatus = returnedExitStatus;
         Logger.Trace("_stepExecutionListener.AfterStep CALL");
         returnedExitStatus = returnedExitStatus.And(_stepExecutionListener.AfterStep(stepExecution));
     }
     catch (Exception e)
     {
         Logger.Error(e, "Exception in afterStep callback in step {0} in job {1}", Name,
             stepExecution.JobExecution.JobInstance.JobName);
     }
     return returnedExitStatus;
 }
예제 #51
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <param name="exitStatus"></param>
 /// <returns></returns>
 private ExitStatus HandleUpdateExecutionContext(StepExecution stepExecution, ExitStatus exitStatus)
 {
     ExitStatus returnedExitStatus = exitStatus;
     try
     {
         JobRepository.UpdateExecutionContext(stepExecution);
     }
     catch (Exception e)
     {
         stepExecution.BatchStatus = BatchStatus.Unknown;
         returnedExitStatus = exitStatus.And(ExitStatus.Unknown);
         stepExecution.AddFailureException(e);
         Logger.Error(e,
             "Encountered an error saving batch meta data for step {0} in job {1}. This job is now in an unknown state and should not be restarted.",
             Name, stepExecution.JobExecution.JobInstance.JobName);
     }
     stepExecution.EndTime = DateTime.Now;
     stepExecution.ExitStatus = returnedExitStatus;
     return returnedExitStatus;
 }
예제 #52
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <param name="exitStatus"></param>
 private void HandleUpdateStepExecution(StepExecution stepExecution, ExitStatus exitStatus)
 {
     try
     {
         JobRepository.Update(stepExecution);
     }
     catch (Exception e)
     {
         stepExecution.BatchStatus = BatchStatus.Unknown;
         stepExecution.ExitStatus = exitStatus.And(ExitStatus.Unknown);
         stepExecution.AddFailureException(e);
         Logger.Error(e,
             "Encountered an error saving batch meta data for step {0} in job {1}. This job is now in an unknown state and should not be restarted.",
             Name, stepExecution.JobExecution.JobInstance.JobName);
     }
 }
 /// <summary>
 /// @see IStepExecutionListener#AfterStep .
 /// </summary>
 /// <param name="stepExecution"></param>
 /// <returns></returns>
 public virtual ExitStatus AfterStep(StepExecution stepExecution)
 {
     return null;
 }
예제 #54
0
 /// <summary>
 /// Registers the StepExecution for property resolution via StepScope
 /// </summary>
 /// <param name="stepExecution"></param>
 protected void DoExecutionRegistration(StepExecution stepExecution)
 {
     StepSynchronizationManager.Register(stepExecution);
 }
예제 #55
0
        /// <summary>
        /// Handle normal step execution.
        /// </summary>
        /// <param name="step"></param>
        /// <param name="execution"></param>
        /// <param name="currentStepExecution"></param>
        private void HandleStepExecution(IStep step, JobExecution execution, StepExecution currentStepExecution)
        {
            JobRepository.Add(currentStepExecution);
            Logger.Info("Executing step: [ {0} ]", step.Name);
            try
            {
                step.Execute(currentStepExecution);
                currentStepExecution.ExecutionContext.Put("batch.executed", true);
            }
            catch (JobInterruptedException)
            {
                // Ensure that the job gets the message that it is stopping
                // and can pass it on to other steps that are executing
                // concurrently.
                execution.Status = BatchStatus.Stopping;
                throw;
            }

            JobRepository.UpdateExecutionContext(execution);
        }
예제 #56
0
        /// <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);

            // 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();

                    _interruptionPolicy.CheckInterrupted(stepExecution);
                    return result;
                }
                ));
        }
예제 #57
0
 private bool StepExecutionPartOfExistingJobExecution(JobExecution jobExecution, StepExecution stepExecution)
 {
     return stepExecution != null && stepExecution.GetJobExecutionId() != null
             && stepExecution.GetJobExecutionId().Equals(jobExecution.Id);
 }
예제 #58
0
 /// <summary>
 /// Custom constructor
 /// </summary>
 /// <param name="chunkContext"></param>
 /// <param name="semaphore"></param>
 /// <param name="owner"></param>
 public ChunkTransactionCallback(ChunkContext chunkContext, Semaphore semaphore, TaskletStep owner)
 {
     _chunkContext = chunkContext;
     _stepExecution = chunkContext.StepContext.StepExecution;
     _semaphore = semaphore;
     _ownerStep = owner;
 }
예제 #59
0
 /// <summary>
 /// Create a new instance of StepContext for this StepExecution.
 /// </summary>
 /// <param name="stepExecution"></param>
 public StepContext(StepExecution stepExecution)
 {
     Assert.NotNull(stepExecution, "A StepContext must have a non-null StepExecution");
     _stepExecution = stepExecution;
 }
예제 #60
0
            /// <summary>
            /// Wraps logic into a transactional context.
            /// </summary>
            /// <returns></returns>
            public RepeatStatus DoInTransaction()
            {
                RepeatStatus result;
                StepContribution contribution = _stepExecution.CreateStepContribution();

                // In case we need to push it back to its old value
                // after a commit fails...
                _oldVersion = new StepExecution(_stepExecution.StepName, _stepExecution.JobExecution);
                Copy(_stepExecution, _oldVersion);

                try
                {
                    try
                    {
                        try
                        {
                            result = _ownerStep._tasklet.Execute(contribution, _chunkContext) ?? RepeatStatus.Finished;
                        }
                        catch (Exception e)
                        {
                            _chunkContext.SetAttribute(StepListenerConstant.RollbackExceptionKey, e);
                            throw;
                        }
                    }
                    finally
                    {
                        // If the step operations are asynchronous then we need
                        // to synchronize changes to the step execution (at a
                        // minimum). Take the lock *before* changing the step
                        // execution.
                        try
                        {
                            _semaphore.WaitOne();
                            _locked = true;
                        }
                        catch (Exception)
                        {
                            Logger.Error("Thread interrupted while locking for repository update");
                            _stepExecution.BatchStatus = BatchStatus.Stopped;
                            _stepExecution.SetTerminateOnly();
                            Thread.CurrentThread.Interrupt();
                        }

                        // Apply the contribution to the step
                        // even if unsuccessful
                        if (Logger.IsDebugEnabled)
                        {
                            Logger.Debug("Applying contribution: {0}", contribution);
                        }
                        _stepExecution.Apply(contribution);

                    }
                    _stepExecutionUpdated = true;
                    _ownerStep._stream.Update(_stepExecution.ExecutionContext);

                    try
                    {
                        // Going to attempt a commit. If it fails this flag will
                        // stay false and we can use that later.
                        _ownerStep.JobRepository.UpdateExecutionContext(_stepExecution);
                        _stepExecution.IncrementCommitCount();
                        if (Logger.IsDebugEnabled)
                        {
                            Logger.Debug("Saving step execution before commit: {0}", _stepExecution);
                        }
                        _ownerStep.JobRepository.Update(_stepExecution);
                    }
                    catch (Exception e)
                    {
                        // If we get to here there was a problem saving the step
                        // execution and we have to fail.
                        Logger.Error(e, JobRepositoryForcedRollbackMsg);
                        throw new FatalStepExecutionException(JobRepositoryForcedRollbackMsg, e);
                    }
                }
                catch (Exception e)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug("Rollback for Exception: {0} : {1} ", e.GetType().Name, e.Message);
                    }
                    Rollback(_stepExecution);
                    throw;
                }
                return result;
            }