-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Feature Proposal: "Done for You" Pagination with IAsyncEnumerable
Summary
Enhance the OnspringClient by introducing methods that utilize the IAsyncEnumerable<T> type to handle automatic pagination for endpoints that return paged responses. This feature will simplify working with paginated data by abstracting the pagination logic away from the user, allowing developers to consume all items from an endpoint using asynchronous enumeration.
Note
The IAsyncEnumerable<T> interface was introduced in C#8 and in order to allow using this feature in packages such as ours that target both netstandard2.0 and netstandard2.1 Microsoft publishes this package that you can include as a dependency to use this feature.
Motivation
Currently, working with paginated responses from the Onspring API requires developers to manually handle pagination by iterating over pages, making multiple API calls, and aggregating results. This approach adds complexity and boilerplate code, which could be avoided by leveraging IAsyncEnumerable<T> for automatic pagination.
Introducing these methods will:
- Simplify developer workflows by abstracting pagination logic.
- Reduce boilerplate code required to interact with paginated endpoints.
- Enable seamless integration with modern .NET async programming patterns (e.g.,
await foreach).
Proposed Solution
Add new methods to the OnspringClient that return IAsyncEnumerable<T> for endpoints that support paginated responses. These methods will:
- Automatically handle fetching additional pages until all data is retrieved.
- Stream results back to the caller using the
IAsyncEnumerable<T>type.
For example, if the existing method to fetch a page of apps is:
Task<ApiResponse<GetPagedAppsResponse>> GetAppsAsync(PagingRequest pagingRequest = null);The proposed method would look like:
IAsyncEnumerable<ApiResponse<GetPagedAppsResponse>> GetAllAppsAsync(int pageSize = 50);Usage Example
var appsResponses = onspringClient.GetAllAppsAsync();
await foreach (var response in appsResponses)
{
if (response.IsSuccessful)
{
foreach (var app in response.Value.Items)
{
Console.WriteLine($"{app.Id}, {app.Name}");
}
}
else
{
Console.WriteLine($"Error: {response.Message}");
}
}Implementation Details
- Add internal helper method to
OnspringClientto encapsulate the pagination logic. - Add methods to
OnspringClientto support fetching all pages of particular entities
Example Helper Implementation
private async IAsyncEnumerable<ApiResponse<T>> GetAllPagesAsync<T>(Func<int, Task<ApiResponse<T>>> callback) where T : PagedResponse
{
var initialResponse = await callback(1);
yield return initialResponse;
var totalPages = initialResponse.Value.TotalPages;
var nextPage = initialResponse.Value.PageNumber + 1;
while (nextPage <= totalPages)
{
var response = await callback(nextPage);
nextPage++;
yield return response;
}
}Impact
This feature adds new methods and does not alter existing ones. The new methods would essentially call those that already exist but handle paging through the responses and yielding each response up one at a time.
This would necessitate creating a base PagedResponse model that we then extend from to derive the existing PagedResponse<T> model, but this change is low risk.
Alternatives Considered
- Continue requiring users to handle pagination manually.
- Introduce helper utilities outside of the
OnspringClientto handle pagination. However, embedding this functionality directly in the client simplifies usage and improves the developer experience.
Additional Context
This feature aligns with modern .NET development practices, leveraging IAsyncEnumerable<T> to provide more intuitive and efficient data processing. It will enhance the usability of the SDK and make it more appealing for developers integrating with Onspring.