protected AbstractTestCaseResolver(IActivityLogger log, TestRunImportSettings settings, IEnumerable<TestRunImportResultInfo> resultInfos,
										   IEnumerable<TestCaseTestPlanDTO> testCaseTestPlans)
		{
			if (log == null)
			{
				throw new ArgumentNullException("log");
			}
			_log = log;
			if (settings == null)
			{
				_log.Error("Ctor member TestRunImportSettings settings is null");
				throw new ArgumentNullException("settings");
			}
			if (testCaseTestPlans == null)
			{
				_log.Error("Ctor member IEnumerable<TestCaseTestPlanDTO> testCaseTestPlans is null");
				throw new ArgumentNullException("testCaseTestPlans");
			}
			TestCaseTestPlans = testCaseTestPlans;
			if (resultInfos == null)
			{
				_log.Error("Ctor member IEnumerable<TestRunImportResultInfo> resultInfos is null");
				throw new ArgumentNullException("resultInfos");
			}
			ResultInfos = resultInfos;
		}
        private double?Calculate(Operation operation)
        {
            var    client = new CalculationEngineClient();
            double?result = null;

            try
            {
                result = client.ApplyCalculation(operation);
                client.Close();
            }
            catch (TimeoutException ex)
            {
                activityLogger.Error(ex);
                activityLogger.Info("Timeout Error! Calculation Engine is anavailable.");
                client.Abort();
            }
            catch (Exception ex)
            {
                activityLogger.Error(ex);
                activityLogger.Info("Unknown Error!");

                client.Abort();
            }

            return(result);
        }
예제 #3
0
 protected AbstractTestCaseResolver(IActivityLogger log, TestRunImportSettings settings, IEnumerable <TestRunImportResultInfo> resultInfos,
                                    IEnumerable <TestCaseTestPlanDTO> testCaseTestPlans)
 {
     if (log == null)
     {
         throw new ArgumentNullException("log");
     }
     _log = log;
     if (settings == null)
     {
         _log.Error("Ctor member TestRunImportSettings settings is null");
         throw new ArgumentNullException("settings");
     }
     if (testCaseTestPlans == null)
     {
         _log.Error("Ctor member IEnumerable<TestCaseTestPlanDTO> testCaseTestPlans is null");
         throw new ArgumentNullException("testCaseTestPlans");
     }
     TestCaseTestPlans = testCaseTestPlans;
     if (resultInfos == null)
     {
         _log.Error("Ctor member IEnumerable<TestRunImportResultInfo> resultInfos is null");
         throw new ArgumentNullException("resultInfos");
     }
     ResultInfos = resultInfos;
 }
예제 #4
0
        private IEnumerable <AssignRevisionToEntityAction> GetActions(string description)
        {
            if (string.IsNullOrEmpty(description))
            {
                return(Enumerable.Empty <AssignRevisionToEntityAction>());
            }

            try
            {
                var commandTree = _parser.Parse(description.Trim() + " ");

                if (commandTree.Errors.Count > 0)
                {
                    _log.Error(new CommentFailedToParseException(commandTree.Errors, description));
                }

                var actions = (List <AssignRevisionToEntityAction>)commandTree.Eval();

                return(actions.MergeActionsWithSameEntityId());
            }
            catch (Exception exception)
            {
                _log.Error(string.Format("Failed to parse comment {0}", description), exception);
                return(Enumerable.Empty <AssignRevisionToEntityAction>());
            }
        }
