/// <summary>
        /// Processes initial web socket connection request, sends unreceived messages and keeps websocket connection alive
        /// </summary>
        /// <param name="context">HttpContext</param>
        /// <param name="socketId">Web Socket Id</param>
        /// <param name="socketInfo">Web Socket item info</param>
        /// <param name="topic">Message topic</param>
        /// <returns></returns>
        private async Task ProcessRequest(HttpContext context, Guid socketId, WebSocketItemInfo socketInfo, string topic)
        {
            // Send old messages
            var oldMessages = _persistanceService.Get(topic, socketInfo.CreationDT);

            foreach (var message in oldMessages)
            {
                await PushMessageToClient(message, socketInfo.Socket);
            }

            // Wait in a loop
            var buffer = new byte[1024 * 4];
            WebSocketReceiveResult result = await socketInfo.Socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None);

            while (!result.CloseStatus.HasValue)
            {
                result = await socketInfo.Socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None);
            }

            // Close connection
            await socketInfo.Socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);

            // Remove from dictionary
            ConcurrentDictionary <Guid, WebSocketItemInfo> socketList;

            _sockets.TryGetValue(topic, out socketList);

            WebSocketItemInfo dummyVar;

            socketList.TryRemove(socketId, out dummyVar);
        }
        /// <summary>
        /// Handles web socket requests
        /// </summary>
        /// <param name="context">HttpContext</param>
        /// <param name="options">Middleware options</param>
        /// <returns></returns>
        public async Task HandleRequest(HttpContext context, LWMessagePushMiddlewareOptions options)
        {
            try
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    if (!context.Request.Query.ContainsKey("topic"))
                    {
                        string err = "Topic is required.";
                        options.LogListener.Log(string.Format("WebSocket handler error: {0}", err), Logging.LogLevel.Error);
                        throw new ArgumentNullException(err);
                    }

                    string   topic             = context.Request.Query["topic"];
                    Guid     socketId          = Guid.NewGuid();
                    string   lastReceive       = context.Request.Query["lastr"];
                    DateTime lastReceivedMsgDT = DateTime.UtcNow;
                    options.LogListener.Log(string.Format("WebSocket connection request is received at {0} UTC for {1}", lastReceivedMsgDT.ToString(), topic), Logging.LogLevel.Verbose);

                    if (lastReceive != null)
                    {
                        DateTime.TryParse(lastReceive, out lastReceivedMsgDT);
                    }

                    WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();

                    WebSocketItemInfo socketInfo = new WebSocketItemInfo(webSocket, lastReceivedMsgDT);
                    var newTopicDict             = new ConcurrentDictionary <Guid, WebSocketItemInfo>();
                    newTopicDict.TryAdd(socketId, socketInfo);

                    _sockets.AddOrUpdate(topic, newTopicDict, (a, b) => { b.TryAdd(socketId, socketInfo); return(b); });
                    await ProcessRequest(context, socketId, socketInfo, topic);
                }
                else
                {
                    context.Response.StatusCode = 400;
                }
            }
            catch (Exception e)
            {
                options.LogListener.Log(string.Format("WebSocket handler error: {0}", e.Message), Logging.LogLevel.Error);
                throw e;
            }
        }