/// <summary>
        /// This method creates a service message and injects it in to the execution path and bypasses the listener infrastructure.
        /// </summary>
        /// <param name="header">The message header to identify the recipient.</param>
        /// <param name="package">The objet package to process.</param>
        /// <param name="ChannelPriority">The prioirty that the message should be processed. The default is 1. If this message is not a valid value, it will be matched to the nearest valid value.</param>
        /// <param name="options">The process options.</param>
        /// <param name="release">The release action which is called when the payload has been executed.</param>
        /// <param name="isDeadLetterMessage">A flag indicating whether the message is a deadletter replay. These messages may be treated differently
        /// by the receiving commands.</param>
        public void Process(ServiceMessageHeader header
                            , object package              = null
                            , int ChannelPriority         = 1
                            , ProcessOptions options      = ProcessOptions.RouteExternal | ProcessOptions.RouteInternal
                            , Action <bool, Guid> release = null
                            , bool isDeadLetterMessage    = false)
        {
            var message = new ServiceMessage(header);

            message.ChannelPriority = ChannelPriority;
            if (package != null)
            {
                message.Blob = mSerializer.PayloadSerialize(package);
            }

            Process(message, options, release, isDeadLetterMessage);
        }
        /// <summary>
        /// This method attaches a rewrite rule to the channel pipeline.
        /// </summary>
        /// <typeparam name="C">The channel pipeline type.</typeparam>
        /// <param name="cpipe">The incoming pipeline.</param>
        /// <param name="canRedirect">The match function.</param>
        /// <param name="changeHeader">The redirect header.</param>
        /// <param name="canCache">Specifies whether the redirect hit can be cached.</param>
        /// <returns>Returns the original pipeline.</returns>
        public static C AttachMessageRedirectRule <C>(this C cpipe
                                                      , Func <TransmissionPayload, bool> canRedirect
                                                      , ServiceMessageHeader changeHeader
                                                      , bool canCache = true)
            where C : IPipelineChannel <IPipeline>
        {
            Action <TransmissionPayload> updateHeader = (p) =>
            {
                p.Message.ChannelId   = changeHeader.ChannelId;
                p.Message.MessageType = changeHeader.MessageType;
                p.Message.ActionType  = changeHeader.ActionType;
            };

            cpipe.AttachMessageRedirectRule(canRedirect, updateHeader, canCache);

            return(cpipe);
        }
Example #3
0
        /// <summary>
        /// This method replaces the channel with the command default if the value specified in the attribute is null.
        /// </summary>
        /// <param name="attr">The incoming attribute whose header channel should be checked.</param>
        /// <returns>Returns a message filter wrapper for the header.</returns>
        protected MessageFilterWrapper CommandChannelIdAdjust <A>(A attr)
            where A : CommandContractAttributeBase
        {
            ServiceMessageHeader header = attr.Header;

            if (header.ChannelId == null)
            {
                if (ChannelId == null)
                {
                    throw new CommandChannelIdNullException($"Command '{FriendlyName}' uses CommandContracts without a Channel id set but its default ChannelId is null.");
                }

                header = new ServiceMessageHeader(ChannelId, header.MessageType, header.ActionType);
            }

            return(new MessageFilterWrapper(header));
        }
        /// <summary>
        /// This method is used to send requests to a remote command and wait for a response.
        /// </summary>
        /// <typeparam name="RQ">The request object type.</typeparam>
        /// <typeparam name="RS">The response object type.</typeparam>
        /// <param name="header">The message header object that defines the remote endpoint.</param>
        /// <param name="rq">The request object.</param>
        /// <param name="settings">The request settings. Use this to specifically set the timeout parameters, amongst other settings, or to pass meta data to the calling party.</param>
        /// <param name="routing">The routing options by default this will try internal and then external endpoints.</param>
        /// <param name="principal">This is the principal that you wish the command to be executed under.
        /// By default this is taken from the calling thread if not passed.</param>
        /// <returns>Returns the async response wrapper.</returns>
        public virtual async Task <ResponseWrapper <RS> > Process <RQ, RS>(
            ServiceMessageHeader header
            , RQ rq
            , RequestSettings settings = null
            , ProcessOptions?routing   = default(ProcessOptions?)
            , IPrincipal principal     = null
            )
        {
            ServiceStartedCheck();

            return(await ProcessOutgoing <RQ, RS>(
                       header.ChannelId, header.MessageType, header.ActionType
                       , rq
                       , settings
                       , routing
                       , fallbackMaxProcessingTime : mDefaultRequestTimespan
                       , principal : principal ?? Thread.CurrentPrincipal));
        }