예제 #5
0
        public IndexResult UpdateGeneralIndex(GeneralDTO general, ICollection <GeneralField> changedFields)
        {
            if (general.GeneralID == null)
            {
                return(new IndexResult());
            }
            IEnumerable <IDocumentIndex> indexes = _documentIndexProvider.GetOrCreateDocumentIndexes(_pluginContext.AccountName, DocumentIndexTypeToken.Entity, DocumentIndexTypeToken.EntityProject, DocumentIndexTypeToken.EntityType);

            if (!indexes.Any(i => changedFields.Any(f => i.Type.IsBelongedToIndexFields(f) || i.Type.IsBelongedToDocumentFields(f))))
            {
                return(new IndexResult());
            }
            IDocumentIndex entityIndex = _documentIndexProvider.GetOrCreateDocumentIndex(_pluginContext.AccountName, DocumentIndexTypeToken.Entity);
            var            document    = entityIndex.FindDocumentByName <EntityDocument>(EntityDocument.CreateName(general.GeneralID));

            if (document == null)
            {
                _log.Error(string.Format("CANNOT PROCESS UPDATE '{0}UpdatedMessage' FOR ENTITY #{1} - '{2}'. ENTITY WAS NOT ADDED DURING PROFILE INITIALIZATION OR ENTITY CREATION !!!", general.EntityTypeName, general.GeneralID.GetValueOrDefault(), general.Name));
                return(new IndexResult());
            }
            if (changedFields.Any(f => entityIndex.Type.IsBelongedToDocumentFields(f)))
            {
                document.ProjectId    = _documentIdFactory.CreateProjectId(general.ParentProjectID.GetValueOrDefault());
                document.EntityTypeId = _documentIdFactory.CreateEntityTypeId(general.EntityTypeID.GetValueOrDefault());
                entityIndex.SaveDocument(document, false);
                _log.Debug(string.Format("Updated {0} #{1} - '{2}':{3}{4}", general.EntityTypeName, general.GeneralID.GetValueOrDefault(), general.Name, changedFields.Contains(GeneralField.ParentProjectID) ? string.Format(" Project - {0};", string.Join(",", general.ParentProjectName)) : string.Empty, changedFields.Contains(GeneralField.EntityTypeID) ? string.Format(" EntityType - {0};", string.Join(",", general.EntityTypeName)) : string.Empty));
            }
            if (changedFields.Any(f => entityIndex.Type.IsBelongedToIndexFields(f)))
            {
                var text        = _textOperations.Prepare(string.Format("{0} {1} ", general.Name, general.Description ?? string.Empty));
                var indexResult = entityIndex.Update(document.FileName, text);
                _log.Debug(string.Format("Updated {0} #{1} - '{2}':{3}{4}", general.EntityTypeName,
                                         general.GeneralID.GetValueOrDefault(), general.Name,
                                         indexResult.WordsAdded.Any() ? string.Format(" added words - {0};", string.Join(",", indexResult.WordsAdded.Keys)) : " NO WORDS ADDED;",
                                         indexResult.WordsRemoved.Any() ? string.Format(" removed words - {0};", string.Join(",", indexResult.WordsRemoved)) : " NO WORDS REMOVED;"));
            }
            IDocumentIndex entityProjectIndex = _documentIndexProvider.GetOrCreateDocumentIndex(_pluginContext.AccountName, DocumentIndexTypeToken.EntityProject);

            if (changedFields.Any(f => entityProjectIndex.Type.IsBelongedToIndexFields(f)) && document.DocNumber >= 0)
            {
                entityProjectIndex.Update(document.DocNumber, general.ParentProjectID.HasValue ? _documentIdFactory.EncodeProjectId(general.ParentProjectID.Value) : string.Empty);
                _localBus.SendLocal(new GeneralProjectChangedLocalMessage
                {
                    GeneralId = general.GeneralID.Value,
                    ProjectId = general.ParentProjectID
                });
            }
            IDocumentIndex entityTypeIndex = _documentIndexProvider.GetOrCreateDocumentIndex(_pluginContext.AccountName, DocumentIndexTypeToken.EntityType);

            if (changedFields.Any(f => entityTypeIndex.Type.IsBelongedToIndexFields(f)) && document.DocNumber >= 0)
            {
                entityTypeIndex.Index(document.DocNumber, general.EntityTypeName);
            }
            return(new IndexResult {
                DocNumber = document.DocNumber
            });
        }
