Skip to content

Commit 5ad0c35

Browse files
committed
Make DeliveryObservableProxy.EnumerateFeed async
1 parent 502d4e2 commit 5ad0c35

File tree

5 files changed

+78
-20
lines changed

5 files changed

+78
-20
lines changed

Kontent.Ai.Delivery.Rx.Tests/Kontent.Ai.Delivery.Rx.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<PackageReference Include="FakeItEasy" Version="8.0.0" />
4848
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
4949
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
50+
<PackageReference Include="System.Reactive" Version="6.0.1" />
5051
<PackageReference Include="xunit" Version="2.9.2" />
5152
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
5253
<PrivateAssets>all</PrivateAssets>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reactive.Linq;
4+
using Kontent.Ai.Delivery.Abstractions;
5+
6+
namespace Kontent.Ai.Delivery.Rx;
7+
8+
/// <summary>
9+
/// Provides extension methods for working with <see cref="IDeliveryItemsFeed{T}"/> instances in a reactive programming context.
10+
/// </summary>
11+
public static class DeliveryItemsFeedExtensions
12+
{
13+
/// <summary>
14+
/// Converts an <see cref="IDeliveryItemsFeed{T}"/> into an <see cref="IObservable{T}"/> sequence.
15+
/// </summary>
16+
/// <typeparam name="T">The type of content items in the feed.</typeparam>
17+
/// <param name="feed">The <see cref="IDeliveryItemsFeed{T}"/> instance to convert.</param>
18+
/// <returns>
19+
/// An <see cref="IObservable{T}"/> sequence that emits items retrieved from the feed.
20+
/// If the feed is <c>null</c>, an empty observable sequence is returned.
21+
/// </returns>
22+
/// <exception cref="Exception">
23+
/// Propagates any exceptions that occur during the retrieval of items from the feed.
24+
/// </exception>
25+
public static IObservable<T> ToObservable<T>(this IDeliveryItemsFeed<T> feed) where T : class
26+
{
27+
if (feed == null)
28+
{
29+
return Observable.Empty<T>();
30+
}
31+
return Observable.Create<T>(async observer =>
32+
{
33+
try
34+
{
35+
await foreach (var item in EnumerateFeed(feed))
36+
{
37+
observer.OnNext(item);
38+
}
39+
observer.OnCompleted();
40+
}
41+
catch (Exception ex)
42+
{
43+
observer.OnError(ex);
44+
}
45+
});
46+
}
47+
48+
private static async IAsyncEnumerable<T> EnumerateFeed<T>(IDeliveryItemsFeed<T> feed) where T : class
49+
{
50+
while (feed.HasMoreResults)
51+
{
52+
var batch = await feed.FetchNextBatchAsync();
53+
foreach (var contentItem in batch.Items)
54+
{
55+
yield return contentItem;
56+
}
57+
}
58+
}
59+
}

Kontent.Ai.Delivery.Rx/DeliveryObservableProxy.cs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Collections.Generic;
33
using System.Reactive.Disposables;
44
using System.Reactive.Linq;
5+
using System.Reactive;
6+
using System.Threading.Tasks;
57
using Kontent.Ai.Delivery.Abstractions;
68