Example #5
0
        /// <summary>
        /// Intercepts the specified event arguments.
        /// </summary>
        /// <typeparam name="H">The harness type.</typeparam>
        /// <param name="harness">The harness.</param>
        /// <param name="action">The event arguments action.</param>
        /// <param name="direction">The optional direction filter.</param>
        /// <param name="header">The optional header.</param>
        /// <param name="processResponses">Set this to true to send any responses passed back in the context to the harness dispatcher. The default is true.</param>
        /// <returns>The harness</returns>
        public static H Intercept <H>(this H harness
                                      , Action <CommandHarnessRequestContext> action
                                      , CommandHarnessTrafficDirection?direction = null
                                      , ServiceMessageHeader header = null
                                      , bool processResponses       = true)
            where H : ICommandHarness
        {
            if (action == null)
            {
                throw new ArgumentNullException("action", "action cannot be null");
            }

            harness.OnEvent += (object sender, CommandHarnessEventArgs e) =>
            {
                //Is this a payload event, no then do not bubble up.
                if (!e.Event.Tracker.HasTransmissionPayload())
                {
                    return;
                }

                if (direction.HasValue && e.Event.Direction != direction.Value)
                {
                    return;
                }

                var payload = e.Event.Tracker.ToTransmissionPayload();
                ServiceMessageHeader headerFind = payload.Message.ToServiceMessageHeader();

                if (header == null || header.IsMatch(headerFind))
                {
                    var context = new CommandHarnessRequestContext(harness, e, payload);

                    action(context);

                    if (processResponses)
                    {
                        context.Responses.ForEach((r) => harness.Dispatcher.Process(r));
                    }
                }
            };

            return(harness);
        }
 /// <summary>
 /// This method creates a service message and injects it in to the execution path and bypasses the listener infrastructure.
 /// </summary>
 /// <param name="header">The message header fragment to identify the recipient. The channel will be inserted by the command harness.</param>
 /// <param name="package">The object package to process.</param>
 /// <param name="ChannelPriority">The priority that the message should be processed. The default is 1. If this message is not a valid value, it will be matched to the nearest valid value.</param>
 /// <param name="options">The process options.</param>
 /// <param name="release">The release action which is called when the payload has been executed by the receiving commands.</param>
 /// <param name="responseHeader">This is the optional response header</param>
 /// <param name="ResponseChannelPriority">This is the response channel priority. This will be set if the response header is not null. The default priority is 1.</param>
 /// <param name="originatorServiceId">This optional parameter allows you to set the originator serviceId</param>
 public void Process(ServiceMessageHeaderFragment header
                     , object package                      = null
                     , int ChannelPriority                 = 1
                     , ProcessOptions options              = ProcessOptions.RouteExternal | ProcessOptions.RouteInternal
                     , Action <bool, Guid> release         = null
                     , ServiceMessageHeader responseHeader = null
                     , int ResponseChannelPriority         = 1
                     , string originatorServiceId          = null
                     )
 {
     Process((Policy.ChannelId, header)
             , package
             , ChannelPriority
             , options
             , release
             , responseHeader
             , ResponseChannelPriority
             , originatorServiceId
             );
 }
Example #7
0
        /// <summary>
        /// This method returns a list of SqlFilter object for the listener channel.
        /// </summary>
        /// <returns>The list of SqlFilter object</returns>
        protected virtual List <SqlFilter> GetFilters()
        {
            List <SqlFilter> list;

            string id = OriginatorId.ExternalServiceId;

            if (id.Length > 50)
            {
                id = id.Substring(0, 50);
            }

            if (ListenOnOriginatorId)
            {
                list = new List <SqlFilter>();
                var servMess = new ServiceMessageHeader(ChannelId);
                list.Add(TopicHelper.SqlFilterQuery(new MessageFilterWrapper(servMess, OriginatorId.ExternalServiceId)));
            }
            else
            {
                list = TopicHelper.SqlFilter(mSupportedMessageTypes, ChannelId, ListenerMappingChannelId);
            }

            return(list);
        }