예제 #6
0
 void DoShutdown(bool disposing, bool waitForTermination)
 {
     if (!_disposed)
     {
         if (disposing)
         {
             GC.SuppressFinalize(this);
         }
         _disposed = true;
         try
         {
             _native.DeactivateAllHooks();
             if (_bridge != null)
             {
                 _bridge.StandardInput.WriteLine();
                 if (waitForTermination)
                 {
                     _bridge.WaitForExit();
                 }
             }
         }
         catch (Exception ex)
         {
             if (disposing)
             {
                 _logger.Error(ex, "While shutting down NativeHookManager.");
             }
         }
     }
 }
        public PluginCommandResponseMessage Execute(string args)
        {
            var fileArgs = args.Deserialize <FileViewDiffArgs>();

            try
            {
                var revision = _repository.GetRevisionId(fileArgs.TpRevisionId);
                var diff     = new DiffResult();

                if (revision != null)
                {
                    var vcs = _vcsFactory.Get(revision.Profile);
                    diff = vcs.GetDiff(revision.RevisionId.RevisionId, fileArgs.Path);
                }

                return(new PluginCommandResponseMessage
                {
                    PluginCommandStatus = PluginCommandStatus.Succeed,
                    ResponseData = diff.Serialize()
                });
            }
            catch (Exception e)
            {
                _logger.Error("ViewDiff error", e);
                return(new PluginCommandResponseMessage
                {
                    PluginCommandStatus = PluginCommandStatus.Error,
                    ResponseData = "Unable to connect to a remote repository: {0}.".Fmt(e.Message)
                });
            }
        }
예제 #8
0
        public void Handle(BugUpdatedMessage message)
        {
            //TODO: take into account: when set the second developer in TP this developer assigned in Bugzilla

            if (!message.ChangedFields.Contains(BugField.EntityStateID))
            {
                return;
            }

            var bugzillaBug = _bugzillaInfoStorageRepository.GetBugzillaBug(message.Dto.ID);

            if (bugzillaBug == null)
            {
                return;
            }

            var status = _entityStateConverter.GetMappedBugzillaStatus(message.Dto);

            if (status == null)
            {
                return;
            }

            try
            {
                _log.InfoFormat("Updating bug status in Bugzilla. TargetProcess Bug ID: {0}; Bugzilla Bug ID: {1}", message.Dto.ID, bugzillaBug.Id);
                _bugzillaService.Execute(_actionFactory.GetChangeStatusAction(message.Dto, bugzillaBug.Id, status));
                _log.InfoFormat("Bug status in Bugzilla updated. TargetProcess Bug ID: {0}; Bugzilla Bug ID: {1}", message.Dto.ID, bugzillaBug.Id);
            }
            catch (Exception e)
            {
                _log.Error(e.Message, e);
            }
        }
        public AbstractTestRunImportResultsReader GetResolver(TestRunImportSettings settings, TextReader reader)
        {
            if (settings == null)
            {
                _log.Error("GetResolver member settings is null");
                throw new ArgumentNullException("settings");
            }

            switch (settings.FrameworkType)
            {
            case FrameworkTypes.FrameworkTypes.NUnit:
                return(new NUnitResultsXmlReader(_log, reader));

            case FrameworkTypes.FrameworkTypes.JUnit:
                return(new JUnitResultsXmlReader(_log, reader));

            case FrameworkTypes.FrameworkTypes.Selenium:
                return(new SeleniumResultsHtmlReader(_log, reader));

            case FrameworkTypes.FrameworkTypes.JenkinsHudson:
                return(new JenkinsHudsonResultsXmlReader(_log, reader));

            default:
                throw new ApplicationException(string.Format("Failed to get resolver for FrameworkType: {0}", settings.FrameworkType));
            }
        }
 public StreamFactoryResult OpenStreamIfModified(Uri uri, LastModifyResult lastModifyResult, bool passiveMode)
 {
     if (uri == null)
     {
         _log.Error("OpenStreamIfModified method uri member is null");
         throw new ArgumentNullException("uri");
     }
     try
     {
         return(OpenStreamIfModified(WebRequest.Create(uri), lastModifyResult, passiveMode));
     }
     catch (UriFormatException ex)
     {
         _log.ErrorFormat("Specified path has invalid format: {0}", ex.Message);
         throw new ApplicationException(string.Format("Specified path has invalid format: {0}", ex.Message), ex);
     }
     catch (NotSupportedException ex)
     {
         _log.ErrorFormat(string.Format("Specified path has invalid format: {0}", ex.Message), ex);
         throw new ApplicationException(
                   string.Format("The request scheme specified in requestUri is not registered: {0}", ex.Message), ex);
     }
     catch (SecurityException ex)
     {
         _log.ErrorFormat("The caller does not have permission to connect to the requested URI or a URI that the request is redirected to: {0}", ex.Message);
         throw new ApplicationException(
                   string.Format(
                       "The caller does not have permission to connect to the requested URI or a URI that the request is redirected to: {0}",
                       ex.Message), ex);
     }
 }
