Example #1
0
        private void OnRetry(Exception err, int retry, BatchJobContext context)
        {
            m_JournalWriter.WriteLine($"Failed to run macro: {err.ParseUserError()}. Retrying (retry #{retry})...");

            ProcessError(err, context);

            m_Logger.Log(err);
        }
Example #2
0
        private void ProcessError(Exception err, BatchJobContext context)
        {
            if (err is ICriticalException)
            {
                m_JournalWriter.WriteLine("Critical error - restarting application");

                TryShutDownApplication(context.CurrentApplicationProcess);
            }
        }
Example #3
0
        private bool TryProcessFile(BatchJobContext context,
                                    IResilientWorker <BatchJobContext> worker,
                                    CancellationToken cancellationToken)
        {
            var fileProcessStartTime = DateTime.Now;

            m_JournalWriter.WriteLine($"Started processing file {context.CurrentJobItem.FilePath}");

            context.ForbidSaving          = null;
            context.CurrentJobItem.Status = JobItemStatus_e.InProgress;

            foreach (var macro in context.CurrentJobItem.Macros)
            {
                context.CurrentMacro = macro;

                try
                {
                    worker.DoWork(RunMacro, context, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    ProcessError(ex, context);

                    if (context.CurrentDocument == null)
                    {
                        context.CurrentJobItem.ReportError(ex);
                    }
                    else
                    {
                        context.CurrentMacro.ReportError(ex);
                    }

                    m_JournalWriter.WriteLine(ex.ParseUserError(out _));
                    m_Logger.Log(ex);
                }
            }

            if (context.CurrentJobItem.Macros.All(m => m.Status == JobItemStatus_e.Succeeded))
            {
                context.CurrentJobItem.Status = JobItemStatus_e.Succeeded;
            }
            else
            {
                context.CurrentJobItem.Status = context.CurrentJobItem.Macros.Any(m => m.Status == JobItemStatus_e.Succeeded) ? JobItemStatus_e.Warning : JobItemStatus_e.Failed;
            }

            m_JournalWriter.WriteLine($"Processing file '{context.CurrentJobItem.FilePath}' completed. Execution time {DateTime.Now.Subtract(fileProcessStartTime).ToString(@"hh\:mm\:ss")}");

            return(context.CurrentJobItem.Status != JobItemStatus_e.Failed);
        }
Example #4
0
        private IXApplication EnsureApplication(BatchJobContext context, CancellationToken cancellationToken)
        {
            if (context.CurrentApplication == null || !context.CurrentApplication.IsAlive)
            {
                TryShutDownApplication(context.CurrentApplicationProcess);

                var vers = m_AppProvider.ParseVersion(context.Job.VersionId);

                context.CurrentApplication = StartApplication(vers, context.Job.StartupOptions,
                                                              cancellationToken);

                context.CurrentApplicationProcess = context.CurrentApplication.Process;
            }

            return(context.CurrentApplication);
        }
Example #5
0
        private void RunMacro(BatchJobContext context, CancellationToken cancellationToken)
        {
            EnsureApplication(context, cancellationToken);

            if (context.CurrentDocument == null || !context.CurrentDocument.IsAlive)
            {
                TryCloseDocument(context.CurrentDocument);

                context.CurrentDocument = EnsureDocument(context.CurrentApplication,
                                                         context.CurrentJobItem.Document, context.Job.OpenFileOptions, cancellationToken, out bool forbidSaving);

                context.ForbidSaving = forbidSaving;
            }

            if (!context.Job.OpenFileOptions.HasFlag(OpenFileOptions_e.Invisible))
            {
                context.CurrentApplication.Documents.Active = context.CurrentDocument;
            }

            m_JournalWriter.WriteLine($"Running '{context.CurrentMacro.FilePath}' macro");

            try
            {
                context.CurrentMacro.Status = JobItemStatus_e.InProgress;

                IXDocument macroDoc = null;

                if (!string.IsNullOrEmpty(context.CurrentMacro.Macro.Arguments) ||
                    context.Job.OpenFileOptions.HasFlag(OpenFileOptions_e.Invisible))
                {
                    macroDoc = context.CurrentDocument;
                }

                m_MacroRunnerSvc.RunMacro(context.CurrentApplication, context.CurrentMacro.FilePath, null,
                                          XCad.Enums.MacroRunOptions_e.UnloadAfterRun,
                                          context.CurrentMacro.Macro.Arguments, macroDoc);

                if (context.CurrentMacro.InternalMacroException != null)
                {
                    var ex = context.CurrentMacro.InternalMacroException;
                    context.CurrentMacro.InternalMacroException = null;
                    throw ex;
                }

                if (context.Job.Actions.HasFlag(Actions_e.AutoSaveDocuments))
                {
                    if (!context.ForbidSaving.Value)
                    {
                        m_JournalWriter.WriteLine("Saving the document");

                        if (context.CurrentDocument.IsAlive)
                        {
                            context.CurrentDocument.Save();
                        }
                        else
                        {
                            throw new UserException("Failed to automatically save the document as it has been closed or disconnected");
                        }
                    }
                    else
                    {
                        throw new SaveForbiddenException();
                    }
                }

                context.CurrentMacro.Status = JobItemStatus_e.Succeeded;
            }
            catch (Exception ex)
            {
                context.CurrentMacro.Status = JobItemStatus_e.Failed;

                if (ex is ICriticalException)
                {
                    throw new CriticalErrorException(ex);
                }
                else if (ex is MacroRunFailedException)
                {
                    throw new UserException($"Failed to run macro '{context.CurrentMacro.DisplayName}': {ex.Message}", ex);
                }
                else if (ex is INoRetryMacroRunException)
                {
                    context.CurrentMacro.ReportError(ex);
                }
                else
                {
                    throw;
                }
            }
        }
Example #6
0
 private void OnTimeout(BatchJobContext context)
 {
     m_JournalWriter.WriteLine("Operation timed out");
     TryShutDownApplication(context.CurrentApplicationProcess);
 }
Example #7
0
        public async Task <bool> BatchRunAsync(CancellationToken cancellationToken = default)
        {
            m_JournalWriter.WriteLine($"Batch macro running started");

            var batchStartTime = DateTime.Now;

            TimeSpan?timeout = null;

            if (m_Job.Timeout > 0)
            {
                timeout = TimeSpan.FromSeconds(m_Job.Timeout);
            }

            var worker = m_WorkerFact.Invoke(timeout);

            worker.Retry   += OnRetry;
            worker.Timeout += OnTimeout;

            m_CurrentContext = new BatchJobContext()
            {
                Job = m_Job
            };

            var jobResult = false;

            try
            {
                await TaskEx.Run(() =>
                {
                    m_JournalWriter.WriteLine($"Collecting files for processing");

                    var app = EnsureApplication(m_CurrentContext, cancellationToken);

                    var allFiles = PrepareJobScope(app, m_Job.Input, m_Job.Filters, m_Job.Macros);

                    m_JournalWriter.WriteLine($"Running batch processing for {allFiles.Length} file(s)");

                    m_ProgressHandler.SetJobScope(allFiles, batchStartTime);

                    if (!allFiles.Any())
                    {
                        throw new UserException("Empty job. No files matching specified filter");
                    }

                    var curBatchSize = 0;

                    for (int i = 0; i < allFiles.Length; i++)
                    {
                        var curAppPrc = m_CurrentContext.CurrentApplicationProcess?.Id;

                        m_CurrentContext.CurrentJobItem = allFiles[i];
                        var res = TryProcessFile(m_CurrentContext, worker, cancellationToken);

                        TryCloseDocument(m_CurrentContext.CurrentDocument);

                        m_CurrentContext.CurrentDocument = null;

                        m_ProgressHandler?.ReportProgress(m_CurrentContext.CurrentJobItem, res);

                        if (!res && !m_Job.ContinueOnError)
                        {
                            throw new UserException("Cancelling the job. Set 'Continue On Error' option to continue job if file failed");
                        }

                        if (m_CurrentContext.CurrentApplicationProcess?.Id != curAppPrc)
                        {
                            curBatchSize = 1;
                        }
                        else
                        {
                            curBatchSize++;
                        }

                        if (m_Job.BatchSize > 0 && curBatchSize >= m_Job.BatchSize)
                        {
                            m_JournalWriter.WriteLine("Closing application as batch size reached the limit");
                            TryShutDownApplication(m_CurrentContext.CurrentApplicationProcess);
                            curBatchSize = 0;
                        }
                    }
                }, new StaTaskScheduler(m_Logger)).ConfigureAwait(false);

                jobResult = true;
            }
            catch (OperationCanceledException)
            {
                throw new JobCancelledException();
            }
            finally
            {
                TryShutDownApplication(m_CurrentContext.CurrentApplicationProcess);
            }

            var duration = DateTime.Now.Subtract(batchStartTime);

            m_ProgressHandler.ReportCompleted(duration);

            m_JournalWriter.WriteLine($"Batch running completed in {duration.ToString(@"hh\:mm\:ss")}");

            return(jobResult);
        }