public async Task Changes() { using (var client = new CouchClient("http://localhost:5984")) { IEnumerable <string> dbs = await client.GetDatabasesNamesAsync().ConfigureAwait(false); CouchDatabase <Rebel> rebels = client.GetDatabase <Rebel>(); if (dbs.Contains(rebels.Database)) { await client.DeleteDatabaseAsync <Rebel>().ConfigureAwait(false); } rebels = await client.CreateDatabaseAsync <Rebel>().ConfigureAwait(false); Rebel luke = await rebels.CreateAsync(new Rebel { Name = "Luke", Age = 19 }).ConfigureAwait(false); Assert.Equal("Luke", luke.Name); var options = new ChangesFeedOptions { IncludeDocs = true }; var filter = ChangesFeedFilter.Selector <Rebel>(r => r.Name == "Luke" && r.Age == 19); var changesResult = await rebels.GetChangesAsync(options, filter); Assert.NotEmpty(changesResult.Results); Assert.Equal(changesResult.Results[0].Id, luke.Id); await client.DeleteDatabaseAsync <Rebel>().ConfigureAwait(false); } }
public void ToQueryParameters_WhenAllPropertyNotDefault_Return_AllProperties() { // Arrange var options = new ChangesFeedOptions { Conflicts = true, Descending = true, Filter = Guid.NewGuid().ToString(), Heartbeat = 1, IncludeDocs = true, Attachments = true, AttachEncodingInfo = true, Limit = 1, Since = Guid.NewGuid().ToString(), Style = ChangesFeedStyle.AllDocs, Timeout = 1, View = Guid.NewGuid().ToString(), SeqInterval = 1 }; // Act var parameters = OptionsHelper.ToQueryParameters(options); // Assert Assert.Equal(13, parameters.Count()); }
public async Task GetContinuousChangesAsync_WithOptions() { using var httpTest = new HttpTest(); // Arrange var tokenSource = new CancellationTokenSource(); var docId = SetFeedResponse(httpTest); httpTest.RespondWithJson(new { ok = true }); var options = new ChangesFeedOptions { Attachments = true }; // Act await foreach (var change in _rebels.GetContinuousChangesAsync(options, null, tokenSource.Token)) { Assert.Equal(docId, change.Id); tokenSource.Cancel(); } // Assert httpTest .ShouldHaveCalled("http://localhost/rebels/_changes") .WithQueryParamValue("feed", "continuous") .WithQueryParamValue("attachments", true) .WithVerb(HttpMethod.Get); }
public void ToQueryParameters_WhenDefault_Return_NoProperties() { // Arrange var options = new ChangesFeedOptions(); // Act var parameters = OptionsHelper.ToQueryParameters(options); // Assert Assert.Empty(parameters); }
private void SetChangesFeedOptions(IFlurlRequest request, ChangesFeedOptions options) { if (options == null) { return; } foreach (var(name, value) in options.ToQueryParameters()) { _ = request.SetQueryParam(name, value); } }
/// <summary> /// Returns a sorted list of changes made to documents in the database. /// </summary> /// <remarks> /// Only the most recent change for a given document is guaranteed to be provided. /// </remarks> /// <param name="options">Options to apply to the request.</param> /// <param name="filter">A filter to apply to the result.</param> /// <returns></returns> public async Task <ChangesFeedResponse <TSource> > GetChangesAsync(ChangesFeedOptions options = null, ChangesFeedFilter filter = null) { IFlurlRequest request = NewRequest() .AppendPathSegment("_changes"); if (options?.LongPoll == true) { _ = request.SetQueryParam("feed", "longpoll"); } SetChangesFeedOptions(request, options); return(filter == null ? await request.GetJsonAsync <ChangesFeedResponse <TSource> >() .ConfigureAwait(false) : await QueryWithFilterAsync(request, filter) .ConfigureAwait(false)); }
public async Task ContinuousChanges() { using (var client = new CouchClient("http://localhost:5984")) { IEnumerable <string> dbs = await client.GetDatabasesNamesAsync().ConfigureAwait(false); CouchDatabase <Rebel> rebels = client.GetDatabase <Rebel>(); if (dbs.Contains(rebels.Database)) { await client.DeleteDatabaseAsync <Rebel>().ConfigureAwait(false); } rebels = await client.CreateDatabaseAsync <Rebel>().ConfigureAwait(false); Rebel luke = await rebels.CreateAsync(new Rebel { Name = "Luke", Age = 19 }).ConfigureAwait(false); Assert.Equal("Luke", luke.Name); luke.Surname = "Vader"; _ = Task.Run(async() => { await Task.Delay(2000); await rebels.CreateOrUpdateAsync(luke); }); var ids = new[] { luke.Id }; var option = new ChangesFeedOptions { Since = "now" }; var filter = ChangesFeedFilter.DocumentIds(ids); using var cancelSource = new CancellationTokenSource(); await foreach (var _ in rebels.GetContinuousChangesAsync(option, filter, cancelSource.Token)) { cancelSource.Cancel(); } await client.DeleteDatabaseAsync <Rebel>().ConfigureAwait(false); } }
public async Task GetChangesAsync_WithOptions() { using var httpTest = new HttpTest(); // Arrange SetFeedResponse(httpTest); httpTest.RespondWithJson(new { ok = true }); var options = new ChangesFeedOptions { LongPoll = true, Attachments = true }; // Act var newR = await _rebels.GetChangesAsync(options); // Assert httpTest .ShouldHaveCalled("http://localhost/rebels/_changes") .WithQueryParamValue("feed", "longpoll") .WithQueryParamValue("attachments", true) .WithVerb(HttpMethod.Get); }
/// <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)); } } }