예제 #11
0
 public void Handle(TargetProcessExceptionThrownMessage message)
 {
     _logger.Error("Build indexes failed", new Exception(message.ExceptionString));
     SendLocal(new IndexExistingEntitiesDoneLocalMessage {
         SagaId = Data.OuterSagaId
     });
     MarkAsComplete();
 }
예제 #12
0
        public void Handle(TargetProcessExceptionThrownMessage message)
        {
            _revisionStorage.RemoveRevisionInfo(Data.RevisionKey);

            _logger.Error(string.Format("Failed to create revision. Revision ID: {0}", Data.SourceControlID), message.GetException());

            MarkAsComplete();
        }
예제 #13
0
        public void Handle(TargetProcessExceptionThrownMessage message)
        {
            _logger.Error("Error occured", new Exception(message.ExceptionString));

            if (Data.CreatingBug)
            {
                AttachmentFolder.Delete(Data.ThirdPartyBug.attachmentCollection.Select(x => x.FileId));
            }
            MarkAsComplete();
        }
        protected void HandleErrorInternal(TargetProcessExceptionThrownMessage message)
        {
            if (!string.IsNullOrEmpty(message.ExceptionString) && message.ExceptionString.StartsWith("EntityNotFoundException"))
            {
                Logger.Warn(string.Format("Entity {0} {1} not found in Target Porcess", Data.WorkItem.TpEntityId.Id, Data.WorkItem.TpEntityId.Type));
            }
            else
            {
                Logger.Error("Error occured", new Exception(message.ExceptionString));
            }

            MarkAsComplete();
        }
		protected AbstractTestRunImportResultsReader(IActivityLogger log, TextReader reader)
		{
			if (log == null)
			{
				throw new ArgumentNullException("log");
			}
			_log = log;
			if (reader == null)
			{
				_log.Error("Ctor member reader is null");
				throw new ArgumentNullException("reader");
			}
			Reader = reader;
		}
        public void Handle(EmailUidsRetrievedMessage message)
        {
            try
            {
                _log.InfoFormat("Downloading {0} messages from email server...", message.Uids.Count());
                _client.Connect();
                _client.Login();

                var count = 0;
                while (ReadNextEmailMessage(message.Uids))
                {
                    count++;
                }
                _log.InfoFormat("Downloaded messages={0}", count);
            }
            catch (Exception ex)
            {
                _client.Disconnect();
                _log.Error(String.Format("Error downloading messages."), ex);
                var skippedUids = message.Uids.Where(x => !_processedUids.Contains(x));
                _messageUidRepository.Remove(skippedUids.ToArray());
            }
        }
예제 #17
0
 protected AbstractTestRunImportResultsReader(IActivityLogger log, TextReader reader)
 {
     if (log == null)
     {
         throw new ArgumentNullException("log");
     }
     _log = log;
     if (reader == null)
     {
         _log.Error("Ctor member reader is null");
         throw new ArgumentNullException("reader");
     }
     Reader = reader;
 }
예제 #18
0
        private bool TryGetChangedIds(DateTime?dateValue, out int[] ids)
        {
            try
            {
                ids = _bugzillaService.GetChangedBugIds(dateValue).Distinct().ToArray();
                return(true);
            }
            catch (Exception e)
            {
                _logger.Error(string.Format("Retrieving changed bugs failed: {0}", e.Message), e);
                ids = new int[] {};

                return(false);
            }
        }
