HallPass 0.0.17

There is a newer version of this package available.
See the version list below for details.
dotnet add package HallPass --version 0.0.17
NuGet\Install-Package HallPass -Version 0.0.17
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HallPass" Version="0.0.17" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add HallPass --version 0.0.17
#r "nuget: HallPass, 0.0.17"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install HallPass as a Cake Addin
#addin nuget:?package=HallPass&version=0.0.17

// Install HallPass as a Cake Tool
#tool nuget:?package=HallPass&version=0.0.17

HallPass - PRE-RELEASE

Client-side rate limiter library for .NET to help client-side developers respect the rate limits of the APIs that they consume.

Installation

Nuget Package Manager

Install-Package HallPass

dotnet CLI

dotnet add package HallPass

Usage

⚠️ the examples below are only proposals, not yet quite implemented...

Configuration

using HallPass;

...

// HallPass extension method
builder.Services.UseHallPass(config =>
{
    // throttle all requests matching a uri pattern
    config.UseTokenBucket(
        uriPattern: "api.foo.com/users",
        requestsPerPeriod: 100,
        periodDuration: TimeSpan.FromMinutes(15));

    // can also use a Func<HttpRequestMessage, bool> to resolve whether to throttle or not
    config.UseTokenBucket(
        httpRequestMessage => httpRequestMessage.RequestUri.ToString().Contains("api.foo.com/posts"),
        1000,
        TimeSpan.FromMinutes(1));
});

Usage - Throttle a single call

using HallPass;

...

class MyService
{
    private readonly IHttpClientFactory _httpClientFactory;

    public MyService(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task<FooUser> GetFooUserAsync(string userId, CancellationToken token = default)
    {
        // HallPass extension method
        HttpClient httpClient = _httpClientFactory.CreateHallPassClient();

        ...
        // block to keep rate within 100 / 15 minutes WITHIN THIS SINGLE APP INSTANCE
        await httpClient.GetAsync($"https://api.foo.com/users/{userId}", token);
    }
}

Usage - Throttle a bunch of calls in a loop

HallPass works for synchronous loops (within async methods) by simply awaiting until it has permission to proceed based on the configuration.

var userIds = Enumerable.Range(1, 500);
foreach (var userId in userIds)
{
    // block to keep rate within 100 / 15 minutes WITHIN THIS SINGLE APP INSTANCE
    await httpClient.GetAsync($"https://api.foo.com/users/{userId}", token);
}

Usage - Throttle a bunch of calls concurrently

HallPass is also thread-safe, working as expected for concurrent bunches of requests.

var tasks = Enumerable
    .Range(1, 500)
    .Select(userId => Task.Run(async () =>
    {
        // block to keep rate within 100 / 15 minutes WITHIN THIS SINGLE APP INSTANCE
        await httpClient.GetAsync($"https://api.foo.com/users/{userId}", token);
    }))
    .ToList();

await Task.WhenAll(tasks);

COMING SOON

  • Throttle a Bunch of Calls Across Distributed Systems
  • More Bucket Types (Leaky Bucket, Fixed Window, Sliding Log, Sliding Window, Query Cost)

COMING SOON: Throttle a Bunch of Calls Across Distributed Systems

Soon, HallPass will be able to throttle calls across distributed systems. If you have multiple instances of an application running at once, but need to respect a single external API rate limit, or if you have multiple different applications running but still need to respect a single external API rate limit between all instances and applications, you'd be able to do so with minimal code changes.

Configuration
builder.Services.UseHallPass(config =>
{
    // remote buckets, for coordinating clusters of services
    config
        .UseTokenBucket("api.bar.com/statuses", 50, TimeSpan.FromMinutes(1))

        // client id and secret provided when registering an app in your HallPass dashboard
        .ForMultipleInstances("my-client-id", "my-client-secret");
});
Usage
/* this line will wait, if necessary, so the frequency remains within 50 requests
   per 1 minute ACROSS ALL DISTRIBUTED INSTANCES for the given HallPass client_id,
   as defined in the configuration */
await httpClient.GetAsync($"https://api.bar.com/statuses");
Distributed Throttling Notes

This will be a paid service, and the HallPass API itself will be rate-limited (with basic throttling and retries handled via the SDK code). We're still finalizing the pricing model, but hope to have a free tier available to demo soon!

HallPass will take care of registering individual instances, "fairly" dolling out permissions, and tracking the global rate limit for your account/app and its usage on our servers.

HallPass will never know what endpoints you're calling, because the actual API call is still handled locally within each application. All that HallPass receives is an encrypted unique ID representing each scoped throttle group, and the bucket type used for that key.

API calls to the HallPass service will be limited. Broadly, the SDK will request and store bunches of HallPasses that can be used locally. When the local cache runs out, it will reach out to the API again for a refill.

COMING SOON: More Bucket Types

Please let us know which bucket types would be valuable to have. Most likely, we're going with Leaky Bucket next. Query Cost will likely either need significant configuration on the side of the user, or will need to be tailored to individual APIs.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.6.2 218 5/1/2023
0.6.1 416 8/18/2022
0.6.0 415 8/18/2022
0.5.5 396 8/17/2022
0.5.4 414 8/17/2022
0.5.3 400 8/17/2022
0.5.2 388 8/15/2022
0.5.1 455 8/15/2022
0.5.0 439 8/1/2022
0.4.1 419 7/29/2022
0.4.0 424 7/29/2022
0.3.0 430 7/28/2022
0.2.7 435 7/28/2022
0.2.6 407 7/28/2022
0.2.4 422 7/27/2022
0.2.3 423 7/21/2022
0.2.2 417 7/18/2022
0.2.1 390 7/15/2022
0.2.0 435 7/14/2022
0.1.3 453 7/7/2022
0.1.2 432 7/5/2022
0.1.1 441 6/8/2022
0.1.0 403 6/7/2022
0.0.18 404 6/7/2022
0.0.17 424 6/7/2022
0.0.16 394 6/6/2022
0.0.15 424 6/6/2022
0.0.14 426 6/6/2022
0.0.13 425 6/6/2022
0.0.12 431 6/6/2022
0.0.11 396 6/4/2022
0.0.10 452 6/3/2022
0.0.9 427 5/31/2022
0.0.8 416 5/31/2022
0.0.7 425 5/31/2022
0.0.6 413 5/31/2022
0.0.5 408 5/31/2022
0.0.4 442 5/31/2022
0.0.3 417 5/31/2022
0.0.2 424 5/31/2022
0.0.1 430 5/11/2022