Example #1
0
        private void RedeclareExchangesAndQueues(AmqpModelContainer model, string serviceName)
        {
            //Redeclare exchanges and queues every minute if exchanges and queues are transient, or the first time client is sending a message
            TimeSpan elapsedSinceLastDeclareExchange = TimeSpan.FromMilliseconds(Environment.TickCount - lastExchangeDeclareTickCount);

            //TODO: Partition elapsedSinceLastDeclareExchange by serviceName and connection so that redeclares take place on new servicenames and connections.

            //Discovering firstDeclare by comparing lastExchangeDeclareTickCount to zero is not perfect
            //because tickcount can wrap back to zero (through the negative number range), if client is running long enough.
            //However, redeclaring exchanges and queues are a safe operation, so this is okay if it occurs more than once in persistent queues.
            bool firstDeclare = lastExchangeDeclareTickCount == 0;

            if (firstDeclare || (!messagingConfig.PersistentWorkQueuesAndExchanges && (elapsedSinceLastDeclareExchange.TotalMilliseconds < 0 || elapsedSinceLastDeclareExchange.TotalSeconds > 60)))
            {
                if (!firstDeclare)
                {
                    //All threads must attempt to declare exchanges and queues if it hasn't been previously declared
                    //(for instance, all threads were started at once)
                    //So do not swap out this value on first declare
                    lastExchangeDeclareTickCount = Environment.TickCount;
                }
                AmqpUtils.DeclareExchangeAndQueues(model.Channel, messageMapper, messagingConfig, serviceName, exchangeDeclareSync, null);
                if (firstDeclare)
                {
                    //Swap out this value after declaring on firstdeclare
                    lastExchangeDeclareTickCount = Environment.TickCount;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Initislizes a new instance of the <see cref="RestBusSubscriber"/>
        /// </summary>
        /// <param name="messageMapper">The <see cref="IMessageMapper"/> used by the subscriber.</param>
        /// <param name="settings">The subscriber settings</param>
        public RestBusSubscriber(IMessageMapper messageMapper, SubscriberSettings settings)
        {
            this.messageMapper = messageMapper;
            messagingConfig    = messageMapper.MessagingConfig; //Fetched only once
            if (messagingConfig == null)
            {
                throw new ArgumentException("messageMapper.MessagingConfig returned null", "messageMapper");
            }

            if (messageMapper.SupportedExchangeKinds == default(ExchangeKind))
            {
                throw new ArgumentException("messageMapper.SupportedExchangeKinds is not set up.", "messageMapper");
            }

            serviceName = (messageMapper.GetServiceName(null) ?? String.Empty).Trim();

            subscriberIdHeader = new string[] { AmqpUtils.GetNewExclusiveQueueId() };

            this.connectionFactory = new ConnectionFactory();
            connectionFactory.Uri  = new Uri(messageMapper.ServerUris[0].Uri);
            ConnectionNames        = messageMapper.ServerUris.Select(u => u.FriendlyName ?? String.Empty).ToArray();
            connectionFactory.RequestedHeartbeat = Client.RPCStrategyHelpers.HEART_BEAT;

            this.Settings            = settings ?? new SubscriberSettings(); //Make sure a default value is set, if not supplied by user.
            this.Settings.Subscriber = this;                                 //Indicate that the subcriber settings is owned by this subscriber.
        }
        public void TestAmqpFixtureRequestReply()
        {
            var amqpFixture = new AmqpFixture();

            //Setup Listener:
            bool MessageReceiver(Message message)
            {
                var subject = message.Properties?.Subject;

                if (subject != null && subject == "EchoMessage")
                {
                    var m = AmqpUtils.DeserializeMessage(message.Body);
                    amqpFixture.AmqpService.SendMessage(message.Properties.ReplyTo, message.Properties.Subject, m, message.Properties.CorrelationId);
                    return(true);
                }
                return(false);
            }

            var listener = amqpFixture.AmqpService.GetAmqpListener(MessageReceiver, "TestRequest");

            //RequestReply Message:
            var requestMsg = new
            {
                Key = "Test"
            };
            var response = amqpFixture.AmqpService.RequestReply(requestMsg, "EchoMessage", "TestRequest");

            Assert.NotNull(response);
            Assert.NotNull(response["Key"]);
            Assert.Equal("Test", response["Key"]);

            listener.Disconnect();
        }
Example #4
0
        private bool OnMessage(Message message)
        {
            var messageBodyObj = AmqpUtils.DeserializeMessage(message.Body);

            if (messageBodyObj == null)
            {
                throw new Exception("Could not deserialize message");
            }

            try
            {
                switch (message.Properties.Subject)
                {
                case "PutResource":
                {
                    var data     = messageBodyObj["body"].ToObject <string>();
                    var hashCode = Hash64Str(data);
                    _amqpService.SendMessage(message.Properties.ReplyTo,
                                             message.Properties.Subject,
                                             new { responseObject = new { hash = hashCode, uuid = Guid.NewGuid() } }, message.Properties.CorrelationId);
                    break;
                }

                default:
                    throw new NotImplementedException();
                }
            }
            catch (Exception e)
            {
                throw;
            }

            return(true);
        }
Example #5
0
        public RestBusSubscriber(IMessageMapper messageMapper)
        {
            exchangeInfo = messageMapper.GetExchangeInfo();
            subscriberId = AmqpUtils.GetRandomId();

            this.connectionFactory = new ConnectionFactory();
            connectionFactory.Uri  = exchangeInfo.ServerAddress;
            connectionFactory.RequestedHeartbeat = Client.RestBusClient.HEART_BEAT;
        }
Example #6
0
//
//
//        public static string PrintAmqpJsonMessage(this Message message)
//        {
//            var sb = new StringBuilder();
//            sb.Append("----------------------------------------------------------------------------\n");
//            sb.Append("Body........................: \n");
//            sb.Append(jsonText);
//            sb.Append("\n");
//            sb.Append("----------------------------------------------------------------------------\n");
//
//            return sb.ToString();
//        }

        public static void DebugLogAmqpMessage(this ILog logger, string message, Amqp.Message m,
                                               string queue = null)
        {
            try
            {
                var msg           = AmqpUtils.DeserializeMessage(m.Body);
                var formattedJson = JsonConvert.SerializeObject(msg, DebugPrintSerializerSettings);
                var sb            = new StringBuilder(message).Append("\n");
                sb.Append("----------------------------------------------------------------------------\n");
                if (queue != null)
                {
                    sb.Append(PadRight("Queue")).Append(queue).Append("\n");
                }

                if (m.Properties != null)
                {
                    if (m.Properties.ReplyTo != null)
                    {
                        sb.Append(PadRight("ReplyTo")).Append(m.Properties.ReplyTo).Append("\n");
                    }

                    if (m.Properties.Subject != null)
                    {
                        sb.Append(PadRight("Subject")).Append(m.Properties.Subject).Append("\n");
                    }

                    if (m.Properties.CorrelationId != null)
                    {
                        sb.Append(PadRight("CorrelationId")).Append(m.Properties.CorrelationId).Append("\n");
                    }

                    if (m.Properties.MessageId != null)
                    {
                        sb.Append(PadRight("Properties.MessageId")).Append(m.Properties.MessageId).Append("\n");
                    }
                }

                if (m.ApplicationProperties != null)
                {
                    foreach (var pair in m.ApplicationProperties.Map)
                    {
                        sb.Append(PadRight($"Application.{pair.Key}")).Append(pair.Value);
                    }
                }
                sb.Append(PadRight("Body")).Append(formattedJson).Append("\n");
                sb.Append("----------------------------------------------------------------------------\n");
                logger.Debug(sb.ToString());
            }
            catch (Exception e)
            {
                logger.Warn("Error in CusomLoggerExtensions while logging Amqp.Message", e);
            }
        }
Example #7
0
        private static void DeclareIndirectReplyToQueue(IModel channel, string queueName)
        {
            //The queue is set to be auto deleted once the last consumer stops using it.
            //However, RabbitMQ will not delete the queue if no consumer ever got to use it.
            //Passing x-expires in solves that: It tells RabbitMQ to delete the queue, if no one uses it within the specified time.

            var callbackQueueArgs = new Dictionary <string, object>();

            callbackQueueArgs.Add("x-expires", (long)AmqpUtils.GetCallbackQueueExpiry().TotalMilliseconds);

            //Declare call back queue
            channel.QueueDeclare(queueName, false, false, true, callbackQueueArgs);
        }
Example #8
0
        public CallbackQueueRPCStrategy(ClientSettings clientSettings, string queueName)
        {
            this.clientSettings = clientSettings;

            if (String.IsNullOrEmpty(queueName))
            {
                queueName = SynchronizedRandom.Instance.Next().ToString();
            }
            else
            {
                queueName = queueName.Trim();
            }
            this.indirectReplyToQueueName = AmqpUtils.GetCallbackQueueName(queueName, AmqpUtils.GetNewExclusiveQueueId());

            //Initialize expectedResponses
            expectedResponses = new ConcurrentDictionary <string, ExpectedResponse>();
        }
        public void TestAmqpFixtureSendAndReceive()
        {
            var amqpFixture = new AmqpFixture();
            var service     = amqpFixture.AmqpService;
            var num         = new Random((int)DateTime.Now.Ticks).Next(999999);

            bool MessageReceiver(Message message)
            {
                var body = AmqpUtils.DeserializeMessage(message.Body);

                Assert.Equal("Test", body["Name"]);
                Assert.Equal(true, body["Test"]);

                ReceivedMessageNum++;
                return(true);
            }

            var amqpListener = service.GetAmqpListener(MessageReceiver, $"TestQueue/{num}");

            Task.Delay(100);
            const int msgNum = 5;

            for (var i = 0; i < msgNum; i++)
            {
                var msg = new
                {
                    Name  = "Test",
                    Test  = true,
                    Value = i
                };

                service.SendMessage($"TestQueue/{num}", "Test", msg);
            }

            var watch = Stopwatch.StartNew();

            while (ReceivedMessageNum < msgNum && watch.ElapsedMilliseconds < 10000)
            {
                Thread.Sleep(100);
            }
            Assert.Equal(msgNum, ReceivedMessageNum);

            amqpListener.Disconnect();
        }
Example #10
0
        /// <summary>Send an HTTP request as an asynchronous operation.</summary>
        /// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1" />.The task object representing the asynchronous operation.</returns>
        /// <param name="request">The HTTP request message to send.</param>
        /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="request" /> was null.</exception>
        public override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (request.RequestUri == null && BaseAddress == null)
            {
                throw new InvalidOperationException("The request URI must either be set or BaseAddress must be set");
            }

            if (disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
            hasKickStarted = true;
            PrepareMessage(request);

            //Get Request Options
            RequestOptions requestOptions    = GetRequestOptions(request);
            var            messageProperties = GetMessagingProperties(requestOptions);

            //Determine if message expects a response
            TimeSpan requestTimeout = GetRequestTimeout(requestOptions);
            //TODO: expectingResponse has a slightly different meaning in publisher confirms
            //where timespan may be longer than zero but MessageExpectsReply is false
            //in which case the timeout only applies to how long to wait for the publisher confirmation.
            bool expectingResponse = requestTimeout != TimeSpan.Zero && GetExpectsReply(request);

            //Declare messaging resources
            ExpectedResponse   arrival = null;
            AmqpModelContainer model   = null;
            bool   modelClosed         = false;
            string correlationId       = null;

            //Get channel pool and decide on RPC strategy
            var          pool        = connectionMgr.GetConnectedPool();
            IRPCStrategy rpcStrategy = pool.IsDirectReplyToCapable && !Settings.DisableDirectReplies ? directStrategy : callbackStrategy;

            try
            {
                #region Ensure CallbackQueue is started (If Using CallbackQueue Strategy)

                rpcStrategy.StartStrategy(pool, expectingResponse);

                #endregion

                #region Populate BasicProperties
                //Fill BasicProperties

                BasicProperties basicProperties = new BasicProperties();

                //Set message delivery mode -- Make message persistent if either:
                // 1. Properties.Persistent is true
                // 2. messagingConfig.PersistentMessages is true and Properties.Persistent is null
                // 3. messagingConfig.PersistentMessages is true and Properties.Persistent is true
                if (messageProperties.Persistent == true || (messagingConfig.PersistentMessages && messageProperties.Persistent != false))
                {
                    basicProperties.Persistent = true;
                }

                //Set Exchange Headers
                var exchangeHeaders = messageProperties.Headers ?? messageMapper.GetHeaders(request);
                if (exchangeHeaders != null)
                {
                    basicProperties.Headers = exchangeHeaders;
                }

                if (expectingResponse)
                {
                    //Set CorrelationId
                    correlationId = correlationIdGen.GetNextId();
                    basicProperties.CorrelationId = correlationId;

                    //Set Expiration if messageProperties doesn't override Client.Timeout, RequestOptions and MessageMapper.
                    if (!messageProperties.Expiration.HasValue && requestTimeout != System.Threading.Timeout.InfiniteTimeSpan &&
                        (messagingConfig.MessageExpires == null || messagingConfig.MessageExpires(request)))
                    {
                        if (requestTimeout.TotalMilliseconds > Int32.MaxValue)
                        {
                            basicProperties.Expiration = Int32.MaxValue.ToString();
                        }
                        else
                        {
                            basicProperties.Expiration = ((int)requestTimeout.TotalMilliseconds).ToString();
                        }
                    }
                }
                else if (!messageProperties.Expiration.HasValue && (messagingConfig.MessageExpires == null || messagingConfig.MessageExpires(request)))
                {
                    //Request has a zero timeout and the message mapper indicates it should expire and messageproperties expiration is not set:
                    //Set the expiration to zero which means RabbitMQ will only transmit if there is a consumer ready to receive it.
                    //If there is no ready consumer, RabbitMQ drops the message. See https://www.rabbitmq.com/ttl.html

                    basicProperties.Expiration = "0";
                }

                //Set expiration if set in message properties
                if (messageProperties.Expiration.HasValue)
                {
                    if (messageProperties.Expiration != System.Threading.Timeout.InfiniteTimeSpan)
                    {
                        var expiration = messageProperties.Expiration.Value.Duration();
                        if (expiration.TotalMilliseconds > Int32.MaxValue)
                        {
                            basicProperties.Expiration = Int32.MaxValue.ToString();
                        }
                        else
                        {
                            basicProperties.Expiration = ((int)expiration.TotalMilliseconds).ToString();
                        }
                    }
                    else
                    {
                        //Infinite Timespan indicates that message should never expire
                        basicProperties.ClearExpiration();
                    }
                }

                #endregion

                #region Get Ready to Send Message

                model = rpcStrategy.GetModel(pool, false);

                var serviceName =
                    (requestOptions == null || requestOptions.ServiceName == null)
                    ? (messageMapper.GetServiceName(request) ?? String.Empty).Trim()
                    : requestOptions.ServiceName.Trim();

                RedeclareExchangesAndQueues(model, serviceName);

                //TODO: Check if cancellation token was set before operation even began
                var taskSource = new TaskCompletionSource <HttpResponseMessage>();

                var exchangeKind = ExchangeKind.Direct;
                //TODO: Get ExchangeKind from CLient.Settings.ExchangeKind
                //TODO: Pull exchangeName from a concurrent dictionary that has a key of serviceName, exchangeKind
                //exchangeKind could be an index into arrays that have concurrentDictionaries.
                var exchangeName = AmqpUtils.GetExchangeName(messagingConfig, serviceName, exchangeKind);

                #endregion

                #region Start waiting for response
                //Start waiting for response if a request timeout is set.
                if (expectingResponse)
                {
                    //TODO: Better to just check if cancellationHasbeen requested instead of checking if it's None
                    if (!cancellationToken.Equals(System.Threading.CancellationToken.None))
                    {
                        //TODO: Have cancellationtokens cancel event trigger callbackHandle
                        //In fact turn this whole thing into an extension
                    }

                    arrival = rpcStrategy.PrepareForResponse(correlationId, basicProperties, model, request, requestTimeout, cancellationToken, taskSource);
                }

                #endregion

                #region Send Message
                //TODO: Implement routing to a different exchangeKind via substituting exchangeName
                //Send message
                model.Channel.BasicPublish(exchangeName,
                                           messageProperties.RoutingKey ?? messageMapper.GetRoutingKey(request, exchangeKind) ?? AmqpUtils.GetWorkQueueRoutingKey(),
                                           basicProperties,
                                           request.ToHttpRequestPacket().Serialize());

                //Close channel
                if (!expectingResponse || rpcStrategy.ReturnModelAfterSending)
                {
                    CloseAmqpModel(model);
                    modelClosed = true;
                }

                #endregion

                #region Cleanup if not expecting response
                //Exit with OK result if no request timeout was set.
                if (!expectingResponse)
                {
                    //TODO: Investigate adding a publisher confirm for zero timeout messages so we know that RabbitMQ did pick up the message before replying OK.
                    //Might add extra complexity to this class.

                    //Zero timespan means the client isn't interested in a response
                    taskSource.SetResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                    {
                        Content = _emptyByteArrayContent
                    });

                    rpcStrategy.CleanupMessagingResources(correlationId, arrival);
                }

                #endregion

                return(taskSource.Task);
            }
            catch (Exception ex)
            {
                //TODO: Log this

                if (model != null && !modelClosed)
                {
                    if (expectingResponse && model.Flags == ChannelFlags.RPC || model.Flags == ChannelFlags.RPCWithPublisherConfirms)
                    {
                        //Model might still be in use in waiting thread and so unsafe to be recycled
                        model.Discard = true;
                    }

                    CloseAmqpModel(model);
                }

                rpcStrategy.CleanupMessagingResources(correlationId, arrival);

                if (ex is HttpRequestException)
                {
                    throw;
                }
                else
                {
                    throw GetWrappedException("An error occurred while sending the request.", ex);
                }
            }
        }
Example #11
0
        public void Restart()
        {
            hasStarted.Set(true);

            //CLose connections and channels
            if (subscriberChannel != null)
            {
                if (subscriberConsumer != null)
                {
                    try
                    {
                        subscriberChannel.Channel.BasicCancel(subscriberConsumer.ConsumerTag);
                    }
                    catch { }
                }

                try
                {
                    subscriberChannel.Close();
                }
                catch
                {
                }
            }

            if (workChannel != null)
            {
                if (workConsumer != null)
                {
                    try
                    {
                        workChannel.Channel.BasicCancel(workConsumer.ConsumerTag);
                    }
                    catch { }
                }

                try
                {
                    workChannel.Close();
                }
                catch
                {
                }
            }

            if (_subscriberPool != null)
            {
                _subscriberPool.Dispose();
            }

            //NOTE: CreateConnection() can throw BrokerUnreachableException
            //That's okay because the exception needs to propagate to Reconnect() or Start()
            var conn = connectionFactory.CreateConnection();

            if (connectionBroken != null)
            {
                connectionBroken.Dispose();
            }
            connectionBroken = new CancellationTokenSource();

            if (stopWaitingOnQueue != null)
            {
                stopWaitingOnQueue.Dispose();
            }
            stopWaitingOnQueue = CancellationTokenSource.CreateLinkedTokenSource(disposedCancellationSource.Token, connectionBroken.Token);

            var pool = new AmqpChannelPooler(conn);

            _subscriberPool = pool;

            //Use pool reference henceforth.

            //Create work channel and declare exchanges and queues
            workChannel = pool.GetModel(ChannelFlags.Consumer);

            //Redeclare exchanges and queues
            AmqpUtils.DeclareExchangeAndQueues(workChannel.Channel, messageMapper, messagingConfig, serviceName, exchangeDeclareSync, Id);

            //Listen on work queue
            workConsumer = new ConcurrentQueueingConsumer(workChannel.Channel, requestQueued);
            string workQueueName = AmqpUtils.GetWorkQueueName(messagingConfig, serviceName);

            workChannel.Channel.BasicQos(0, (ushort)Settings.PrefetchCount, false);
            workChannel.Channel.BasicConsume(workQueueName, Settings.AckBehavior == SubscriberAckBehavior.Automatic, workConsumer);

            //Listen on subscriber queue
            subscriberChannel  = pool.GetModel(ChannelFlags.Consumer);
            subscriberConsumer = new ConcurrentQueueingConsumer(subscriberChannel.Channel, requestQueued);
            string subscriberWorkQueueName = AmqpUtils.GetSubscriberQueueName(serviceName, Id);

            subscriberChannel.Channel.BasicQos(0, (ushort)Settings.PrefetchCount, false);
            subscriberChannel.Channel.BasicConsume(subscriberWorkQueueName, Settings.AckBehavior == SubscriberAckBehavior.Automatic, subscriberConsumer);

            //Cancel connectionBroken on connection/consumer problems
            pool.Connection.ConnectionShutdown   += (s, e) => { connectionBroken.Cancel(); };
            workConsumer.ConsumerCancelled       += (s, e) => { connectionBroken.Cancel(); };
            subscriberConsumer.ConsumerCancelled += (s, e) => { connectionBroken.Cancel(); };
        }
Example #12
0
        public void TestInteropClient()
        {
            var requestQueueName = "Resources";

//            Connection.DisableServerCertValidation = true;

            // uncomment the following to write frame traces
//            Amqp.Trace.TraceLevel = TraceLevel.Frame;
//            Amqp.Trace.TraceListener = (l, f, a) =>
//            {
//                switch (l)
//                {
//                    case TraceLevel.Error: Logger.ErrorFormat(f, a); break;
//                    case TraceLevel.Warning: Logger.WarnFormat(f, a); break;
//                    case TraceLevel.Information:
//                    case TraceLevel.Output: Logger.InfoFormat(f, a); break;
//                    case TraceLevel.Verbose:
//                    case TraceLevel.Frame:
//                    default: Logger.DebugFormat(f, a); break;
//                }
//            };

            int sizeKB = 1024 * 10; //10MB

            //generate large payload
            var rand   = new Random(System.DateTimeOffset.Now.Millisecond);
            var ms     = new MemoryStream();
            var buffer = new byte[1024];

            for (var written = 0L; written < sizeKB; written++)
            {
                rand.NextBytes(buffer);
                ms.Write(buffer, 0, buffer.Length);
            }
            var base64String = Convert.ToBase64String(ms.ToArray());

            var msg = new
            {
                name     = $"rand{sizeKB}KB.bin",
                mimeType = "application/octet-stream",
                body     = base64String
            };
            var jsonText = JsonConvert.SerializeObject(msg);
            var bytes    = Encoding.UTF8.GetBytes(jsonText);


            var amqpService = Fixture.AmqpService;
//            try
//            {
            var session = amqpService.GetSession();

            // Sender attaches to fixed request queue name
            var sender = new SenderLink(session, "Interop.Client-sender", requestQueueName);

            // Receiver attaches to dynamic address.
            // Discover its name when it attaches.
            var replyTo          = "";
            var receiverAttached = new ManualResetEvent(false);

            void OnReceiverAttached(ILink l, Attach a)
            {
                replyTo = ((Source)a.Source).Address;
                receiverAttached.Set();
            }

            // Create receiver and wait for it to attach.
            var receiver = new ReceiverLink(
                session, "Interop.Client-receiver", new Source()
            {
                Dynamic = true
            }, OnReceiverAttached);

            if (receiverAttached.WaitOne(10000))
            {
                // Receiver is attached.
                Logger.Debug("Receiver is attached");

                var request = new Message(bytes)
                {
                    Properties = new Properties()
                    {
                        MessageId = "request" + 0,
                        ReplyTo   = replyTo,
                        Subject   = "PutResource"
                    }
                };

                sender.Send(request);
                var response = receiver.Receive();
                if (null != response)
                {
                    receiver.Accept(response);
                    var message = AmqpUtils.DeserializeMessage(response?.Body);
                    var uuid    = message["responseObject"]?["uuid"]?.ToString();
                    Assert.NotNull(uuid);
                    var guid = Guid.Parse(uuid);
                }
                else
                {
                    throw new ApplicationException(
                              string.Format("Receiver timeout receiving response {0}", 0));
                }
            }

            else
            {
                throw new ApplicationException("Receiver attach timeout");
            }
            receiver.Close();
            sender.Close();
            session.Close();
            return;
//            }
//            catch (Exception e)
//            {
//                Console.Error.WriteLine("Exception {0}.", e);
//                if (null != connection)
//                {
//                    connection.Close();
//                }
//            }
        }
Example #13
0
        public JObject SendInteropClientRequest(object msg, string subject, string requestQueue)
        {
            JObject message = null;

            var bytes = AmqpUtils.SerializeMessage(msg);

            var          amqpService = Fixture.AmqpService;
            var          session     = amqpService.GetSession();
            SenderLink   sender      = null;
            ReceiverLink receiver    = null;

            try
            {
                // Sender attaches to fixed request queue name
                sender = new SenderLink(session, "Interop.Client-sender", requestQueue);

                // Receiver attaches to dynamic address.
                // Discover its name when it attaches.
                var replyTo          = "";
                var receiverAttached = new ManualResetEvent(false);

                void OnReceiverAttached(ILink l, Attach a)
                {
                    replyTo = ((Source)a.Source).Address;
                    receiverAttached.Set();
                }

                // Create receiver and wait for it to attach.
                receiver = new ReceiverLink(
                    session, "Interop.Client-receiver", new Source()
                {
                    Dynamic = true
                }, OnReceiverAttached);

                if (receiverAttached.WaitOne(10000))
                {
                    // Receiver is attached.
                    Logger.Debug("Receiver is attached");

                    var request = new Message(bytes)
                    {
                        Properties = new Properties()
                        {
//                            MessageId = "request" + 0,
                            CorrelationId = replyTo,
                            ReplyTo       = replyTo,
                            Subject       = subject
                        }
                    };

                    sender.Send(request);
                    var response = receiver.Receive(TimeSpan.FromSeconds(8));

                    if (null != response)
                    {
                        receiver.Accept(response);
                        message = AmqpUtils.DeserializeMessage(response?.Body);
                    }
                    else
                    {
                        throw new ApplicationException(
                                  string.Format("Receiver timeout receiving response {0}", 0));
                    }
                }
                else
                {
                    throw new ApplicationException("Receiver attach timeout");
                }
            }
            catch (Exception e)
            {
                throw new ApplicationException("Exception: ", e);
            }
            finally
            {
                receiver?.Close();
                sender?.Close();
                session.Close();
            }
            return(message);
        }
Example #14
0
        public void Restart()
        {
            isStarted = true;

            //CLose connections and channels
            if (subscriberChannel != null)
            {
                try
                {
                    subscriberChannel.Close();
                }
                catch
                {
                }
            }

            if (workChannel != null)
            {
                try
                {
                    workChannel.Close();
                }
                catch
                {
                }
            }

            if (conn != null)
            {
                try
                {
                    conn.Close();
                }
                catch
                {
                }

                try
                {
                    conn.Dispose();
                }
                catch
                {
                }
            }


            //TODO: CreateConnection() can always throw BrokerUnreachableException so keep that in mind when calling
            conn = connectionFactory.CreateConnection();

            //Create shared queue
            SharedQueue <BasicDeliverEventArgs> queue = new SharedQueue <BasicDeliverEventArgs>();

            //Create work channel and declare exchanges and queues
            workChannel = conn.CreateModel();

            /* Work this into subscriber dispose and restart
             * //Cancel consumers on server
             * if(workCTag != null)
             * {
             *  try
             *  {
             *      workChannel.BasicCancel(workCTag);
             *  }
             *  catch { }
             * }
             *
             * if (subscriberCTag != null)
             * {
             *  try
             *  {
             *      workChannel.BasicCancel(subscriberCTag);
             *  }
             *  catch { }
             * }
             */

            //Redeclare exchanges and queues
            AmqpUtils.DeclareExchangeAndQueues(workChannel, exchangeInfo, exchangeDeclareSync, subscriberId);

            //Listen on work queue
            workConsumer = new QueueingBasicConsumer(workChannel, queue);
            string workQueueName = AmqpUtils.GetWorkQueueName(exchangeInfo);

            workChannel.BasicConsume(workQueueName, false, workConsumer);

            //Listen on subscriber queue
            subscriberChannel  = conn.CreateModel();
            subscriberConsumer = new QueueingBasicConsumer(subscriberChannel, queue);
            string subscriberWorkQueueName = AmqpUtils.GetSubscriberQueueName(exchangeInfo, subscriberId);

            subscriberChannel.BasicConsume(subscriberWorkQueueName, false, subscriberConsumer);
        }