예제 #19
0
        public double?ApplyCalculation(Operation operation)
        {
            activityLogger.Info("start calculation by calculation engine...");
            if (!IsServerAvailable())
            {
                activityLogger.Error(new Exception("Error! Calculation engine service unavaliable"));
                throw new TimeoutException();
            }
            var calculationContext = new Context();

            switch (operation.OperationType)
            {
            case OperationType.Addition:
                activityLogger.Info("applying Addition...");
                calculationContext.SetCalculationStrategy(new AdditionStrategy());
                break;

            case OperationType.Division:
                activityLogger.Info("applying Division...");
                calculationContext.SetCalculationStrategy(new DivisionStrategy());

                break;

            case OperationType.Multiplication:
                activityLogger.Info("applying Multiplication...");
                calculationContext.SetCalculationStrategy(new MultiplicationStrategy());

                break;

            case OperationType.Subtraction:
                activityLogger.Info("applying Subtraction...");
                calculationContext.SetCalculationStrategy(new SubtractionStrategy());

                break;

            default:
                throw new ArgumentException("Invalid operation");
            }
            return(calculationContext.Execute(operation.FirstNumber.Value, operation.SecondNumber.Value));
        }
 public PluginCommandResponseMessage Execute(string args)
 {
     if (_profile.IsNull)
     {
         return(new PluginCommandResponseMessage
         {
             ResponseData = "Indexing was not started yet.",
             PluginCommandStatus = PluginCommandStatus.Fail
         });
     }
     try
     {
         if (_documentIndexRebuilder.RebuildIfNeeded())
         {
             return(new PluginCommandResponseMessage
             {
                 ResponseData = "Index rebuild is in progress.",
                 PluginCommandStatus = PluginCommandStatus.Fail
             });
         }
         var             searchData      = args.Deserialize <QueryData>();
         QueryResult     queryResult     = _queryRunner.Run(searchData);
         QueryResultData queryResultData = CreateQueryResultData(queryResult);
         return(new PluginCommandResponseMessage
         {
             ResponseData = queryResultData.Serialize(),
             PluginCommandStatus = PluginCommandStatus.Succeed
         });
     }
     catch (DocumentIndexConcurrentAccessException e)
     {
         _logger.Error(e);
         return(new PluginCommandResponseMessage
         {
             ResponseData = "Search failed because of concurrent access exception. Try again, please",
             PluginCommandStatus = PluginCommandStatus.Error
         });
     }
 }
        private void AssignUser(TeamDTO team, string userEmail, Action sucess)
        {
            if (!NeedToProcess(team) || AnotherRole(team))
            {
                return;
            }

            var bugzillaBug = _bugzillaInfoStorageRepository.GetBugzillaBug(team.AssignableID);

            _logger.InfoFormat("Changing bug assignment in Bugzilla. TargetProcess Bug ID: {0}; Email: {1}", bugzillaBug.TpId, userEmail);

            try
            {
                _service.Execute(_actionFactory.GetAssigneeAction(bugzillaBug.Id, userEmail));
                sucess();
            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message, ex);
            }

            _logger.InfoFormat("Bug assignment changed in Bugzilla. TargetProcess Bug ID: {0}; Email: {1}", bugzillaBug.TpId, userEmail);
        }
예제 #22
0
        public void Handle(CommentCreatedMessage message)
        {
            if (!NeedToProcess(message.Dto))
            {
                return;
            }

            _logger.InfoFormat("Importing comment to Bugzilla. TargetProcess Bug ID: {0}", message.Dto.GeneralID);

            try
            {
                var offset = _bugzillaService.GetTimeOffset();

                _bugzillaService.Execute(_actionFactory.GetCommentAction(message.Dto, offset));
                _storage.Get <CommentDTO>(message.Dto.GeneralID.ToString()).Add(message.Dto);
            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message, ex);
            }

            _logger.InfoFormat("Comment imported to Bugzilla. TargetProcess Bug ID: {0}", message.Dto.GeneralID);
        }
