private static string GetProcessTypeOfChannel(string type)
        {
            var processTypeOfChannel = RedisServices.HashGet(_keyListChannelName, type);

            if (string.IsNullOrEmpty(processTypeOfChannel))
            {
                processTypeOfChannel = ProcessType.Topic.ToString();
            }
            return(processTypeOfChannel);
        }
        public static ChannelInfo GetChannelInfo(string channelName)
        {
            var channelVal = RedisServices.HashGet(_keyListChannelName, channelName);

            return(new ChannelInfo()
            {
                DataStructure = channelVal,
                Name = channelName,
                Subscribers = GetSubscribers(channelName),
                PendingDataQueueLength = GetPendingDataQueueLength(channelName),
                SuccessDataQueueLength = GetSuccessDataQueueLength(channelName),
                ErrorDataQueueLength = GetErrorDataQueueLength(channelName)
            });
        }
        private static Thread CreateNotifyWorker(string type)
        {
            return(new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        string queueDataName = GetKeyQueueDataForChannel(type);

                        var processTypeOfChannel = RedisServices.HashGet(_keyListChannelName, type);
                        string channelSubscriber = GetKeySubscribersForChannel(type);

                        var subscribers = RedisServices.HashGetAll(channelSubscriber);

                        if (RedisServices.QueueHasValue(queueDataName))
                        {
                            ProcessType processType = GetProcessTypeByName(processTypeOfChannel);
                            if (processType == ProcessType.Topic)
                            {
                                string queueDataNameChannelSubscriber = GetKeyToRealPublishFromChannelToSubscriber(string.Empty, type, processTypeOfChannel);
                                //notify to parent, then parent will find subscribers to process same data
                                RedisServices.Publish(queueDataNameChannelSubscriber, processTypeOfChannel);
                            }
                            else
                            {
                                foreach (var subc in subscribers)
                                {
                                    string queueDataNameChannelSubscriber = GetKeyToRealPublishFromChannelToSubscriber(subc.Key, type, processTypeOfChannel);

                                    RedisServices.Publish(queueDataNameChannelSubscriber, processTypeOfChannel);
                                    //notify to subscribers to dequeue data and process
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                    }
                    finally
                    {
                        Thread.Sleep(100);
                    }
                }
            }));
        }
        /// <summary>
        /// type = channel
        /// </summary>
        /// <param name="type"></param>
        static void RegisterNotifyWorkerAndStart(string type)
        {
            var processTypeOfChannel = RedisServices.HashGet(_keyListChannelName, type);

            var channelRegistered = type + "_" + processTypeOfChannel;

            lock (_mapedHandleCounter)
            {
                int count;
                if (_mapedHandleCounter.TryGetValue(channelRegistered, out count))
                {
                    if (count > 0)
                    {
                        _mapedHandleCounter[channelRegistered] = 1;
                        // allow only one worker (thread dequeue data)
                        return;
                    }
                    ////if allow more than one thread to dequeue
                    //List<Thread> listWorker;

                    //if (_mapedHandleWorkers.TryGetValue(type, out listWorker))
                    //{
                    //    var nextWorker = CreateDequeuWorker(type);
                    //    listWorker.Add(nextWorker);
                    //    nextWorker.Start();
                    //    _mapedHandleWorkers[type] = listWorker;
                    //    _mapedHandleCounter[type] = count + 1;
                    //}
                }
                else
                {
                    _mapedHandleCounter[channelRegistered] = 1;

                    var firstWorker = CreateNotifyWorker(type);

                    _mapedHandleWorkers[channelRegistered] = new List <Thread>()
                    {
                        firstWorker
                    };
                    //make sure alway have at less one worker to dequeue
                    firstWorker.Start();
                }
            }
        }