Example #8
0
        protected virtual bool SupportedResolve(ServiceMessageHeader header, out H command)
        {
            foreach (var item in mSupported)
            {
                if (item.Key.Message.Header.IsPartialKey)
                {
                    string partialkey = item.Key.Message.Header.ToPartialKey();

                    if (header.ToKey().StartsWith(partialkey))
                    {
                        command = item.Value;
                        return(true);
                    }
                }
                else if (item.Key.Message.Header.Equals(header))
                {
                    command = item.Value;
                    return(true);
                }
            }

            command = null;
            return(false);
        }
        /// <summary>
        /// Attaches the UDP listener to the incoming channel.
        /// </summary>
        /// <typeparam name="C">The pipeline type.</typeparam>
        /// <param name="cpipe">The pipeline.</param>
        /// <param name="udp">The UDP endpoint configuration.</param>
        /// <param name="defaultDeserializerContentType">Default deserializer MIME Content-type, i.e application/json.</param>
        /// <param name="defaultDeserializerContentEncoding">Default deserializer MIME Content-encoding, i.e. GZIP.</param>
        /// <param name="requestAddress">This is the optional address fragment which specifies the incoming message destination. If this is not set then ("","") will be used. This does not include a channelId as this will be provided by the pipeline.</param>
        /// <param name="responseAddress">This is the optional return address destination to be set for the incoming messages.</param>
        /// <param name="requestAddressPriority">This is the default priority for the request message. The default is null. This will inherit from the channel priority.</param>
        /// <param name="responseAddressPriority">This is the priority for the response address. The default is 1.</param>
        /// <param name="deserialize">The deserialize action.</param>
        /// <param name="canDeserialize">The deserialize check function.</param>
        /// <param name="action">The optional action to be called when the listener is created.</param>
        /// <returns>Returns the pipeline.</returns>
        public static C AttachUdpListener <C>(this C cpipe
                                              , UdpConfig udp
                                              , string defaultDeserializerContentType       = null
                                              , string defaultDeserializerContentEncoding   = null
                                              , ServiceMessageHeaderFragment requestAddress = null
                                              , ServiceMessageHeader responseAddress        = null
                                              , int?requestAddressPriority  = null
                                              , int responseAddressPriority = 1
                                              , Action <SerializationHolder> deserialize        = null
                                              , Func <SerializationHolder, bool> canDeserialize = null
                                              , Action <UdpChannelListener> action = null
                                              )
            where C : IPipelineChannelIncoming <IPipeline>
        {
            defaultDeserializerContentType = (
                defaultDeserializerContentType
                ?? $"udp_in/{cpipe.Channel.Id}"
                ).ToLowerInvariant();

            var listener = new UdpChannelListener(udp
                                                  , defaultDeserializerContentType, defaultDeserializerContentEncoding
                                                  , requestAddress, responseAddress, requestAddressPriority, responseAddressPriority
                                                  );

            if (deserialize != null)
            {
                cpipe.Pipeline.AddPayloadSerializer(
                    defaultDeserializerContentType
                    , deserialize: deserialize
                    , canDeserialize: canDeserialize);
            }

            cpipe.AttachListener(listener, action, true);

            return(cpipe);
        }
Example #10
0
 /// <summary>
 /// This method converts the message metadata in to a header.
 /// </summary>
 /// <returns></returns>
 public virtual string ToKey()
 {
     return(ServiceMessageHeader.ToKey(ChannelId, MessageType, ActionType));
 }
 /// <summary>
 /// This is the constructor for registering a manual command.
 /// </summary>
 /// <param name="header">The ServiceMessageHeader route for the command.</param>
 /// <param name="command">The command to process.</param>
 /// <param name="referenceId">The optional reference id for tracking.</param>
 public CommandInline(ServiceMessageHeader header
                      , Func <TransmissionPayload, List <TransmissionPayload>, IPayloadSerializationContainer, Task> command
                      , string referenceId = null) : this(new MessageFilterWrapper(header), command, referenceId)
 {
 }