예제 #23
0
 public static NativeHookManager Create(IActivityLogger logger, bool withBridge = true)
 {
     if (logger == null)
     {
         throw new ArgumentNullException("logger");
     }
     using (logger.OpenGroup(LogLevel.Info, "Initializing a new NativeHookManager."))
     {
         Process bridge = null;
         try
         {
             // This method is thread-safe and the type is cached.
             // It is useless to add yet another lock layer.
             _native = CK.Interop.PInvoker.GetInvoker <INativeGlobalHookInterop>();
             if (withBridge)
             {
                 ProcessStartInfo s = new ProcessStartInfo();
                 s.FileName = "CK.LLHook.NativeBridge." + (OSVersionInfo.ProgramBits == OSVersionInfo.SoftwareArchitecture.Bit32 ? "64" : "32");
                 #if DEBUG
                 s.FileName += ".dbg.exe";
                 #else
                 s.FileName += ".exe";
                 #endif
                 s.UseShellExecute       = false;
                 s.CreateNoWindow        = true;
                 s.RedirectStandardInput = true;
                 bridge = Process.Start(s);
             }
         }
         catch (Exception ex)
         {
             logger.Error(ex);
             return(null);
         }
         return(new NativeHookManager(logger, bridge));
     }
 }
		public void Handle(TickMessage message)
		{
			var profile = _storageRepository.GetProfile<TestRunImportPluginProfile>();
			if (profile.FrameworkType == FrameworkTypes.FrameworkTypes.Selenium && profile.PostResultsToRemoteUrl)
			{
				return;
			}

			try
			{
				_log.InfoFormat("Started synchronizing at {0}", DateTime.Now);

				var lastModifyResults = _storageRepository.Get<LastModifyResult>();
				var lastModifyResult = lastModifyResults.Empty() ? new LastModifyResult() : lastModifyResults.Single();

				var jenkinsHudsonLastCompletedBuildNumber = profile.FrameworkType == FrameworkTypes.FrameworkTypes.JenkinsHudson ?
					GetJenkinsHudsonLastCompletedBuildNumber(profile) : null;

				if (profile.FrameworkType == FrameworkTypes.FrameworkTypes.JenkinsHudson &&
						(jenkinsHudsonLastCompletedBuildNumber == null || string.CompareOrdinal(lastModifyResult.ETagHeader, jenkinsHudsonLastCompletedBuildNumber) == 0))
				{
					_log.Info("No new modification of results source detected");
					return;
				}

				var uri = profile.FrameworkType == FrameworkTypes.FrameworkTypes.JenkinsHudson
										? new Uri(string.Format("{0}/lastCompletedBuild/testReport/api/xml", profile.ResultsFilePath.TrimEnd(new[] { '/', '\\' })))
										: new Uri(profile.ResultsFilePath);
				var factoryResult = _streamFactory.OpenStreamIfModified(uri, lastModifyResult, profile.PassiveMode);

				_log.InfoFormat("{0} modification of results source detected", factoryResult == null ? "No new" : "New");

				if (factoryResult != null)
				{
					if (profile.FrameworkType == FrameworkTypes.FrameworkTypes.JenkinsHudson)
					{
						factoryResult.LastModifyResult.ETagHeader = jenkinsHudsonLastCompletedBuildNumber;
					}

					lastModifyResults.Clear();
					lastModifyResults.Add(factoryResult.LastModifyResult);

					using (factoryResult.Stream)
					{
						using (var reader = new StreamReader(factoryResult.Stream))
						{
							try
							{
								var result = _resultsReaderFactory.GetResolver(profile, reader).GetTestRunImportResults();
								_log.InfoFormat("{0} items for import detected in resutls source", result.Count == 0 ? "No" : result.Count.ToString(CultureInfo.InvariantCulture));
								if (result.Count > 0)
								{
									_localBus.SendLocal(new TestRunImportResultDetectedLocalMessage
																				{
																					TestRunImportInfo =
																						new TestRunImportInfo { TestRunImportResults = result.ToArray() }
																				});
								}
							}
							catch (ApplicationException)
							{
								throw;
							}
							catch (XmlException ex)
							{
								throw new ApplicationException("Error parsing results XML file", ex);
							}
							catch (Exception ex)
							{
								throw new ApplicationException("Error importing results XML file", ex);
							}
						}
					}
				}
			}
			catch (UriFormatException ex)
			{
				_log.Error(ex.Message);
				throw new ApplicationException(string.Format("Specified path has invalid format. {0}", ex.Message), ex);
			}
			catch (ApplicationException ex)
			{
				_log.Error(ex.Message);
				throw;
			}
			catch (Exception ex)
			{
				_log.ErrorFormat("Could not read file \"{0}\": {1}", profile.ResultsFilePath, ex.Message);
				throw new ApplicationException(
					string.Format("Could not read file \"{0}\": {1}", profile.ResultsFilePath, ex.Message), ex);
			}
		}
예제 #25
0
 public void Handle(TargetProcessExceptionThrownMessage message)
 {
     _logger.Error("Comment import failed", new Exception(message.ExceptionString));
     MarkAsComplete();
 }
 public void Handle(TargetProcessExceptionThrownMessage message)
 {
     _logger.Error("Rebuild indexes for comment failed", new Exception(message.ExceptionString));
     MarkAsComplete();
 }
예제 #27
0
        public void Handle(TargetProcessExceptionThrownMessage message)
        {
            _logger.Error(string.Format("Failed to attach revision to entity. Revision ID: {0}; Entity ID: {1}", Data.RevisionDto.SourceControlID, Data.EntityId), message.GetException());

            MarkAsComplete();
        }