/// <summary> /// Generates the report /// @see ITasklet#Execute /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { LocalReport report = new LocalReport { ReportPath = ReportFile.GetFileInfo().FullName }; if (Parameters != null && Parameters.Any()) { if (Logger.IsTraceEnabled) { Logger.Trace("{0} parameter(s) were given for the report ", Parameters.Count); } report.SetParameters(Parameters.Select(p => new ReportParameter(p.Key, p.Value))); } else { if (Logger.IsTraceEnabled) { Logger.Trace("No parameter was given for the report "); } } //DataSet DataSet ds = DbOperator.Select(Query, QueryParameterSource); //ReportDataSource ReportDataSource rds = new ReportDataSource { Name = DatasetName, Value = ds.Tables[0] }; report.DataSources.Add(rds); if (Logger.IsTraceEnabled) { Logger.Trace("Report init : DONE => Preparing to render"); } byte[] output = report.Render(ReportFormat); if (Logger.IsTraceEnabled) { Logger.Trace("Report init : rendering DONE => Preparing to serialize"); } //Create target directory if required OutFile.GetFileInfo().Directory.Create(); //dump to target file using (FileStream fs = new FileStream(OutFile.GetFileInfo().FullName, FileMode.Create)) { fs.Write(output, 0, output.Length); } if (Logger.IsTraceEnabled) { Logger.Info("Report init : serialization DONE - end of ReportTasklet execute."); } return(RepeatStatus.Finished); }
/// <summary> /// @see ITasklet#Execute. /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { Chunk <TI> inputs = (Chunk <TI>)chunkContext.GetAttribute(InputsKey); if (inputs == null) { inputs = _chunkProvider.Provide(contribution); if (_buffering) { chunkContext.SetAttribute(InputsKey, inputs); } } _chunkProcessor.Process(contribution, inputs); _chunkProvider.PostProcess(contribution, inputs); // Allow a message coming back from the processor to say that we // are not done yet if (inputs.Busy) { if (_logger.IsDebugEnabled) { _logger.Debug("Inputs still busy"); } return(RepeatStatus.Continuable); } chunkContext.RemoveAttribute(InputsKey); chunkContext.SetComplete(); if (_logger.IsDebugEnabled) { _logger.Debug("Inputs not busy, ended: {0}", inputs.End); } return(RepeatStatus.ContinueIf(!inputs.End)); }
/// <summary> /// Transform inputs. /// </summary> /// <param name="contribution"></param> /// <param name="inputs"></param> /// <returns></returns> /// <exception cref="System.Exception"></exception> protected Chunk <TOut> Transform(StepContribution contribution, Chunk <TIn> inputs) { var outputs = new Chunk <TOut>(); var toRemove = new List <TIn>(); foreach (var item in inputs.Items) { TOut output; try { output = DoProcess(item); } catch (Exception) { // For a simple chunk processor (no fault tolerance) we are done // here, so prevent any more processing of these inputs. inputs.Clear(); throw; } if (output != null) { outputs.Add(output); } else { toRemove.Add(item); } } toRemove.ForEach(i => inputs.Items.Remove(i)); return(outputs); }
private RepeatStatus HandleCompletion(StepContribution contribution, Task <int> systemCommandTask) { contribution.ExitStatus = SystemProcessExitCodeMapper.GetExitStatus(systemCommandTask.Result); if (Logger.IsInfoEnabled) { Logger.Info( "SystemCommandTasklet : System command execution end with exit status [{0}]", contribution.ExitStatus); } return(RepeatStatus.Finished); }
/// <summary> /// see IChunkProcessor#Process. /// </summary> /// <param name="contribution"></param> /// <param name="inputs"></param> public void Process(StepContribution contribution, Chunk <TIn> inputs) { InitializeUserData(inputs); if (IsComplete(inputs)) { return; } Chunk <TOut> outputs = Transform(contribution, inputs); contribution.IncrementFilterCount(GetFilterCount(inputs, outputs)); Write(contribution, inputs, GetAdjustedOutputs(inputs, outputs)); }
public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { // Write counter to a file - Should be running for 10 seconds roughly int counter = 1000; string[] lines = new string[counter]; for (int i = 0; i < counter; i++) { lines[i] = DateTime.Now.Ticks.ToString(); Thread.Sleep(10); } File.WriteAllLines(@"C:\temp\MyDummyTasklet_out_" + DateTime.Now.Ticks + ".txt", lines); return(RepeatStatus.Finished); }
/// <summary> /// Configures a <see cref="Sorter{T}"/> and executes it. /// </summary> /// <param name="contribution">ignored</param> /// <param name="chunkContext">ignored</param> /// <returns><see cref="RepeatStatus.Finished"/></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { Logger.Info("Starting sort tasklet."); var sorter = BuildSorter(); var stopwatch = new Stopwatch(); stopwatch.Start(); sorter.Sort(); stopwatch.Stop(); Logger.Info("Total sort time: {0:F2}s", stopwatch.ElapsedMilliseconds / 1000d); contribution.ExitStatus = ExitStatus.Completed; return(RepeatStatus.Finished); }
/// <summary> /// Simple implementation delegates to the #DoWrite(List) method and /// increments the write count in the contribution. Subclasses can handle /// more complicated scenarios, e.g.with fault tolerance. If output items are /// skipped they should be removed from the inputs as well. /// </summary> /// <param name="contribution"></param> /// <param name="inputs"></param> /// <param name="outputs"></param> /// <exception cref="Exception"></exception> protected void Write(StepContribution contribution, Chunk <TIn> inputs, Chunk <TOut> outputs) { try { DoWrite(outputs.Items); } catch (Exception) { //For a simple chunk processor (no fault tolerance) we are done // here, so prevent any more processing of these inputs. inputs.Clear(); throw; } contribution.IncrementWriteCount(outputs.Size()); }
/// <summary> /// @see IChunkProvider#Provide. /// </summary> /// <param name="contribution"></param> /// <returns></returns> public Chunk <T> Provide(StepContribution contribution) { Chunk <T> inputs = new Chunk <T>(); _repeatOperations.Iterate(context => { var item = Read(contribution, inputs); if (item == null) { inputs.End = true; return(RepeatStatus.Finished); } inputs.Add(item); contribution.IncrementReadCount(); return(RepeatStatus.Continuable); }); return(inputs); }
public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { // open connection using (DbConnection connection = _providerFactory.CreateConnection()) { connection.ConnectionString = _connectionString; connection.Open(); string preparedCommand = PrepareCommands(Resource); DbCommand command = connection.CreateCommand(); command.CommandText = preparedCommand; int sqlDone = command.ExecuteNonQuery(); if (Logger.IsTraceEnabled) { Logger.Trace("SQL script execution end with {0} return code", sqlDone); } } return(RepeatStatus.Finished); }
/// <summary> /// @see ITasklet#Execute() /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { switch (Mode) { case FileUtilsMode.Copy: Copy(); break; case FileUtilsMode.Delete: foreach (IResource target in Targets) { if (target.Exists()) { Delete(target); } else { Error(target); } } break; case FileUtilsMode.Merge: Merge(true); break; case FileUtilsMode.MergeCopy: Merge(false); break; case FileUtilsMode.Reset: Reset(); break; case FileUtilsMode.Compare: Compare(); break; default: throw new InvalidOperationException("This mode is not supported :[" + Mode + "]"); } return(RepeatStatus.Finished); }
/// <summary> /// Execute system command and map its exit code to ExitStatus using <see cref="SystemProcessExitCodeMapper"/>. /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, Scope.Context.ChunkContext chunkContext) { using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource()) { CancellationToken cancellationToken = cancellationTokenSource.Token; using (Task <int> systemCommandTask = new Task <int>(ExecuteCommand, cancellationToken)) { long t0 = DateTime.Now.Ticks; _taskExecutor.Execute(systemCommandTask); while (true) { Thread.Sleep(new TimeSpan(_checkInterval)); CheckStoppingState(chunkContext); if (systemCommandTask.IsCompleted) { return(HandleCompletion(contribution, systemCommandTask)); } else if (new TimeSpan(DateTime.Now.Ticks - t0).TotalMilliseconds > _timeout) { cancellationTokenSource.Cancel(); throw new SystemCommandException( "Execution of system command did not finish within the timeout"); } else if (_execution.TerminateOnly) { cancellationTokenSource.Cancel(); throw new JobInterruptedException( string.Format("Job interrupted while executing system command '{0}'", Command)); } else if (_stopped) { cancellationTokenSource.Cancel(); contribution.ExitStatus = ExitStatus.Stopped; return(RepeatStatus.Finished); } } } } }
/// <summary> /// Read /// Delegates to #DoRead(). Subclasses can add additional behaviour /// (e.g. exception handling). /// </summary> /// <param name="contribution">the current step execution contribution</param> /// <param name="chunk">the current chunk</param> /// <returns>a new item for processing</returns> /// <exception cref="Exception">if there is a generic issue</exception> protected T Read(StepContribution contribution, Chunk <T> chunk) { return(DoRead()); }
/// <summary> /// @see IChunkProvider#PostProcess. /// </summary> /// <param name="contribution"></param> /// <param name="chunk"></param> public void PostProcess(StepContribution contribution, Chunk <T> chunk) { //Left empty on purpose (do nothing) }
/// <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); }
private RepeatStatus HandleCompletion(StepContribution contribution, Task<int> systemCommandTask) { contribution.ExitStatus = SystemProcessExitCodeMapper.GetExitStatus(systemCommandTask.Result); if (Logger.IsInfoEnabled) { Logger.Info( "SystemCommandTasklet : System command execution end with exit status [{0}]", contribution.ExitStatus); } return RepeatStatus.Finished; }
/// <summary> /// Execute system command and map its exit code to ExitStatus using <see cref="SystemProcessExitCodeMapper"/>. /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, Scope.Context.ChunkContext chunkContext) { using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource()) { CancellationToken cancellationToken = cancellationTokenSource.Token; using (Task<int> systemCommandTask = new Task<int>(ExecuteCommand, cancellationToken)) { long t0 = DateTime.Now.Ticks; _taskExecutor.Execute(systemCommandTask); while (true) { Thread.Sleep(new TimeSpan(_checkInterval)); CheckStoppingState(chunkContext); if (systemCommandTask.IsCompleted) { return HandleCompletion(contribution, systemCommandTask); } else if (new TimeSpan(DateTime.Now.Ticks - t0).TotalMilliseconds > _timeout) { cancellationTokenSource.Cancel(); throw new SystemCommandException( "Execution of system command did not finish within the timeout"); } else if (_execution.TerminateOnly) { cancellationTokenSource.Cancel(); throw new JobInterruptedException( string.Format("Job interrupted while executing system command '{0}'",Command)); } else if (_stopped) { cancellationTokenSource.Cancel(); contribution.ExitStatus = ExitStatus.Stopped; return RepeatStatus.Finished; } } } } }
/// <summary> /// Scan remote directory for files matching the given file name pattern and download /// them, if any, to the given local directory. /// @see ITasklet#Execute /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { //Delegated DoExecute(); return(RepeatStatus.Finished); }
/// <summary> /// Wraps command execution into system process call. /// </summary> /// <returns></returns> /// <exception cref="Exception"></exception> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { if (Logger.IsTraceEnabled) { Logger.Trace("*** Executing PowerShell Script File: {0}", ScriptResource.GetFullPath()); } //=> PowerShell will throw an error if we do not Suppress ambient transaction... // see https://msdn.microsoft.com/en-us/library/system.transactions.transaction.current(v=vs.110).aspx#NotExistJustToMakeTheAElementVisible using (var transactionScope = new TransactionScope(TransactionScopeOption.Suppress)) { //=> Runspace configuration information includes the assemblies, commands, format and type files, // providers, and scripts that are available within the runspace. RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); //Creates a single runspace that uses the default host and runspace configuration using (Runspace runSpace = RunspaceFactory.CreateRunspace(runspaceConfiguration)) { //=> When this runspace is opened, the default host and runspace configuration // that are defined by Windows PowerShell will be used. runSpace.Open(); //=> Set Variables so they are available to user script... if (Variables != null && Variables.Any()) { foreach (KeyValuePair<string, object> variable in Variables) { runSpace.SessionStateProxy.SetVariable(variable.Key, variable.Value); } } //=> this is exit status variables to be tested on exit from power shell script... // it is defined in PwerShell global scope...and must be set by scipt writer on exit... runSpace.SessionStateProxy.SetVariable("ScriptExitStatus", _scriptExitStatus); //=> Allows the execution of commands from a CLR //RunspaceInvoke scriptInvoker = new RunspaceInvoke(runSpace); //scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); using (PowerShell psInstance = PowerShell.Create()) { try { // prepare a new collection to store output stream objects PSDataCollection<PSObject> outputCollection = new PSDataCollection<PSObject>(); outputCollection.DataAdded += AllStreams_DataAdded; psInstance.Streams.Error.DataAdded += AllStreams_DataAdded; psInstance.Streams.Verbose.DataAdded += AllStreams_DataAdded; psInstance.Streams.Warning.DataAdded += AllStreams_DataAdded; psInstance.Streams.Debug.DataAdded += AllStreams_DataAdded; psInstance.Runspace = runSpace; //=> This tasklet should be in the same dll as ExitStatus, i.e. Summer.Batch.Core.dll // we need to get the path to loaded Summer.Batch.Core.dll so we can load it in PowerShell var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; //=> need to load Summer.Batch.Core into runspace so we can reference ExitStatus psInstance.AddScript("[System.Reflection.Assembly]::LoadFrom(\""+assemblyLocation+"\")").AddStatement(); //=> add user command and its parameters... psInstance.AddCommand(ScriptResource.GetFullPath()); if (Parameters != null && Parameters.Any()) { foreach (KeyValuePair<string, object> variable in Parameters) { psInstance.AddParameter(variable.Key, variable.Value); } } //=> Invoke Asynchronously... IAsyncResult asyncResult = psInstance.BeginInvoke<PSObject, PSObject>(null, outputCollection); // do something else until execution has completed. long t0 = DateTime.Now.Ticks; while (!asyncResult.IsCompleted) { //=> take a nap and let script do its job... Thread.Sleep(new TimeSpan(_checkInterval)); //=> to check if job was told to stop... CheckStoppingState(chunkContext); //=> lets make sure we did not exceed alloted time... long timeFromT0 = (long)(new TimeSpan(DateTime.Now.Ticks - t0)).TotalMilliseconds; if (timeFromT0 > _timeout) { //=> Stop PowerShell... psInstance.Stop(); //=> behave based on TimeoutBehaviorOption if (_timeoutBehavior.Equals(TimeoutBehaviorOption.SetExitStatusToFailed)) { contribution.ExitStatus = ExitStatus.Failed; break; } else if (_timeoutBehavior.Equals(TimeoutBehaviorOption.ThrowException)) { //=> lets dump what we got before throwing an error... LogStreams(); throw new FatalStepExecutionException("Execution of PowerShell script exceeded allotted time.", null); } } else if (_execution.TerminateOnly) { //=> Stop PowerShell... psInstance.Stop(); //=> lets dump what we got before throwing an error... LogStreams(); throw new JobInterruptedException( string.Format("Job interrupted while executing PowerShell script '{0}'", ScriptResource.GetFilename())); } else if (_stopped) { psInstance.Stop(); contribution.ExitStatus = ExitStatus.Stopped; break; } } // end while scope //=> Wait to the end of execution... //psInstance.EndInvoke(_asyncResult); //NOTE: asyncResult.IsCompleted will be set to true if PowerShell.Stop was called or // PowerShell completed its work //=> if status not yet set (script completed)...handle completion... if (contribution.ExitStatus.IsRunning()) { //=> script needs to set exit code...if exit code not set we assume 0 var lastExitCode = (int)runSpace.SessionStateProxy.PSVariable.GetValue("LastExitCode", 0); _scriptExitStatus = runSpace.SessionStateProxy.GetVariable("ScriptExitStatus") as ExitStatus; //=> set exit status... if (_scriptExitStatus != null && !_scriptExitStatus.IsRunning()) { if (Logger.IsTraceEnabled) { Logger.Trace("***> ScriptExitStatus returned by script => {0}", _scriptExitStatus); } contribution.ExitStatus = _scriptExitStatus; } else //=> let user decide on ExitStatus { if (Logger.IsTraceEnabled) { if (_scriptExitStatus == null) { Logger.Trace("***> ScriptExitStatus is null. Using PowerShellExitCodeMapper to determine ExitStatus."); } else if (_scriptExitStatus.IsRunning()) { Logger.Trace("***> ScriptExitStatus is EXECUTING or UNKNOWN. Using PowerShellExitCodeMapper to determine ExitStatus."); } } if (PowerShellExitCodeMapper != null) { //=> determine exit status using User Provided PowerShellExitCodeMapper contribution.ExitStatus = PowerShellExitCodeMapper.GetExitStatus(lastExitCode); } else //at this point we are not able to determine exit status, user needs to fix this... { //=> lets dump what we got before throwing an error... LogStreams(); throw new FatalStepExecutionException( "PowerShellTasklet is not able to determine ExitStatus. ScriptExitStatus is null or (is EXECUTING or UNKNOWN) and "+ "PowerShellExitCodeMapper is NOT defined. Please set $global:ScriptExitStatus or define PowerShellExitCodeMapper.", null); } } } if (Logger.IsInfoEnabled) { Logger.Info("PowerShell execution exit status [{0}]", contribution.ExitStatus); } //=> output captured stream data to Log... LogStreams(); } catch (RuntimeException ex) { Logger.Error(ex.Message); throw; } } // end PowerShell Scope //=> close Runspace... runSpace.Close(); //=> we are done... return RepeatStatus.Finished; } // end of Runspace Scope }// end of TransactionScope }
public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { _logger.Info("KO transition was used"); throw new Exception("Job failed: Wrong transition used"); }
/// <summary> /// Wraps command execution into system process call. /// </summary> /// <returns></returns> /// <exception cref="Exception"></exception> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { if (Logger.IsTraceEnabled) { Logger.Trace("*** Executing PowerShell Script File: {0}", ScriptResource.GetFullPath()); } //=> PowerShell will throw an error if we do not Suppress ambient transaction... // see https://msdn.microsoft.com/en-us/library/system.transactions.transaction.current(v=vs.110).aspx#NotExistJustToMakeTheAElementVisible using (var transactionScope = new TransactionScope(TransactionScopeOption.Suppress)) { //=> Runspace configuration information includes the assemblies, commands, format and type files, // providers, and scripts that are available within the runspace. RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); //Creates a single runspace that uses the default host and runspace configuration using (Runspace runSpace = RunspaceFactory.CreateRunspace(runspaceConfiguration)) { //=> When this runspace is opened, the default host and runspace configuration // that are defined by Windows PowerShell will be used. runSpace.Open(); //=> Set Variables so they are available to user script... if (Variables != null && Variables.Any()) { foreach (KeyValuePair <string, object> variable in Variables) { runSpace.SessionStateProxy.SetVariable(variable.Key, variable.Value); } } //=> this is exit status variables to be tested on exit from power shell script... // it is defined in PwerShell global scope...and must be set by scipt writer on exit... runSpace.SessionStateProxy.SetVariable("ScriptExitStatus", _scriptExitStatus); //=> Allows the execution of commands from a CLR //RunspaceInvoke scriptInvoker = new RunspaceInvoke(runSpace); //scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); using (PowerShell psInstance = PowerShell.Create()) { try { // prepare a new collection to store output stream objects PSDataCollection <PSObject> outputCollection = new PSDataCollection <PSObject>(); outputCollection.DataAdded += AllStreams_DataAdded; psInstance.Streams.Error.DataAdded += AllStreams_DataAdded; psInstance.Streams.Verbose.DataAdded += AllStreams_DataAdded; psInstance.Streams.Warning.DataAdded += AllStreams_DataAdded; psInstance.Streams.Debug.DataAdded += AllStreams_DataAdded; psInstance.Runspace = runSpace; //=> This tasklet should be in the same dll as ExitStatus, i.e. Summer.Batch.Core.dll // we need to get the path to loaded Summer.Batch.Core.dll so we can load it in PowerShell var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; //=> need to load Summer.Batch.Core into runspace so we can reference ExitStatus psInstance.AddScript("[System.Reflection.Assembly]::LoadFrom(\"" + assemblyLocation + "\")").AddStatement(); //=> add user command and its parameters... psInstance.AddCommand(ScriptResource.GetFullPath()); if (Parameters != null && Parameters.Any()) { foreach (KeyValuePair <string, object> variable in Parameters) { psInstance.AddParameter(variable.Key, variable.Value); } } //=> Invoke Asynchronously... IAsyncResult asyncResult = psInstance.BeginInvoke <PSObject, PSObject>(null, outputCollection); // do something else until execution has completed. long t0 = DateTime.Now.Ticks; while (!asyncResult.IsCompleted) { //=> take a nap and let script do its job... Thread.Sleep(new TimeSpan(_checkInterval)); //=> to check if job was told to stop... CheckStoppingState(chunkContext); //=> lets make sure we did not exceed alloted time... long timeFromT0 = (long)(new TimeSpan(DateTime.Now.Ticks - t0)).TotalMilliseconds; if (timeFromT0 > _timeout) { //=> Stop PowerShell... psInstance.Stop(); //=> behave based on TimeoutBehaviorOption if (_timeoutBehavior.Equals(TimeoutBehaviorOption.SetExitStatusToFailed)) { contribution.ExitStatus = ExitStatus.Failed; break; } else if (_timeoutBehavior.Equals(TimeoutBehaviorOption.ThrowException)) { //=> lets dump what we got before throwing an error... LogStreams(); throw new FatalStepExecutionException("Execution of PowerShell script exceeded allotted time.", null); } } else if (_execution.TerminateOnly) { //=> Stop PowerShell... psInstance.Stop(); //=> lets dump what we got before throwing an error... LogStreams(); throw new JobInterruptedException( string.Format("Job interrupted while executing PowerShell script '{0}'", ScriptResource.GetFilename())); } else if (_stopped) { psInstance.Stop(); contribution.ExitStatus = ExitStatus.Stopped; break; } } // end while scope //=> Wait to the end of execution... //psInstance.EndInvoke(_asyncResult); //NOTE: asyncResult.IsCompleted will be set to true if PowerShell.Stop was called or // PowerShell completed its work //=> if status not yet set (script completed)...handle completion... if (contribution.ExitStatus.IsRunning()) { //=> script needs to set exit code...if exit code not set we assume 0 var lastExitCode = (int)runSpace.SessionStateProxy.PSVariable.GetValue("LastExitCode", 0); _scriptExitStatus = runSpace.SessionStateProxy.GetVariable("ScriptExitStatus") as ExitStatus; //=> set exit status... if (_scriptExitStatus != null && !_scriptExitStatus.IsRunning()) { if (Logger.IsTraceEnabled) { Logger.Trace("***> ScriptExitStatus returned by script => {0}", _scriptExitStatus); } contribution.ExitStatus = _scriptExitStatus; } else //=> let user decide on ExitStatus { if (Logger.IsTraceEnabled) { if (_scriptExitStatus == null) { Logger.Trace("***> ScriptExitStatus is null. Using PowerShellExitCodeMapper to determine ExitStatus."); } else if (_scriptExitStatus.IsRunning()) { Logger.Trace("***> ScriptExitStatus is EXECUTING or UNKNOWN. Using PowerShellExitCodeMapper to determine ExitStatus."); } } if (PowerShellExitCodeMapper != null) { //=> determine exit status using User Provided PowerShellExitCodeMapper contribution.ExitStatus = PowerShellExitCodeMapper.GetExitStatus(lastExitCode); } else //at this point we are not able to determine exit status, user needs to fix this... { //=> lets dump what we got before throwing an error... LogStreams(); throw new FatalStepExecutionException( "PowerShellTasklet is not able to determine ExitStatus. ScriptExitStatus is null or (is EXECUTING or UNKNOWN) and " + "PowerShellExitCodeMapper is NOT defined. Please set $global:ScriptExitStatus or define PowerShellExitCodeMapper.", null); } } } if (Logger.IsInfoEnabled) { Logger.Info("PowerShell execution exit status [{0}]", contribution.ExitStatus); } //=> output captured stream data to Log... LogStreams(); } catch (RuntimeException ex) { Logger.Error(ex.Message); throw; } } // end PowerShell Scope //=> close Runspace... runSpace.Close(); //=> we are done... return(RepeatStatus.Finished); } // end of Runspace Scope } // end of TransactionScope }
/// <summary> /// Do nothing execution, since all the logic is in after step /// </summary> /// <param name="contribution"></param> /// <param name="chunkContext"></param> /// <returns></returns> public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { return(RepeatStatus.Finished); }
public RepeatStatus Execute(StepContribution contribution, ChunkContext chunkContext) { _logger.Info("OK transition was used"); return(RepeatStatus.Finished); }