ProcessContext
Represents a thread-safe context for a IRunnable process to publish events. This class cannot be inherited.
using Relativity.DataExchange.Resources;
using Relativity.Logging;
using System;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
namespace Relativity.DataExchange.Process
{
public sealed class ProcessContext
{
private readonly IProcessErrorWriter errorWriter;
private readonly IProcessEventWriter eventWriter;
private readonly ILog logger;
private readonly IAppSettings settings;
private int recordCount;
public object InputArgs { get; set; }
public bool SafeMode { get; set; }
public event EventHandler<CancellationRequestEventArgs> CancellationRequest;
public event EventHandler<ErrorReportEventArgs> ErrorReport;
public event EventHandler<ExportErrorEventArgs> ExportServerErrors;
public event EventHandler<ExportErrorEventArgs> ExportErrorReport;
public event EventHandler<ExportErrorEventArgs> ExportErrorFile;
public event EventHandler<FatalExceptionEventArgs> FatalException;
public event EventHandler<FieldMappedEventArgs> FieldMapped;
public event EventHandler<ParentFormClosingEventArgs> ParentFormClosing;
public event EventHandler<ProcessCompleteEventArgs> ProcessCompleted;
public event EventHandler<ProcessEndEventArgs> ProcessEnded;
public event EventHandler<ProcessEventArgs> ProcessEvent;
public event EventHandler<ProgressEventArgs> Progress;
public event EventHandler<RecordCountEventArgs> RecordCountIncremented;
public event EventHandler<RecordNumberEventArgs> RecordProcessed;
public event EventHandler<ShowReportEventArgs> ShowReportEvent;
public event EventHandler<EventArgs> Shutdown;
public event EventHandler<StatusBarEventArgs> StatusBarChanged;
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Both object perform no actual disposal.")]
public ProcessContext()
: this(new NullProcessEventWriter(), new NullProcessErrorWriter(), AppSettings.Instance, new NullLogger())
{
}
public ProcessContext(IProcessEventWriter eventWriter, IProcessErrorWriter errorWriter, IAppSettings settings, ILog logger)
{
if (eventWriter == null)
throw new ArgumentNullException("eventWriter");
if (errorWriter == null)
throw new ArgumentNullException("errorWriter");
if (settings == null)
throw new ArgumentNullException("settings");
if (logger == null)
throw new ArgumentNullException("logger");
this.eventWriter = eventWriter;
this.errorWriter = errorWriter;
this.settings = settings;
this.logger = logger;
SafeMode = false;
}
public void Clear()
{
recordCount = 0;
this.CancellationRequest = null;
this.ErrorReport = null;
this.ExportErrorFile = null;
this.ExportErrorReport = null;
this.ExportServerErrors = null;
this.FatalException = null;
this.FieldMapped = null;
this.ParentFormClosing = null;
this.ProcessCompleted = null;
this.ProcessEnded = null;
this.ProcessEvent = null;
this.Progress = null;
this.RecordCountIncremented = null;
this.ShowReportEvent = null;
this.Shutdown = null;
this.StatusBarChanged = null;
}
public void PublishCancellationRequest(Guid processId)
{
PublishCancellationRequest(processId, true);
}
public void PublishCancellationRequest(Guid processId, bool requestByUser)
{
CancellationRequestEventArgs e = new CancellationRequestEventArgs(processId, requestByUser);
this.CancellationRequest?.Invoke(this, e);
}
public void PublishErrorEvent(string recordInfo, string message)
{
ProcessEventArgs processEventArgs = new ProcessEventArgs(ProcessEventType.Error, recordInfo, message);
this.ProcessEvent?.Invoke(this, processEventArgs);
LogProcessEvent(processEventArgs);
WriteError(recordInfo, message);
}
public void PublishErrorReport(IDictionary error)
{
ErrorReportEventArgs e = new ErrorReportEventArgs(error);
this.ErrorReport?.Invoke(this, e);
}
public void PublishExportErrorFile(string file)
{
ExportErrorEventArgs e = new ExportErrorEventArgs(file);
this.ExportErrorFile?.Invoke(this, e);
}
public void PublishExportErrorReport(string file)
{
ExportErrorEventArgs e = new ExportErrorEventArgs(file);
this.ExportErrorReport?.Invoke(this, e);
}
public void PublishExportServerErrors(string file)
{
ExportErrorEventArgs e = new ExportErrorEventArgs(file);
this.ExportServerErrors?.Invoke(this, e);
}
public void PublishFieldMapped(string sourceField, string targetField)
{
FieldMappedEventArgs e = new FieldMappedEventArgs(sourceField, targetField);
this.FieldMapped?.Invoke(this, e);
}
public void PublishFatalException(Exception exception)
{
if (exception == null)
throw new ArgumentNullException("exception");
FatalExceptionEventArgs e = new FatalExceptionEventArgs(exception);
this.FatalException?.Invoke(this, e);
WriteError("FATAL ERROR", exception.ToString());
LogProcessEvent(new ProcessEventArgs(ProcessEventType.Error, string.Empty, exception.ToString()));
LogFatalException(exception);
}
public void PublishParentFormClosing(Guid processId)
{
ParentFormClosingEventArgs e = new ParentFormClosingEventArgs(processId);
this.ParentFormClosing?.Invoke(this, e);
}
public void PublishProcessCompleted()
{
PublishProcessCompleted(false, string.Empty, false);
}
public void PublishProcessCompleted(bool closeForm)
{
PublishProcessCompleted(closeForm, string.Empty, false);
}
public void PublishProcessCompleted(bool closeForm, string exportFilePath)
{
PublishProcessCompleted(closeForm, exportFilePath, false);
}
public void PublishProcessCompleted(bool closeForm, string exportFilePath, bool exportLog)
{
ProcessCompleteEventArgs e = new ProcessCompleteEventArgs(closeForm, exportFilePath, exportLog);
this.ProcessCompleted?.Invoke(this, e);
errorWriter.Close();
if (!closeForm && errorWriter.HasErrors) {
ProcessErrorReport processErrorReport = errorWriter.BuildErrorReport(CancellationToken.None);
if (processErrorReport == null)
throw new InvalidOperationException(Strings.BuildErrorReportArgError);
ShowReportEventArgs e2 = new ShowReportEventArgs(processErrorReport.Report, processErrorReport.MaxLengthExceeded);
this.ShowReportEvent?.Invoke(this, e2);
}
}
public void PublishProcessEnded(long nativeFileBytes, long metadataBytes, double sqlProcessRate)
{
ProcessEndEventArgs e = new ProcessEndEventArgs(nativeFileBytes, metadataBytes, sqlProcessRate);
this.ProcessEnded?.Invoke(this, e);
}
[SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed", Justification = "This was done for backwards compatibility reasons.")]
public void PublishProgress(long totalRecords, long totalProcessedRecords, long totalProcessedWarningRecords, long totalProcessedErrorRecords, DateTime startTime, DateTime timestamp, double metadataThroughput, double nativeFileThroughput, Guid processId, string totalRecordsDisplay = null, string totalProcessedRecordsDisplay = null, IDictionary metadata = null)
{
ProgressEventArgs e = new ProgressEventArgs(processId, metadata, startTime, timestamp, totalRecords, totalRecordsDisplay, totalProcessedRecords, totalProcessedRecordsDisplay, totalProcessedWarningRecords, totalProcessedErrorRecords, metadataThroughput, nativeFileThroughput, ProgressEventArgs.UnitOfMeasurement.Records);
this.Progress?.Invoke(this, e);
}
public void PublishProgressInBytes(long totalBytes, long processedBytes, DateTime startTime, DateTime timestamp, Guid processId, string totalBytesDisplay, string processedBytesDisplay)
{
ProgressEventArgs e = new ProgressEventArgs(processId, null, startTime, timestamp, totalBytes, totalBytesDisplay, processedBytes, processedBytesDisplay, 0, 0, 0, 0, ProgressEventArgs.UnitOfMeasurement.Bytes);
this.Progress?.Invoke(this, e);
}
public void PublishRecordCountIncremented()
{
recordCount++;
RecordCountEventArgs e = new RecordCountEventArgs(recordCount);
this.RecordCountIncremented?.Invoke(this, e);
}
public void PublishRecordProcessed(long recordNumber)
{
RecordNumberEventArgs e = new RecordNumberEventArgs(recordNumber);
this.RecordProcessed?.Invoke(this, e);
}
public void PublishShutdown()
{
this.Shutdown?.Invoke(this, EventArgs.Empty);
}
public void PublishStatusBarChanged(string message, string popupText)
{
StatusBarEventArgs e = new StatusBarEventArgs(message, popupText);
this.StatusBarChanged?.Invoke(this, e);
}
public void PublishStatusEvent(string recordInfo, string message)
{
ProcessEventArgs processEventArgs = new ProcessEventArgs(ProcessEventType.Status, recordInfo, message);
this.ProcessEvent?.Invoke(this, processEventArgs);
LogProcessEvent(processEventArgs);
}
public void SaveOutputFile(string file)
{
eventWriter.Save(file);
}
public void PublishWarningEvent(string recordInfo, string message)
{
ProcessEventArgs processEventArgs = new ProcessEventArgs(ProcessEventType.Warning, recordInfo, message);
this.ProcessEvent?.Invoke(this, processEventArgs);
LogProcessEvent(processEventArgs);
}
private void LogProcessEvent(ProcessEventArgs args)
{
if (settings.LogAllEvents && !SafeMode)
eventWriter.Write(new ProcessEventDto(args.EventType, args.RecordInfo, args.Message, args.Timestamp));
}
private void LogFatalException(Exception exception)
{
logger.LogFatal(exception, "A fatal exception has occurred.", Array.Empty<object>());
}
private void WriteError(string key, string description)
{
errorWriter.Write(key, description);
}
}
}