protected override void RunLoop()
        {
            using (var redisClient = clientsManager.GetReadOnlyClient())
            {                
                using (var subscription = redisClient.CreateSubscription())
                {
                    subscription.OnUnSubscribe = channel => Log.Debug("OnUnSubscribe: " + channel);

                    subscription.OnMessage = (channel, msg) =>
                    {

                        if (msg == WorkerStatus.StopCommand)
                        {
                            Log.Debug("Stop Command Issued");

                            if (Interlocked.CompareExchange(ref status, WorkerStatus.Stopped, WorkerStatus.Started) != WorkerStatus.Started)
                                Interlocked.CompareExchange(ref status, WorkerStatus.Stopped, WorkerStatus.Stopping);

                            Log.Debug("UnSubscribe From All Channels...");
                            subscription.UnSubscribeFromAllChannels(); //Un block thread.
                            return;
                        }

                        this.IncrementMessageCount(1);
                        var messageReceivedArgs = new MessageReceivedArgs {QueueName = msg};
                        this.MqServer.NotifyMessageReceived(messageReceivedArgs);                        
                    };

                    subscription.SubscribeToChannels(QueueNames.TopicIn); //blocks thread
                }
            }
        }
Ejemplo n.º 2
0
        // IList<WaitHandle> manualResetEvents = new List<WaitHandle>();
        public override void NotifyMessageReceived(MessageReceivedArgs messageReceivedArgs)
        {
            var handlerThreadCount = this.MessageHandlerRegister.RegisteredHandlers[messageReceivedArgs.MessageType].Configuration.NoOfThreads;

            if (handlerThreadCount == 0) //// 0 => Threadpool
            {
                // Threadpool
                // Queue the item to execute using the thread pool.

                // TODO: Use Wait and Pulse; Use a incremental lock counter to ensure that all queued work items complete.
                // var manualResetEvent = new ManualResetEvent(false);
                // lock (manualResetEvents)
                // {
                // TODO: Verify that a lock is not required.
                // manualResetEvents.Add(manualResetEvent);
                Interlocked.Increment(ref threadPoolWorkItemCount);
                ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteUsingQueuedWorkItem), messageReceivedArgs);
                // TODO: How to wait for all tasks to complete using this method?
                // }

                /*
                 * // TODO: Change Project Framework to 3.5
                 * // TODO: Wait for all queued work items to complete when stop is called, in DISPOSE method.
                 * lock (manualResetEvents)
                 * {
                 *  // After stop is called, set a flag that indicates pulse should be called when count == 0
                 *  // TODO: Loop until count is 0; then pulse (Or, if already 0; pulse instantly)
                 *  WaitHandle.WaitAll(manualResetEvents.ToArray());
                 * }*/
            }
            else
            {
                // Static Thread
                base.NotifyMessageReceived(messageReceivedArgs);
            }
        }
        protected override void RunLoop()
        {
            // Use Long-Polling to retrieve messages from a specific SQS queue.      
            while (Interlocked.CompareExchange(ref status, 0, 0) == WorkerStatus.Started)            
            {
                Log.DebugFormat("Polling SQS Queue '{0}' for messages.", this.QueueName);

                var response = this.SqsClient.ReceiveMessage(this.QueueUrl, this.WaitTimeInSeconds, this.MaxNumberOfMessages, this.MessageVisibilityTimeout, "ApproximateReceiveCount"); // Blocks until timout, or msg received
                if (response.IsSetReceiveMessageResult() && response.ReceiveMessageResult.Message.Count > 0)
                {
                    // Place the item in the ready to process queue, and notify workers that a new msg has arrived.                    
                    Log.DebugFormat("Received {0} Message(s) from Queue '{1}'.", response.ReceiveMessageResult.Message.Count, this.QueueName);

                    // Thread-safe local queue -> Provides access to msg reponse, and retrieving multiple msgs!
                    foreach (var sqsMessage in response.ReceiveMessageResult.Message)
                    {
                        // TODO: Remember; Need to code so no problem if same message received twice... consider cache?
                        // TODO: Need to verify Message MD5, and use 'IsSet()' methods to ensure the msg is valid. Earlier in process.
                        if (sqsMessage.IsSetMD5OfBody() && !MessageSecurity.IsMd5Valid(sqsMessage.Body, sqsMessage.MD5OfBody))
                        {
                            Log.WarnFormat("Message '{0}' has invalid MD5 signature, will not be processed.");
                            continue;                            
                        }


                        var messageBytes = Convert.FromBase64String(sqsMessage.Body);
                        
                        // Set standard message properties
                        var message = messageBytes.ToMessage(this.MessageType);
                        if (sqsMessage.IsSetAttribute() && sqsMessage.Attribute.Count > 0)
                        {
                            foreach (var attribute in sqsMessage.Attribute)
                            {
                                if (attribute.Name == "ApproximateReceiveCount")
                                {
                                    message.RetryAttempts = int.Parse(attribute.Value);    
                                    break;
                                }
                            }                            
                        }

                        // Set SQS message properties
                        var sqsMessageBody = message.Body as ISqsMessageBody;
                        if (sqsMessageBody != null)
                        {
                            sqsMessageBody.ReceiptHandle = sqsMessage.ReceiptHandle;
                            sqsMessageBody.QueueUrl = this.QueueUrl;
                            sqsMessageBody.QueueName = this.QueueName;
                            sqsMessageBody.VisibilityTimeout = this.MessageVisibilityTimeout;
                            message.RetryAttempts += sqsMessageBody.PreviousRetryAttempts;
                        }
                        else
                        {
                            Log.WarnFormat("The message type '{0}' is using the AwsSqsQueueHandler, but does not implement 'ISqsMessageBody'. No AwsSqsMessageHandlerRegister pre,post or error message handlers will be executed.", this.MessageType.Name);
                        }
                        // =====================
                        
                        this.MessageCoordinator.EnqueMessage(this.QueueName, message, this.MessageType);
                        this.IncrementMessageCount(1);

                        var messageReceivedArgs = new MessageReceivedArgs { MessageType = this.MessageType, QueueName = this.QueueName, MessageId = sqsMessage.MessageId };
                        this.MqServer.NotifyMessageReceived(messageReceivedArgs);
                    }
                }
            }
          
            Log.DebugFormat("Stopped polling SQS queue: {0}", this.QueueName);            
        }