void CleanupDispatchedEnvelope(ImmutableEnvelope envelope) { try { _manager.Memorize(envelope.EnvelopeId); } catch (ThreadAbortException) { // continue; throw; } catch (Exception ex) { SystemObserver.Notify(new EnvelopeCleanupFailed(ex, _dispatcherName, envelope)); } try { _quarantine.TryRelease(envelope); } catch (ThreadAbortException) { // continue throw; } catch (Exception ex) { SystemObserver.Notify(new EnvelopeCleanupFailed(ex, _dispatcherName, envelope)); } SystemObserver.Notify(new EnvelopeDispatched(envelope, _dispatcherName)); }
void ProcessMessage(EnvelopeTransportContext context) { var processed = false; try { if (_memory.DoWeRemember(context.Unpacked.EnvelopeId)) { _observer.Notify(new EnvelopeDuplicateDiscarded(context.QueueName, context.Unpacked.EnvelopeId)); } else { _dispatcher.DispatchMessage(context.Unpacked); _memory.Memorize(context.Unpacked.EnvelopeId); } processed = true; } catch (Exception dispatchEx) { // if the code below fails, it will just cause everything to be reprocessed later, // which is OK (duplication manager will handle this) _observer.Notify(new EnvelopeDispatchFailed(context.Unpacked, context.QueueName, dispatchEx)); // quarantine is atomic with the processing if (_quarantine.TryToQuarantine(context, dispatchEx)) { _observer.Notify(new EnvelopeQuarantined(dispatchEx, context.Unpacked, context.QueueName)); // acking message is the last step! _inbox.AckMessage(context); } else { _inbox.TryNotifyNack(context); } } try { if (processed) { // 1st step - dequarantine, if present _quarantine.TryRelease(context); // 2nd step - ack. _inbox.AckMessage(context); // 3rd - notify. _observer.Notify(new EnvelopeAcked(context.QueueName, context.Unpacked.EnvelopeId, context.Unpacked.GetAllAttributes())); } } catch (Exception ex) { // not a big deal. Message will be processed again. _observer.Notify(new EnvelopeAckFailed(ex, context.Unpacked.EnvelopeId, context.QueueName)); } }