Skip to content

Commit

Permalink
Simplified extending pagination pipelines. (#6921)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Feb 19, 2024
1 parent 85c1d03 commit 1f34422
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/HotChocolate/Core/src/Abstractions/SetState.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace HotChocolate;

public delegate void SetState<T>(T value);
public delegate void SetState<in T>(T value);

public delegate void SetState(object value);
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,9 @@ public static class WellKnownContextData
/// Type key to access the internal schema options.
/// </summary>
public const string InternalSchemaOptions = "HotChocolate.Types.InternalSchemaOptions";

/// <summary>
/// Type key to access the paging arguments in the local resolver state.
/// </summary>
public const string PagingArguments = "HotChocolate.Types.PagingArguments";
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#nullable enable

namespace HotChocolate.Types.Pagination;

/// <summary>
/// The cursor paging arguments are used to specify the
/// paging behavior of the cursor based paging handler.
/// </summary>
#if NET6_0_OR_GREATER
public readonly record struct CursorPagingArguments
#else
public readonly struct CursorPagingArguments
#endif
{
/// <summary>
/// Initializes a new instance of <see cref="CursorPagingArguments"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ public void ValidateContext(IResolverContext context)
}
}

async ValueTask<IPage> IPagingHandler.SliceAsync(
IResolverContext context,
object source)
public void PublishPagingArguments(IResolverContext context)
{
var first = context.ArgumentValue<int?>(CursorPagingArgumentNames.First);
var last = AllowBackwardPagination
Expand All @@ -110,7 +108,15 @@ async ValueTask<IPage> IPagingHandler.SliceAsync(
AllowBackwardPagination
? context.ArgumentValue<string?>(CursorPagingArgumentNames.Before)
: null);

context.SetLocalState(WellKnownContextData.PagingArguments, arguments);
}

async ValueTask<IPage> IPagingHandler.SliceAsync(
IResolverContext context,
object source)
{
var arguments = context.GetLocalState<CursorPagingArguments>(WellKnownContextData.PagingArguments);
return await SliceAsync(context, source, arguments).ConfigureAwait(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,19 @@ public void ValidateContext(IResolverContext context)
}
}

async ValueTask<IPage> IPagingHandler.SliceAsync(
IResolverContext context,
object source)
public void PublishPagingArguments(IResolverContext context)
{
var skip = context.ArgumentValue<int?>(OffsetPagingArgumentNames.Skip);
var take = context.ArgumentValue<int?>(OffsetPagingArgumentNames.Take);
var arguments = new OffsetPagingArguments(skip, take ?? DefaultPageSize);
context.SetLocalState(WellKnownContextData.PagingArguments, arguments);
}

async ValueTask<IPage> IPagingHandler.SliceAsync(
IResolverContext context,
object source)
{
var arguments =context.GetLocalState<OffsetPagingArguments>(WellKnownContextData.PagingArguments);
return await SliceAsync(context, source, arguments).ConfigureAwait(false);
}

Expand Down
22 changes: 22 additions & 0 deletions src/HotChocolate/Core/src/Types/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
using HotChocolate.Resolvers;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;
using HotChocolate.Types.Interceptors;
using HotChocolate.Types.Introspection;
using HotChocolate.Types.Pagination;
using HotChocolate.Utilities;

#nullable enable
Expand Down Expand Up @@ -451,4 +453,24 @@ public ISchemaBuilder TryAddTypeInterceptor(TypeInterceptor interceptor)
/// Returns a new instance of <see cref="SchemaBuilder"/>.
/// </returns>
public static SchemaBuilder New() => new();

private sealed class CopyOptions : TypeInterceptor
{
public override void OnBeforeCompleteType(ITypeCompletionContext completionContext, DefinitionBase definition)
{
if (definition is SchemaTypeDefinition schemaDef)
{
var key = typeof(PagingOptions).FullName!;

if (completionContext.DescriptorContext.ContextData.TryGetValue(key, out var value))
{
schemaDef.ContextData[key] = value;
}
else
{
schemaDef.ContextData[key] = new PagingOptions();
}
}
}
}
}
11 changes: 11 additions & 0 deletions src/HotChocolate/Core/src/Types/Types/Pagination/IPagingHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

