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)); } }
public void Dispatch(byte[] message) { ImmutableEnvelope envelope = null; try { envelope = _streamer.ReadAsEnvelopeData(message); } catch (Exception ex) { // permanent quarantine for serialization problems _quarantine.Quarantine(message, ex); SystemObserver.Notify(new EnvelopeDeserializationFailed(ex, "dispatch")); return; } if (_manager.DoWeRemember(envelope.EnvelopeId)) { SystemObserver.Notify(new EnvelopeDuplicateDiscarded(envelope.EnvelopeId)); return; } try { _action(envelope); // non-essential but recommended CleanupDispatchedEnvelope(envelope); } catch (ThreadAbortException) { return; } catch (Exception ex) { if (_quarantine.TryToQuarantine(envelope, ex)) { SystemObserver.Notify(new EnvelopeQuarantined(ex, _dispatcherName, envelope)); // message quarantined. Swallow return; } // if we are on a persistent queue, this will tell to retry throw; } }