79
namespace Kontent.Ai.Delivery.Rx
@@ -104,8 +106,7 @@ public IObservable<T> GetItemsFeedObservable<T>(params IQueryParameter[] paramet
104106
/// <returns>The <see cref="IObservable{T}"/> that represents the content items. If no query parameters are specified, all content items are returned.</returns>
105107
public IObservable<T> GetItemsFeedObservable<T>(IEnumerable<IQueryParameter> parameters) where T : class
106108
{
107-
var feed = DeliveryClient?.GetItemsFeed<T>(parameters);
108-
return feed == null ? null : EnumerateFeed(feed)?.ToObservable();
109+
return DeliveryClient?.GetItemsFeed<T>(parameters).ToObservable();
109110
}
110111

111112
/// <summary>
@@ -127,8 +128,7 @@ public IObservable<IUsedInItem> GetItemUsedInObservable(string codename, params
127128
/// <returns>The <see cref="IObservable{IUsedInItem}"/> that represents the parent content items for the specified content item. If no query parameters are specified, parents in default language are returned.</returns>
128129
public IObservable<IUsedInItem> GetItemUsedInObservable(string codename, IEnumerable<IQueryParameter> parameters)
129130
{
130-
var feed = DeliveryClient?.GetItemUsedIn(codename, parameters);
131-
return feed == null ? null : EnumerateFeed(feed)?.ToObservable();
131+
return DeliveryClient?.GetItemUsedIn(codename, parameters).ToObservable();
132132
}
133133

134134
/// <summary>
@@ -150,8 +150,7 @@ public IObservable<IUsedInItem> GetAssetUsedInObservable(string codename, params
150150
/// <returns>The <see cref="IObservable{IUsedInItem}"/> that represents the parent content items for the specified content item. If no query parameters are specified, parents in default language are returned.</returns>
151151
public IObservable<IUsedInItem> GetAssetUsedInObservable(string codename, IEnumerable<IQueryParameter> parameters)
152152
{
153-
var feed = DeliveryClient?.GetAssetUsedIn(codename, parameters);
154-
return feed == null ? null : EnumerateFeed(feed)?.ToObservable();
153+
return DeliveryClient?.GetAssetUsedIn(codename, parameters).ToObservable();
155154
}
156155

157156
/// <summary>
@@ -246,17 +245,6 @@ public IObservable<ILanguage> GetLanguagesObservable(params IQueryParameter[] pa
246245

247246
#endregion
248247
#region "Private methods"
249-
private static IEnumerable<T> EnumerateFeed<T>(IDeliveryItemsFeed<T> feed) where T : class
250-
{
251-
while (feed.HasMoreResults)
252-
{
253-
foreach (var contentItem in feed.FetchNextBatchAsync().Result.Items)
254-
{
255-
yield return contentItem;
256-
}
257-
}
258-
}
259-
260248
private static IObservable<T> GetObservableOfOne<T>(Func<T> responseFactory)
261249
{
262250
return Observable.Create((IObserver<T> observer) =>

Kontent.Ai.Delivery.Rx/Kontent.Ai.Delivery.Rx.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525

2626
<ItemGroup>
2727
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
28-
<PackageReference Include="System.Reactive" Version="5.0.0" />
28+
<PackageReference Include="System.Reactive" Version="6.0.1" />
2929
<PackageReference Include="Microsoft.Sourcelink.Github" Version="1.1.1" PrivateAssets="All" />
30-
<None Include="../README.md" Pack="true" PackagePath=""/>
31-
<None Include="../kai-logo-symbol-color-rgb.png" Pack="true" PackagePath=""/>
30+
<None Include="../README.md" Pack="true" PackagePath="" />
31+
<None Include="../kai-logo-symbol-color-rgb.png" Pack="true" PackagePath="" />
3232
</ItemGroup>
3333

3434
<ItemGroup>

Kontent.Ai.Delivery/DeliveryClient.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ public async Task<IDeliverySyncResponse> GetSyncAsync(string continuationToken)
372372
/// <returns>The <see cref="DeliveryUsedInItems"/> instance that can be used to enumerate through content item parents for the specified item codename. If no query parameters are specified, default language parents are enumerated.</returns>
373373
public IDeliveryItemsFeed<IUsedInItem> GetItemUsedIn(string codename, IEnumerable<IQueryParameter> parameters = null)
374374
{
375+
if (codename == null)
376+
{
377+
throw new ArgumentNullException(nameof(codename), "The codename of a content item is not specified.");
378+
}
379+
375380
ValidateUsedInParameters(parameters);
376381
var endpointUrl = UrlBuilder.GetItemUsedInUrl(codename, parameters);
377382

@@ -386,6 +391,11 @@ public IDeliveryItemsFeed<IUsedInItem> GetItemUsedIn(string codename, IEnumerabl
386391
/// <returns>The <see cref="DeliveryUsedInItems"/> instance that can be used to enumerate through asset parents for the specified asset codename. If no query parameters are specified, default language parents are enumerated.</returns>
387392
public IDeliveryItemsFeed<IUsedInItem> GetAssetUsedIn(string codename, IEnumerable<IQueryParameter> parameters = null)
388393
{
394+
if (codename == null)
395+
{
396+
throw new ArgumentNullException(nameof(codename), "The codename of an asset is not specified.");
397+
}
398+
389399
ValidateUsedInParameters(parameters);
390400
var endpointUrl = UrlBuilder.GetAssetUsedInUrl(codename, parameters);
391401

0 commit comments

Comments
 (0)