namespace HotChocolate.Types.Pagination;

/// <summary>
/// The paging handler is used in the paging middleware to abstract the actual paging logic.
/// </summary>
public interface IPagingHandler
{
/// <summary>
Expand All @@ -19,6 +22,14 @@ public interface IPagingHandler
/// </exception>
void ValidateContext(IResolverContext context);

/// <summary>
/// Publish Paging Arguments to local state.
/// </summary>
/// <param name="context">
/// The current resolver context.
/// </param>
void PublishPagingArguments(IResolverContext context);

/// <summary>
/// Slices the <paramref name="source"/> and returns a page from it.
/// </summary>
Expand Down
10 changes: 6 additions & 4 deletions src/HotChocolate/Core/src/Types/Types/Pagination/PagingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,12 @@ IExtendedType ResolveType()
}

private static FieldMiddleware CreateMiddleware(
IPagingHandler handler) =>
FieldClassMiddlewareFactory.Create(
typeof(PagingMiddleware),
(typeof(IPagingHandler), handler));
IPagingHandler handler)
=> next =>
{
var middleware = new PagingMiddleware(next, handler);
return context => middleware.InvokeAsync(context);
};

public static IExtendedType GetSchemaType(
IDescriptorContext context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ public class PagingMiddleware(FieldDelegate next, IPagingHandler pagingHandler)
private readonly IPagingHandler _pagingHandler = pagingHandler ??
throw new ArgumentNullException(nameof(pagingHandler));

public async Task InvokeAsync(IMiddlewareContext context)
public async ValueTask InvokeAsync(IMiddlewareContext context)
{
_pagingHandler.ValidateContext(context);
_pagingHandler.PublishPagingArguments(context);

await _next(context).ConfigureAwait(false);

// if the result is a field result we gonna unwrap it.
if (context.Result is IFieldResult fieldResult)
{
if (fieldResult.IsError)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public async Task TakeFirst()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -75,6 +76,7 @@ public async Task TakeLastSingle()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -110,6 +112,7 @@ public async Task TakeLast()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -148,12 +151,14 @@ public async Task TakeFirstAfter()

var pagingDetails = new CursorPagingArguments();
var context = new MockContext(pagingDetails);
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

pagingDetails = new CursorPagingArguments(after: connection.Info.StartCursor, first: 2);
context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -192,12 +197,14 @@ public async Task TakeLastBefore()

var pagingDetails = new CursorPagingArguments(first: 5);
var context = new MockContext(pagingDetails);
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

pagingDetails = new CursorPagingArguments(before: connection.Info.EndCursor, last: 2);
context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -238,6 +245,7 @@ public async Task HasNextPage_True()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand All @@ -260,6 +268,7 @@ public async Task HasNextPage_False()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand All @@ -280,12 +289,15 @@ public async Task HasPrevious_True()

var pagingDetails = new CursorPagingArguments(first: 1);
var context = new MockContext(pagingDetails);

pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

pagingDetails = new CursorPagingArguments(after: connection.Info.EndCursor, first: 2);
context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand All @@ -308,6 +320,7 @@ public async Task HasPrevious_False()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -339,6 +352,7 @@ public async Task Executable()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -388,6 +402,7 @@ public async Task Executable_Queryable()
var context = new MockContext(pagingDetails);

// act
pagingHandler.PublishPagingArguments(context);
var connection = (Connection)await pagingHandler.SliceAsync(context, list);

// assert
Expand Down Expand Up @@ -444,11 +459,8 @@ public IServiceProvider Services
set => throw new NotImplementedException();
}

public IImmutableDictionary<string, object?> LocalContextData
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
public IImmutableDictionary<string, object?> LocalContextData { get; set; } =
ImmutableDictionary<string, object?>.Empty;

public CancellationToken RequestAborted => default;

Expand Down

0 comments on commit 1f34422

Please sign in to comment.