Skip to content

Commit

Permalink
items-feed support (#28)
Browse files Browse the repository at this point in the history
Related to issue #20
  • Loading branch information
alanta authored Dec 28, 2020
1 parent 8c0b9fc commit aecd896
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 3 deletions.
19 changes: 19 additions & 0 deletions Kontent.Statiq.Tests/Tools/KontentSetupHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using FakeItEasy;
using Kentico.Kontent.Delivery.Abstractions;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Kontent.Statiq.Tests.Tools
{
Expand All @@ -15,6 +16,24 @@ public static IDeliveryClient WithFakeContent<TContent>(this IDeliveryClient cli

return client;
}

public static IDeliveryClient WithFakeContentFeed<TContent>(this IDeliveryClient client, params TContent[] content)
{
var response = A.Fake<IDeliveryItemsFeed<TContent>>();
var moreData = true;
A.CallTo(() => response.HasMoreResults).ReturnsLazily( _ => moreData );
A.CallTo(() => response.FetchNextBatchAsync()).ReturnsLazily(_ =>
{
moreData = false; // return a single batch
var data = A.Fake<IDeliveryItemsFeedResponse<TContent>>();
A.CallTo(() => data.Items).Returns(content);
return Task.FromResult(data);
});
A.CallTo(() => client.GetItemsFeed<TContent>(A<IEnumerable<IQueryParameter>>._))
.Returns(response);

return client;
}

public static IDeliveryClient WithFakeTaxonomy(this IDeliveryClient client, params ITaxonomyGroup[] taxonomies)
{
Expand Down
47 changes: 47 additions & 0 deletions Kontent.Statiq.Tests/When_using_the_items_feed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using FakeItEasy;
using FluentAssertions;
using Kentico.Kontent.Delivery.Abstractions;
using Kontent.Statiq.Tests.Models;
using Kontent.Statiq.Tests.Tools;
using Statiq.Common;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;

namespace Kontent.Statiq.Tests
{
public class When_using_the_items_feed
{
[Fact]
public async Task It_should_invoke_the_correct_endpoint()
{
// Arrange
var content = new Article
{
System = new TestContentItemSystemAttributes
{
Type = "article",
Id = "cf106f4e-30a4-42ef-b313-b8ea3fd3e5c5",
Language = "en-US",
Codename = "coffee_beverages_explained",
Name = "Coffee Beverages Explained",
LastModified = new DateTime(2019, 09, 18, 10, 58, 38, 917)
}
};

var deliveryClient = A.Fake<IDeliveryClient>()
.WithFakeContentFeed(content);

var sut = new Kontent<Article>(deliveryClient)
.WithItemsFeed();

// Act
var docs = await sut.ExecuteAsync(A.Fake<IExecutionContext>());

// Assert
docs.Should().HaveCount(1);
A.CallTo(() => deliveryClient.GetItemsFeed<Article>(A<IEnumerable<IQueryParameter>>._)).MustHaveHappenedOnceExactly();
}
}
}
41 changes: 38 additions & 3 deletions Kontent.Statiq/Kontent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public sealed class Kontent<TContentModel> : Module where TContentModel : class
internal Func<TContentModel, string>? GetContent { get; set; }

private readonly IDeliveryClient _client;
private bool _useItemFeed;

internal List<IQueryParameter> QueryParameters { get; } = new List<IQueryParameter>();

Expand All @@ -29,16 +30,50 @@ public sealed class Kontent<TContentModel> : Module where TContentModel : class
public Kontent(IDeliveryClient client)
{
_client = client ?? throw new ArgumentNullException(nameof(client), $"{nameof(client)} must not be null");
_useItemFeed = false;
}

/// <summary>
/// Use the items-feed endpoint instead of the items endpoint.
/// <para>Use this when you have a lot of content and get a bad request response.</para>
/// </summary>
/// <returns>The module.</returns>
public Kontent<TContentModel> WithItemsFeed()
{
_useItemFeed = true;
return this;
}

/// <inheritdoc />
protected override async Task<IEnumerable<IDocument>> ExecuteContextAsync(IExecutionContext context)
{
var items = await _client.GetItemsAsync<TContentModel>(QueryParameters);
if (_useItemFeed)
{
var feed = _client.GetItemsFeed<TContentModel>(QueryParameters);

var documents = new List<IDocument>();

while (feed.HasMoreResults)
{
var nextBatch = await feed.FetchNextBatchAsync();

var documentTasks = nextBatch.Items.Select(item => KontentDocumentHelpers.CreateDocument(context, item, GetContent)).ToArray();

var documentBatch = await Task.WhenAll(documentTasks);

documents.AddRange(documentBatch);
}

return documents;
}
else
{
var items = await _client.GetItemsAsync<TContentModel>(QueryParameters);

var documentTasks = items.Items.Select(item => KontentDocumentHelpers.CreateDocument(context, item, GetContent)).ToArray();
var documentTasks = items.Items.Select(item => KontentDocumentHelpers.CreateDocument(context, item, GetContent)).ToArray();

return await Task.WhenAll(documentTasks);
return await Task.WhenAll(documentTasks);
}
}
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ Implement and register a link resolver. See the [Kontent docs](https://github.co
Make sure all your classes are in a namespace.

> A _Bad request_ occurs while loading data from Kontent
If you have a lot of content items, use the items-feed by calling `.WithItemsFeed()` method on the Kontent module.

## How do I build this repo?

You'll need a .NET Core development setup: Windows, Mac, Linux with VisualStudio, VS Code or Rider.
Expand Down

0 comments on commit aecd896

Please sign in to comment.