-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Why make this change? This change allows users to use the runtime config to provide limits on the number of records that can be retrieved through paginated calls. It also gives them the ability to define a default size which will be the size returned when no pagination input is given (no first in case of graphql and no limit in case of rest calls). ## What is this change? It adds the nullable paginationoptions property to runtimeoptions of runtimeConfig. Default page size is set to 100. Max page size is set to 100,000 ( can be altered by the user in their runtimeconfig). A call with -1 pagination input will result in max page size records being returned. Any call with a pagination number higher than max page size will be rejected with bad request. In config: default-page-size is an integer default-page-size default is 100 default-page-size value -1 means "same as max-page-size" default-page-size value 0 is an error default-page-size value less than -1 is an error default-page-size value more than than max-page-size is an error max-page-size is an integer max-page-size default is 100,000 max-page-size value -1 means "same as int.MaxValue" max-page-size value 0 is an error max-page-size value less than -1 is an error max-page-size value more than int.MaxValue is an error In a query (REST or GQL): $first=-1 means "whatever the max-page-size value is" $first=less than -1 is an error $first=0 is an error $first=(any value more than max-page-size) is an error Sample configuration file: ```json { "runtime": { "pagination": { "default-page-size": -1, "max-page-size": 1233 } } } ``` ## How was this tested? 1. For default page value of 100, invalid page value of 0 or <-1 the existing test cases should cover. 2. Added tests for both GQL and REST for above conditions. --------- Co-authored-by: Sean Leonard <sean.leonard@microsoft.com> Co-authored-by: aaronburtle <93220300+aaronburtle@users.noreply.github.com>
- Loading branch information
1 parent
e660ba3
commit a999b62
Showing
21 changed files
with
476 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Diagnostics.CodeAnalysis; | ||
using System.Net; | ||
using System.Text.Json.Serialization; | ||
using Azure.DataApiBuilder.Service.Exceptions; | ||
|
||
namespace Azure.DataApiBuilder.Config.ObjectModel; | ||
|
||
/// <summary> | ||
/// Pagination options for the dab setup. | ||
/// Properties are nullable to support DAB CLI merge config | ||
/// expected behavior. | ||
/// </summary> | ||
public record PaginationOptions | ||
{ | ||
/// <summary> | ||
/// Default page size. | ||
/// </summary> | ||
public const uint DEFAULT_PAGE_SIZE = 100; | ||
|
||
/// <summary> | ||
/// Max page size. | ||
/// </summary> | ||
public const uint MAX_PAGE_SIZE = 100000; | ||
|
||
/// <summary> | ||
/// The default page size for pagination. | ||
/// </summary> | ||
[JsonPropertyName("default-page-size")] | ||
public int? DefaultPageSize { get; init; } = null; | ||
|
||
/// <summary> | ||
/// The max page size for pagination. | ||
/// </summary> | ||
[JsonPropertyName("max-page-size")] | ||
public int? MaxPageSize { get; init; } = null; | ||
|
||
[JsonConstructor] | ||
public PaginationOptions(int? DefaultPageSize = null, int? MaxPageSize = null) | ||
{ | ||
if (MaxPageSize is not null) | ||
{ | ||
ValidatePageSize((int)MaxPageSize); | ||
this.MaxPageSize = MaxPageSize == -1 ? Int32.MaxValue : (int)MaxPageSize; | ||
UserProvidedMaxPageSize = true; | ||
} | ||
else | ||
{ | ||
this.MaxPageSize = (int)MAX_PAGE_SIZE; | ||
} | ||
|
||
if (DefaultPageSize is not null) | ||
{ | ||
ValidatePageSize((int)DefaultPageSize); | ||
this.DefaultPageSize = DefaultPageSize == -1 ? (int)this.MaxPageSize : (int)DefaultPageSize; | ||
UserProvidedDefaultPageSize = true; | ||
} | ||
else | ||
{ | ||
this.DefaultPageSize = (int)DEFAULT_PAGE_SIZE; | ||
} | ||
|
||
if (this.DefaultPageSize > this.MaxPageSize) | ||
{ | ||
throw new DataApiBuilderException( | ||
message: "Pagination options invalid. The default page size cannot be greater than max page size", | ||
statusCode: HttpStatusCode.ServiceUnavailable, | ||
subStatusCode: DataApiBuilderException.SubStatusCodes.ConfigValidationError); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Flag which informs CLI and JSON serializer whether to write default page size. | ||
/// property and value to the runtime config file. | ||
/// When user doesn't provide the default-page-size property/value, which signals DAB to use the default, | ||
/// the DAB CLI should not write the default value to a serialized config. | ||
/// This is because the user's intent is to use DAB's default value which could change | ||
/// and DAB CLI writing the property and value would lose the user's intent. | ||
/// This is because if the user were to use the CLI created config, a default-page-size | ||
/// property/value specified would be interpreted by DAB as "user explicitly default-page-size." | ||
/// </summary> | ||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)] | ||
[MemberNotNullWhen(true, nameof(DefaultPageSize))] | ||
public bool UserProvidedDefaultPageSize { get; init; } = false; | ||
|
||
/// <summary> | ||
/// Flag which informs CLI and JSON serializer whether to write max-page-size | ||
/// property and value to the runtime config file. | ||
/// When user doesn't provide the max-page-size property/value, which signals DAB to use the default, | ||
/// the DAB CLI should not write the default value to a serialized config. | ||
/// This is because the user's intent is to use DAB's default value which could change | ||
/// and DAB CLI writing the property and value would lose the user's intent. | ||
/// This is because if the user were to use the CLI created config, a max-page-size | ||
/// property/value specified would be interpreted by DAB as "user explicitly max-page-size." | ||
/// </summary> | ||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)] | ||
[MemberNotNullWhen(true, nameof(MaxPageSize))] | ||
public bool UserProvidedMaxPageSize { get; init; } = false; | ||
|
||
private static void ValidatePageSize(int pageSize) | ||
{ | ||
if (pageSize < -1 || pageSize == 0 || pageSize > Int32.MaxValue) | ||
{ | ||
throw new DataApiBuilderException( | ||
message: "Pagination options invalid. Page size arguments cannot be 0, exceed max int value or be less than -1", | ||
statusCode: HttpStatusCode.ServiceUnavailable, | ||
subStatusCode: DataApiBuilderException.SubStatusCodes.ConfigValidationError); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.