Example #12
0
 /// <summary>
 /// This method unregisters a particular command.
 /// </summary>
 /// <param name="header"></param>
 /// <param name="isMasterJob">Specifies whether the command is linked to a master job.</param>
 protected void CommandUnregister(ServiceMessageHeader header, bool isMasterJob = false)
 {
     CommandUnregister(new MessageFilterWrapper(header, null), isMasterJob);
 }
 public CommandContractAttribute(string messageType, string actionType)
 {
     Header = new ServiceMessageHeader(null, messageType, actionType);
 }
 public CommandContractAttribute(string channelId = null, string messageType = null, string actionType = null)
 {
     Header = new ServiceMessageHeader(channelId, messageType, actionType);
 }
Example #15
0
 /// <summary>
 /// Intercepts just the outgoing messages, and then processes any responses returned in the context.
 /// </summary>
 /// <typeparam name="H">The harness type.</typeparam>
 /// <param name="harness">The harness.</param>
 /// <param name="action">The action.</param>
 /// <param name="header">The optional message destination header filter. You can pass a partial header.</param>
 /// <returns>Returns the harness to continue the pipeline.</returns>
 /// <exception cref="ArgumentNullException">action - action cannot be null</exception>
 public static H InterceptOutgoing <H>(this H harness, Action <CommandHarnessRequestContext> action, ServiceMessageHeader header = null)
     where H : ICommandHarness
 {
     return(harness.Intercept(action, CommandHarnessTrafficDirection.Outgoing, header, true));
 }
Example #16
0
 /// <summary>
 /// This method converts the message response metadata in to a header.
 /// </summary>
 /// <returns></returns>
 public virtual string ToResponseKey()
 {
     return(ServiceMessageHeader.ToKey(ResponseChannelId, ResponseMessageType, ResponseActionType));
 }
Example #17
0
 /// <summary>
 /// This is the default constructor.
 /// </summary>
 /// <param name="header">THe actual service message header.</param>
 /// <param name="clientId">This is the optional client id.</param>
 public MessageFilterWrapper(ServiceMessageHeader header, string clientId = null)
 {
     Header   = header;
     ClientId = clientId;
 }
Example #18
0
 /// <summary>
 /// This is the default
 /// </summary>
 /// <param name="channelId">The channelId.</param>
 /// <param name="messageType">The message type.</param>
 /// <param name="messageAction">The action type.</param>
 public ContractAttribute(string channelId, string messageType, string messageAction)
 {
     mHeader = new ServiceMessageHeader(channelId, messageType, messageAction);
 }
Example #19
0
 /// <summary>
 /// This constructor sets the header parameters.
 /// </summary>
 /// <param name="header">The header</param>
 public ServiceMessage(ServiceMessageHeader header) : this()
 {
     ChannelId   = header.ChannelId;
     MessageType = header.MessageType;
     ActionType  = header.ActionType;
 }
Example #20
0
 /// <summary>
 /// This exception is thrown when a request is sent to a command that is not recognised.
 /// </summary>
 /// <param name="id">The payload id.</param>
 /// <param name="header">The message header.</param>
 /// <param name="commandType">The command type.</param>
 public CommandNotSupportedException(Guid id, ServiceMessageHeader header, Type commandType) : base($"The command '{header.Key}' is not supported in {commandType.Name}")
 {
     Id      = id;
     Header  = header;
     Command = commandType.Name;
 }
Example #21
0
 public MessageFilterWrapper(ServiceMessageHeader header, bool isDeadLetter = false)
 {
     Header       = header;
     IsDeadLetter = isDeadLetter;
 }
Example #22
0
 /// <summary>
 /// This is the default constructor.
 /// </summary>
 /// <param name="header">THe actual service message header.</param>
 public MessageFilterWrapper(ServiceMessageHeader header)
 {
     Header = header;
 }
Example #23
0
        /// <summary>
        /// This commands returns true is the command channelId and action are supported.
        /// </summary>
        /// <param name="header">The message header.</param>
        /// <returns>Returns true if the message is supported.</returns>
        public virtual bool SupportsMessage(ServiceMessageHeader header)
        {
            H command;

            return(SupportedResolve(header, out command));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CommandContractAttributeBase"/> class.
 /// </summary>
 /// <param name="header">The service message header.</param>
 protected CommandContractAttributeBase(ServiceMessageHeader header)
 {
     Header = header;
 }