| | | 1 | | namespace TeleFlow.Framework.RateLimiting; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Describes whether an incoming update can continue through the framework pipeline after |
| | | 5 | | /// update-level rate limiting has been evaluated. |
| | | 6 | | /// </summary> |
| | | 7 | | public readonly record struct UpdateRateLimitDecision |
| | | 8 | | { |
| | | 9 | | private const byte AcceptedKind = 0; |
| | | 10 | | private const byte RejectedKind = 1; |
| | | 11 | | |
| | | 12 | | private readonly byte _kind; |
| | | 13 | | |
| | | 14 | | private UpdateRateLimitDecision( |
| | | 15 | | byte kind, |
| | | 16 | | TimeSpan? retryAfter, |
| | | 17 | | string? policyName) |
| | | 18 | | { |
| | 2 | 19 | | if (retryAfter < TimeSpan.Zero) |
| | | 20 | | { |
| | 1 | 21 | | throw new ArgumentOutOfRangeException( |
| | 1 | 22 | | nameof(retryAfter), |
| | 1 | 23 | | retryAfter, |
| | 1 | 24 | | "Rate-limit retry delay must not be negative."); |
| | | 25 | | } |
| | | 26 | | |
| | 1 | 27 | | _kind = kind; |
| | | 28 | | RetryAfter = retryAfter; |
| | 1 | 29 | | PolicyName = string.IsNullOrWhiteSpace(policyName) ? null : policyName; |
| | 1 | 30 | | } |
| | | 31 | | |
| | | 32 | | /// <summary> |
| | | 33 | | /// Gets a decision that allows the update to continue through the framework pipeline. |
| | | 34 | | /// </summary> |
| | 3 | 35 | | public static UpdateRateLimitDecision Accepted => default; |
| | | 36 | | |
| | | 37 | | /// <summary> |
| | | 38 | | /// Gets whether the update is allowed to continue through the framework pipeline. |
| | | 39 | | /// </summary> |
| | 5 | 40 | | public bool IsAccepted => _kind == AcceptedKind; |
| | | 41 | | |
| | | 42 | | /// <summary> |
| | | 43 | | /// Gets whether the update was rejected by a rate limiter. |
| | | 44 | | /// </summary> |
| | 1 | 45 | | public bool IsRejected => _kind == RejectedKind; |
| | | 46 | | |
| | | 47 | | /// <summary> |
| | | 48 | | /// Gets the optional delay after which the update sender may retry, when the limiter can provide it. |
| | | 49 | | /// </summary> |
| | | 50 | | public TimeSpan? RetryAfter { get; } |
| | | 51 | | |
| | | 52 | | /// <summary> |
| | | 53 | | /// Gets the optional developer-controlled policy name that rejected the update. |
| | | 54 | | /// </summary> |
| | | 55 | | public string? PolicyName { get; } |
| | | 56 | | |
| | | 57 | | /// <summary> |
| | | 58 | | /// Creates a decision that rejects the update and stops the framework pipeline. |
| | | 59 | | /// </summary> |
| | | 60 | | public static UpdateRateLimitDecision Rejected( |
| | | 61 | | TimeSpan? retryAfter = null, |
| | | 62 | | string? policyName = null) |
| | | 63 | | { |
| | 2 | 64 | | return new UpdateRateLimitDecision(RejectedKind, retryAfter, policyName); |
| | | 65 | | } |
| | | 66 | | } |