/// <inheritdoc /> public async IAsyncEnumerable <ChangesFeedResponseResult <TSource> > GetContinuousChangesAsync(ChangesFeedOptions options, ChangesFeedFilter filter, [EnumeratorCancellation] CancellationToken cancellationToken) { var infiniteTimeout = TimeSpan.FromMilliseconds(Timeout.Infinite); IFlurlRequest request = NewRequest() .WithTimeout(infiniteTimeout) .AppendPathSegment("_changes") .SetQueryParam("feed", "continuous"); if (options != null) { request = request.ApplyQueryParametersOptions(options); } await using Stream stream = filter == null ? await request.GetStreamAsync(cancellationToken, HttpCompletionOption.ResponseHeadersRead) .ConfigureAwait(false) : await request.QueryContinuousWithFilterAsync <TSource>(_queryProvider, filter, cancellationToken) .ConfigureAwait(false); await foreach (var line in stream.ReadLinesAsync(cancellationToken)) { if (string.IsNullOrEmpty(line)) { continue; } ChangesFeedResponseResult <TSource> result = JsonConvert.DeserializeObject <ChangesFeedResponseResult <TSource> >(line); yield return(result); } }
/// <summary> /// Returns changes as they happen. A continuous feed stays open and connected to the database until explicitly closed. /// </summary> /// <remarks> /// To stop receiving changes call <c>Cancel()</c> on the <c>CancellationTokenSource</c> used to create the <c>CancellationToken</c>. /// </remarks> /// <param name="options">Options to apply to the request.</param> /// <param name="filter">A filter to apply to the result.</param> /// <param name="cancellationToken">A cancellation token to stop receiving changes.</param> /// <returns></returns> public async IAsyncEnumerable <ChangesFeedResponseResult <TSource> > GetContinuousChangesAsync(ChangesFeedOptions options, ChangesFeedFilter filter, [EnumeratorCancellation] CancellationToken cancellationToken) { var infiniteTimeout = TimeSpan.FromMilliseconds(Timeout.Infinite); IFlurlRequest request = NewRequest() .WithTimeout(infiniteTimeout) .AppendPathSegment("_changes") .SetQueryParam("feed", "continuous"); SetChangesFeedOptions(request, options); await using Stream stream = filter == null ? await request.GetStreamAsync(cancellationToken, HttpCompletionOption.ResponseHeadersRead) .ConfigureAwait(false) : await QueryContinuousWithFilterAsync(request, filter, cancellationToken) .ConfigureAwait(false); using var reader = new StreamReader(stream); while (!cancellationToken.IsCancellationRequested && !reader.EndOfStream) { if (cancellationToken.IsCancellationRequested) { continue; } var line = await reader.ReadLineAsync().ConfigureAwait(false); if (!string.IsNullOrEmpty(line)) { yield return(JsonConvert.DeserializeObject <ChangesFeedResponseResult <TSource> >(line)); } } }
protected async Task <JsonDocument> GetJson( IFlurlRequest request, CancellationToken cancellationToken) { var delta = DateTime.Now - _lastRequestTime; if (delta < RequestInterval) { await Task.Delay(delta, cancellationToken); } var result = await request.GetStreamAsync(cancellationToken); _lastRequestTime = DateTime.Now; return(await JsonDocument.ParseAsync(result, cancellationToken : cancellationToken)); }
/// <inheritdoc /> public async IAsyncEnumerable <ChangesFeedResponseResult <TSource> > GetContinuousChangesAsync(ChangesFeedOptions?options, ChangesFeedFilter?filter, [EnumeratorCancellation] CancellationToken cancellationToken) { var infiniteTimeout = TimeSpan.FromMilliseconds(Timeout.Infinite); IFlurlRequest request = NewRequest() .WithTimeout(infiniteTimeout) .AppendPathSegment("_changes") .SetQueryParam("feed", "continuous"); if (options != null) { request = request.ApplyQueryParametersOptions(options); } await using Stream stream = filter == null ? await request.GetStreamAsync(cancellationToken, HttpCompletionOption.ResponseHeadersRead) .ConfigureAwait(false) : await request.QueryContinuousWithFilterAsync <TSource>(_queryProvider, filter, cancellationToken) .ConfigureAwait(false); await foreach (var line in stream.ReadLinesAsync(cancellationToken)) { if (string.IsNullOrEmpty(line)) { continue; } MatchCollection matches = _feedChangeLineStartPattern.Matches(line); for (var i = 0; i < matches.Count; i++) { var startIndex = matches[i].Index; var endIndex = i < matches.Count - 1 ? matches[i + 1].Index : line.Length; var lineLength = endIndex - startIndex; var substring = line.Substring(startIndex, lineLength); yield return(JsonConvert.DeserializeObject <ChangesFeedResponseResult <TSource> >(substring)); } } }