using Polly; namespace Foxcord.Rest.Rate; public class DiscordResilienceStrategy(RateLimiter rateLimiter) : ResilienceStrategy { protected override async ValueTask> ExecuteCore( Func>> callback, ResilienceContext context, TState state) { var path = context.Properties.GetValue(new ResiliencePropertyKey("Path"), string.Empty); if (path == string.Empty) throw new DiscordRequestError("Path was not set in Polly context"); var b = await rateLimiter.LockBucket(BucketKeyUtils.Parse(path), context.CancellationToken); var response = await callback(context, state).ConfigureAwait(context.ContinueOnCapturedContext); if (response.Exception is RateLimitError rateLimitError) b.Release(rateLimitError.Headers); else if (response.Result != null) b.Release(response.Result.Headers); return response; } } public class DiscordResilienceStrategyOptions : ResilienceStrategyOptions; public static class DiscordResilienceStrategyExtensions { public static ResiliencePipelineBuilder AddDiscordStrategy( this ResiliencePipelineBuilder builder, RateLimiter rateLimiter) => builder.AddStrategy(_ => new DiscordResilienceStrategy(rateLimiter), new DiscordResilienceStrategyOptions()); }