private static void ReturnMessageToQueue(InWorkMessage message, ConcurrentHashSet <InWorkMessage> inworkMessages, CancellationToken cancellationToken) { message.ReturnMessage(); if (inworkMessages != null) { inworkMessages.TryRemove(message); } cancellationToken.ThrowIfCancellationRequested(); }
private static void ReturnMessageToQueue(InWorkMessage message, ConcurrentHashSet<InWorkMessage> inworkMessages, CancellationToken cancellationToken) { message.ReturnMessage(); if (inworkMessages != null) inworkMessages.TryRemove(message); cancellationToken.ThrowIfCancellationRequested(); }
private static void ListenQueue(string queueName, IJobActivator jobActivator, Logger logger, ConcurrentHashSet <InWorkMessage> inworkMessages, CancellationToken cancellationToken) { if (!MessageQueue.Exists(queueName)) { throw new InvalidOperationException(string.Format("Очередь {0} отсутствует.", queueName)); } var mq = new MessageQueue(queueName); while (true) { try { using (var messageQueueTransaction = new MessageQueueTransaction()) { messageQueueTransaction.Begin(); var mes = mq.Receive(messageQueueTransaction); if (mes == null) { logger.Error("Получено пустое сообщение"); continue; } if (cancellationToken.IsCancellationRequested) { logger.Info("Операция отменена"); return; } mes.Formatter = new XmlMessageFormatter(new[] { typeof(MessageWrapper) }); var inWorkMessage = new InWorkMessage { Job = (MessageWrapper)mes.Body, QueueName = queueName, Label = mes.Label }; if (!inworkMessages.TryAdd(inWorkMessage)) { continue; } if (inWorkMessage.Job.RetryCount == 0) { logger.Info("Запущена задача {0}", inWorkMessage.Label); } else { logger.Info("Запущена задача {0}. Повторная попытка {1}", inWorkMessage.Label, inWorkMessage.Job.RetryCount); } var serializedjob = JobHelper.FromJson <SerializedJob>(inWorkMessage.Job.SerializedJob); var job = serializedjob.Deserialize(); //Отправляем задачу в работу и добавляем обработчик который в случае ошибки или отмены задачи вернет сообщение в очередь. //Если задача завершилась успешно, проставляем флаг об этом. Task.Factory.StartNew(() => job.Perform(jobActivator, cancellationToken), cancellationToken) .ContinueWith(t => { if (t.Exception != null) { t.Exception.Handle(ex => { if (ex.GetType() == typeof(JobFailedException)) { logger.Info("При выполнении задачи {0} возникла ошибка.", inWorkMessage.Label); logger.Error(ex.GetAllInnerExceptionMessagesAndTrace()); Thread.Sleep(60000); ReturnMessageToQueue(inWorkMessage, inworkMessages, cancellationToken); return(true); } logger.Fatal(ex.GetAllInnerExceptionMessagesAndTrace()); ReturnMessageToQueue(inWorkMessage, inworkMessages, cancellationToken); return(false); }); } else { logger.Info("Задача {0} завершилась успешно.", inWorkMessage.Label); inWorkMessage.CompleteMessage(); } }, TaskContinuationOptions.NotOnCanceled); messageQueueTransaction.Commit(); } } catch (Exception e) { logger.Fatal(e.GetAllInnerExceptionMessagesAndTrace()); //inworkMessages.CompleteAdding(); throw; } } }
private static void ListenQueue(string queueName, IJobActivator jobActivator, Logger logger, ConcurrentHashSet<InWorkMessage> inworkMessages, CancellationToken cancellationToken) { if (!MessageQueue.Exists(queueName)) { throw new InvalidOperationException(string.Format("Очередь {0} отсутствует.", queueName)); } var mq = new MessageQueue(queueName); while (true) { try { using (var messageQueueTransaction = new MessageQueueTransaction()) { messageQueueTransaction.Begin(); var mes = mq.Receive(messageQueueTransaction); if (mes == null) { logger.Error("Получено пустое сообщение"); continue; } if (cancellationToken.IsCancellationRequested) { logger.Info("Операция отменена"); return; } mes.Formatter = new XmlMessageFormatter(new[] {typeof(MessageWrapper)}); var inWorkMessage = new InWorkMessage { Job = (MessageWrapper)mes.Body, QueueName = queueName, Label = mes.Label}; if(!inworkMessages.TryAdd(inWorkMessage)) continue; if (inWorkMessage.Job.RetryCount==0) logger.Info("Запущена задача {0}", inWorkMessage.Label); else logger.Info("Запущена задача {0}. Повторная попытка {1}", inWorkMessage.Label, inWorkMessage.Job.RetryCount); var serializedjob = JobHelper.FromJson<SerializedJob>(inWorkMessage.Job.SerializedJob); var job = serializedjob.Deserialize(); //Отправляем задачу в работу и добавляем обработчик который в случае ошибки или отмены задачи вернет сообщение в очередь. //Если задача завершилась успешно, проставляем флаг об этом. Task.Factory.StartNew(() => job.Perform(jobActivator, cancellationToken), cancellationToken) .ContinueWith(t => { if (t.Exception != null) { t.Exception.Handle(ex => { if (ex.GetType() == typeof (JobFailedException)) { logger.Info("При выполнении задачи {0} возникла ошибка.", inWorkMessage.Label); logger.Error(ex.GetAllInnerExceptionMessagesAndTrace()); Thread.Sleep(60000); ReturnMessageToQueue(inWorkMessage, inworkMessages, cancellationToken); return true; } logger.Fatal(ex.GetAllInnerExceptionMessagesAndTrace()); ReturnMessageToQueue(inWorkMessage, inworkMessages, cancellationToken); return false; }); } else { logger.Info("Задача {0} завершилась успешно.", inWorkMessage.Label); inWorkMessage.CompleteMessage(); } }, TaskContinuationOptions.NotOnCanceled); messageQueueTransaction.Commit(); } } catch (Exception e) { logger.Fatal(e.GetAllInnerExceptionMessagesAndTrace()); //inworkMessages.CompleteAdding(); throw; } } }