private async Task ReadStreamAsync(Stream stream) { var encoder = new UTF8Encoding(); var streamReadcancellationTokenSource = new CancellationTokenSource(); _log.Debug($"Reading stream ...."); while (!_cancellationTokenSource.IsCancellationRequested && IsConnected()) { if (stream.CanRead && IsConnected()) { var buffer = new byte[BufferSize]; var timeoutTask = _wrapperAdapter.TaskDelay(ReadTimeout * 1000); var streamReadTask = stream.ReadAsync(buffer, 0, BufferSize, streamReadcancellationTokenSource.Token); // Creates a task that will complete when any of the supplied tasks have completed. // Returns: A task that represents the completion of one of the supplied tasks. The return task's Result is the task that completed. var finishedTask = await _wrapperAdapter.WhenAny(streamReadTask, timeoutTask); if (finishedTask == timeoutTask) { throw new Exception($"Streaming read time out after {ReadTimeout} seconds."); } int len = streamReadTask.Result; if (len == 0) { throw new Exception($"Streaming end of the file."); } var notificationString = encoder.GetString(buffer, 0, len); _log.Debug($"Read stream encoder buffer: {notificationString}"); if (notificationString != KeepAliveResponse && IsConnected()) { var lines = notificationString.Split(new[] { "\n\n" }, StringSplitOptions.None); foreach (var line in lines) { try { if (!string.IsNullOrEmpty(line)) { var eventData = _notificationParser.Parse(line); if (eventData != null) { DispatchEvent(eventData); } } } catch (NotificationErrorException ex) { _log.Debug($"Notification error: {ex.Message}. Status Server: {ex.Notification.StatusCode}."); if (ex.Notification.StatusCode >= 40140 && ex.Notification.StatusCode <= 40149) { Disconnect(reconnect: true); } else if (ex.Notification.StatusCode >= 40000 && ex.Notification.StatusCode <= 49999) { Disconnect(); } } catch (Exception ex) { _log.Debug($"Error during event parse: {ex.Message}"); } } } } } _log.Debug($"Stop read stream"); }
private async Task ReadStreamAsync(Stream stream, CancellationToken cancellationToken) { _log.Debug($"Reading stream ...."); try { while (!cancellationToken.IsCancellationRequested && (IsConnected() || _firstEvent)) { if (stream.CanRead && (IsConnected() || _firstEvent)) { Array.Clear(_buffer, 0, BufferSize); var timeoutToken = new CancellationTokenSource(); var timeoutTask = _wrapperAdapter.TaskDelay(ReadTimeoutMs, timeoutToken.Token); var streamReadTask = stream.ReadAsync(_buffer, 0, BufferSize, cancellationToken); // Creates a task that will complete when any of the supplied tasks have completed. // Returns: A task that represents the completion of one of the supplied tasks. The return task's Result is the task that completed. var finishedTask = await _wrapperAdapter.WhenAny(streamReadTask, timeoutTask); try { if (finishedTask == timeoutTask) { throw new ReadStreamException(SSEClientActions.RETRYABLE_ERROR, $"Streaming read time out after {ReadTimeoutMs} seconds."); } int len = streamReadTask.Result; if (len == 0) { throw new ReadStreamException(SSEClientActions.RETRYABLE_ERROR, "Streaming end of the file."); } var notificationString = _encoder.GetString(_buffer, 0, len); _log.Debug($"Read stream encoder buffer: {notificationString}"); if (_firstEvent) { ProcessFirtsEvent(notificationString); } if (notificationString != KeepAliveResponse && IsConnected()) { var lines = notificationString.Split(_notificationSplitArray, StringSplitOptions.None); foreach (var line in lines) { if (!string.IsNullOrEmpty(line)) { var eventData = _notificationParser.Parse(line); if (eventData != null) { if (eventData.Type == NotificationType.ERROR) { var notificationError = (NotificationError)eventData; ProcessErrorNotification(notificationError); } else { DispatchEvent(eventData); } } } } } } finally { _log.Debug("Disposing Stream Read Task..."); timeoutToken.Cancel(); timeoutToken.Dispose(); _wrapperAdapter.TaskWaitAndDispose(timeoutTask, streamReadTask, finishedTask); } } } } catch (ReadStreamException ex) { _log.Debug("ReadStreamException", ex); throw ex; } catch (Exception ex) { if (!cancellationToken.IsCancellationRequested) { _log.Debug("Stream ended abruptly, proceeding to reconnect.", ex); throw new ReadStreamException(SSEClientActions.RETRYABLE_ERROR, ex.Message); } _log.Debug("Stream Token cancelled.", ex); } finally { _log.Debug($"Stop read stream"); } }