Пример #1
0
        private async Task ReadLoop(HttpResponseMessage httpResponse, CancellationToken token)
        {
            try
            {
                await Task.Run(async() =>
                {
                    using (httpResponse)
                    {
                        using (var content = await httpResponse.Content.ReadAsStreamAsync())
                        {
                            using (var sr = new StreamReader(content))
                            {
                                bool?isFirstTimeRetrieval = null;
                                #region ----- While true -----
                                while (true)
                                {
                                    CancellationToken.Token.ThrowIfCancellationRequested();

                                    string line;
                                    #region ----- Read line
                                    line = await sr.ReadLineAsync();
                                    if (string.IsNullOrEmpty(line))
                                    {
                                        continue;
                                    }
                                    if (OnEventStreaming != null)
                                    {
                                        OnEventStreaming(this, new EventStreamingEventArgs(line));
                                    }
                                    #endregion

                                    string eventName;
                                    string dataLine;
                                    #region ----- Read event name / data line
                                    if (!line.StartsWith("event: "))
                                    {
                                        var message = string.Format("Expecting line to start with 'event: ', line: {0}", line);
                                        Debug.WriteLine("[StreamingResponse.Exception] " + message);
                                        throw new FirebaseEventStreamingException(null, null, message);
                                    }
                                    eventName = line.Substring(7);
                                    dataLine  = await sr.ReadLineAsync();
                                    if (OnEventStreamingResponseRaw != null)
                                    {
                                        OnEventStreamingResponseRaw(this, new EventStreamingResponseRawEventArgs(eventName, dataLine));
                                    }
                                    if (EXTRA_DEBUG)
                                    {
                                        Debug.WriteLine(string.Format("[StreamingResponse.Content] {0} | {1}", line, dataLine));
                                    }
                                    #endregion

                                    if (eventName == "keep-alive")
                                    {
                                    }
                                    else if (eventName == "put" || eventName == "patch")
                                    {
                                        if (dataLine.StartsWith("data: "))
                                        {
                                            if (OnEventStreamingResponse == null &&
                                                OnObjectRootPatchReceived == null &&
                                                OnObjectPropertyPatchReceived == null)
                                            {
                                                return;                                           // Not watching
                                            }
                                            #region ----- Read path / data
                                            var dataRecord = dataLine.Substring(6);
                                            var jData      = JObject.Parse(dataRecord);

                                            var pathToken = jData["path"];
                                            if (pathToken == null)
                                            {
                                                var message = "Firebase stream response should contain a token 'path'.";
                                                Debug.WriteLine("[StreamingResponse.##### WARNING #####] " + message);
                                                throw new FirebaseEventStreamingException(eventName, dataRecord, message);
                                            }
                                            if (pathToken.Type != JTokenType.String)
                                            {
                                                var message = "Path token received in Firebase stream response is not of type String.";
                                                Debug.WriteLine("[StreamingResponse.##### WARNING #####] " + message);
                                                throw new FirebaseEventStreamingException(eventName, dataRecord, message);
                                            }

                                            JToken dataToken = jData["data"];
                                            if (dataToken == null)
                                            {
                                                var message = "Firebase stream response should contain a token 'data'.";
                                                Debug.WriteLine("[StreamingResponse.##### WARNING #####] " + message);
                                                throw new FirebaseEventStreamingException(eventName, dataRecord, message);
                                            }

                                            var responseData      = new EventStreamingResponseData((string)pathToken, dataToken);
                                            var jsonDataBeginning = responseData.Data.Substring(0, Math.Min(50, responseData.Data.Length)) + (responseData.Data.Length > 50 ? "..." : "");
                                            Debug.WriteLine(string.Format("[StreamingResponse.{0}] {1}", eventName, responseData.Path));
                                            Debug.WriteLine(string.Format("      ---> {0} <---", jsonDataBeginning));

                                            var response = new EventStreamingResponse(eventName, responseData);
                                            if (OnEventStreamingResponse != null)
                                            {
                                                OnEventStreamingResponse(this, new EventStreamingResponseEventArgs <T>(response));
                                            }
                                            #endregion

                                            #region ----- Deal with object data received
                                            var jsonPatch = _jsonPatchManager.GeneratePatchFrom(response);
                                            if (responseData.Path == "/" && eventName == "put")
                                            {
                                                isFirstTimeRetrieval = isFirstTimeRetrieval == null ? true : false;
                                                if (OnObjectRootPatchReceived != null)
                                                {
                                                    // var obj = _serializer.Deserialize<T>(responseData.Data);
                                                    OnObjectRootPatchReceived(this, jsonPatch, isFirstTimeRetrieval.Value);
                                                }
                                            }
                                            else if (OnObjectPropertyPatchReceived != null)
                                            {
                                                if (isFirstTimeRetrieval == null)
                                                {
                                                    var message = "Firebase streaming did not emit first time retrieval of object.";
                                                    Debug.WriteLine("[StreamingResponse.##### WARNING #####] " + message);
                                                    throw new FirebaseEventStreamingException(eventName, dataRecord, message);
                                                }
                                                OnObjectPropertyPatchReceived(this, jsonPatch);
                                            }
                                            #endregion
                                        }
                                    }
                                    else
                                    {
                                        Debug.WriteLine("[StreamingResponse.Exception] " + string.Format("Firebase stream response not handled. Event: {0} | Data: {1}", eventName, dataLine));
                                        throw new FirebaseEventStreamingException(eventName, dataLine, "Firebase stream response not handled.");
                                    }
                                }
                                #endregion ----- While true (end)
                            } // Using sr = StreamReader
                        }     // Using content
                    }         // Using httpResponse
                }, cancellationToken : token); // Task.Run
            }
            catch (Exception exceptionInLongRunningTask)
            {
                if (this.ExceptionHandler == null)
                {
                    throw;
                }
                this.ExceptionHandler(exceptionInLongRunningTask);
            }
        }