/SimpleServiceBus/Bus/Pipeline/MessagePipeline.cs
# · C# · 229 lines · 175 code · 54 blank · 0 comment · 26 complexity · 9b1d966b9704b2b03bb4516f38af2618 MD5 · raw file
- using System;
- using System.Collections.Generic;
- using SimpleServiceBus.Bus.MessageManagement;
- using SimpleServiceBus.Endpoint;
-
- namespace SimpleServiceBus.Bus.Pipeline
- {
- public enum PipelineStatus
- {
- Uninitialized = 0,
- Initializing,
- Initialized,
- Processing,
- Complete
- }
-
- public class MessagePipeline : IMessagePipeline
- {
- private PipelineStatus _status;
- protected PipelineEvents _events;
-
- protected MessagePipeline(PipelineEvents events):this()
- {
- if (events != null)
- _events = events;
- }
-
- public MessagePipeline()
- {
- _events = new PipelineEvents();
- PipelineComponents = new List<IMessagePipelineComponent>();
- }
-
- public IMessagingEndpoint Endpoint { get; private set; }
- public PipelineDirection PipelineDirection { get; private set; }
- public IPipelineEvents PipelineEvents
- {
- get { return _events; }
- }
-
- public IList<IMessagePipelineComponent> PipelineComponents { get; protected set; }
-
-
- public PipelineStatus Status
- {
- get { return _status; }
- private set
- {
- if (_status != value)
- {
- PipelineStatus prev = _status;
-
- _status = value;
-
- var message = CurrentContext == null ? null : CurrentContext.MessageEnvelope;
-
- _events.OnPipelineStatusChanged(new MessagePipelineStatusChangedEventArgs
- {Pipeline = this, PreviousStatus = prev, CurrentStatus = value,Message = message});
- }
- }
- }
-
- public int CurrentComponentIndex { get; private set; }
-
- #region IMessagePipeline Members
-
-
- public IMessageContext CurrentContext { get; private set; }
- public IMessagePipelineComponent CurrentComponent { get; private set; }
-
-
- public virtual void Initialize(MessageEnvelope messageEnvelope,IMessagingEndpoint endpoint,PipelineDirection direction,params IMessagePipelineComponent[] pipelineComponents)
- {
- SetCurrentPipeline(this, direction);
-
- PipelineDirection = direction;
- Endpoint = endpoint;
-
- if (pipelineComponents != null)
- ((List<IMessagePipelineComponent>)PipelineComponents).AddRange(pipelineComponents);
-
-
- if (Status > PipelineStatus.Uninitialized)
- throw new InvalidOperationException(
- "This MessageEnvelope Processing Pipeline has already been initialized. Initialized can only be called once.");
-
- Status = PipelineStatus.Initializing;
-
- CurrentContext = CreateMessageContext(messageEnvelope);
- InitializePipelineComponents();
-
- Status = PipelineStatus.Initialized;
- _events.OnPipelineInitialized(new MessagePipelineEventArgs{Pipeline = this,Message = CurrentContext.MessageEnvelope});
- }
-
- public void ProcessMessage()
- {
- try
- {
- if (Status != PipelineStatus.Initialized)
- throw new InvalidOperationException("The current status of this MessageEnvelope Pipeline is " + Status +
- ". Process() can only be called when the current status is Initialized.");
- Status = PipelineStatus.Processing;
-
- _events.OnPipelineStarted(new MessagePipelineEventArgs { Pipeline = this, Message = CurrentContext.MessageEnvelope});
-
- if (PipelineComponents != null)
- {
- for (CurrentComponentIndex = 0; CurrentComponentIndex < PipelineComponents.Count; CurrentComponentIndex++)
- {
- IMessagePipelineComponent component = PipelineComponents[CurrentComponentIndex];
-
- CurrentComponent = component;
-
- if (component.Enabled == false ||
- component.EnabledFor(CurrentContext.MessageEnvelope) == false)
- continue;
-
-
- _events.OnProcessingComponentStarted(new MessagePipelineEventArgs { Pipeline = this, Message = CurrentContext.MessageEnvelope });
-
- component.ProcessMessage(CurrentContext.MessageEnvelope);
-
- _events.OnProcessingComponentCompleted(new MessagePipelineEventArgs { Pipeline = this, Message = CurrentContext.MessageEnvelope });
-
- if (CurrentContext.AbortMessageProcessing)
- break;
- }
- }
-
- Status = PipelineStatus.Complete;
- CurrentComponent = null;
-
- _events.OnPipelineCompleted(new MessagePipelineEventArgs { Pipeline = this, Message = CurrentContext.MessageEnvelope });
-
- }
- catch (Exception ex)
- {
- ex =
- new MessageProcessingException(
- "An error occurred processing a message in pipeline component " + GetType().Name, ex,
- CurrentContext.MessageEnvelope);
- if (!_events.OnPipelineError(new MessagePipelineErrorEventArgs {Pipeline = this, Error = ex, Message = CurrentContext.MessageEnvelope}))
- throw;
- }
- finally
- {
- ClearCurrentPipeline(PipelineDirection);
- }
- }
-
-
- public virtual void Dispose()
- {
- CurrentReceivePipeline = null;
- CurrentContext = null;
- foreach (IMessagePipelineComponent component in PipelineComponents)
- {
- component.Dispose();
- }
- }
-
- #endregion
-
- protected virtual void InitializePipelineComponents()
- {
- foreach (IMessagePipelineComponent pipelineComponent in PipelineComponents)
- {
- pipelineComponent.Pipeline = this;
- }
- }
-
- protected virtual IMessageContext CreateMessageContext(MessageEnvelope messageEnvelope)
- {
- return new MessageContext(messageEnvelope, this);
- }
-
-
-
- #region Thead Status Singleton
-
- [ThreadStatic] private static IMessagePipeline _currentReceivePipeline;
-
- public static IMessagePipeline CurrentReceivePipeline
- {
- get { return _currentReceivePipeline; }
- protected set { _currentReceivePipeline = value; }
- }
-
- [ThreadStatic]
- private static IMessagePipeline _currentSendPipeline;
-
- public static IMessagePipeline CurrentSendPipeline
- {
- get { return _currentSendPipeline; }
- protected set { _currentSendPipeline = value; }
- }
-
- public static void SetCurrentPipeline(IMessagePipeline pipeline,PipelineDirection direction)
- {
- if (direction == PipelineDirection.Receive)
- {
- if (CurrentReceivePipeline != null)
- throw new InvalidOperationException(
- "Only oneReceivePipeline is allowed per thread. A MessagePipline has already been asigned to this thread.");
-
- CurrentReceivePipeline = pipeline;
- }
- else
- {
- if (CurrentSendPipeline != null)
- throw new InvalidOperationException(
- "Only one SendPipeline is allowed per thread. A MessagePipline has already been asigned to this thread.");
-
- CurrentSendPipeline = pipeline;
- }
- }
-
- public static void ClearCurrentPipeline(PipelineDirection direction)
- {
- if (direction == PipelineDirection.Receive)
- CurrentReceivePipeline = null;
- else
- CurrentSendPipeline = null;
- }
-
- #endregion
- }
- }