No project description provided
Project description
asyncbalancer
⚠️ Warning: This package is currently not stable and may change without notice.
Use it at your own risk.
asyncbalancer is a lightweight package for routing requests across multiple providers while storing provider state in Redis.
Key features:
- provider selection based on availability and score,
- circuit breaker per provider,
- resource limits (
tpm,rpm, etc.) with TTL, - CLI for state inspection and manual state administration.
Requirements
- Python
>= 3.12 - Redis (local or remote)
Installation
From the project root:
pip install -e .
After installation, the CLI command is available:
asyncbalancer --help
You can also run it directly as a module:
python3 -m asyncbalancer --help
Configuration
Configuration is loaded from the [tool.asyncbalancer] section in pyproject.toml (or config.toml).
Minimal example:
[tool.asyncbalancer]
driver = "redis"
resources_file = "./examples/config.json"
tier_order = ["free", "pro", "enterprise"]
[tool.asyncbalancer.drivers.redis]
host = "localhost"
port = 6379
db = 0
[tool.asyncbalancer.providers.gemini]
api_key = "your-api-key"
name = "gemini-2.5-flash"
tiers = ["pro", "enterprise"]
Tier-based provider access
You can control which providers are available for each user tier.
tier_orderdefines the fallback order from lower to higher tier.- each provider can define
tiersto limit access. - if a provider does not define
tiers, it is treated as available for all tiers.
Example:
[tool.asyncbalancer]
tier_order = ["free", "pro", "enterprise"]
[tool.asyncbalancer.providers.gemma]
tiers = ["free", "pro", "enterprise"]
[tool.asyncbalancer.providers.gemini]
tiers = ["pro", "enterprise"]
[tool.asyncbalancer.providers.claude]
tiers = ["enterprise"]
How routing works:
- Router reads user tier from
ProviderRequest.tier(orProviderRequest.options["tier"]). - It first tries providers assigned to that tier.
- If no provider can handle the request, it falls back to lower tiers based on
tier_order.
Examples with tier_order = ["free", "pro", "enterprise"]:
- user tier
enterprise-> tryenterprise, thenpro, thenfree - user tier
pro-> trypro, thenfree - user tier
free-> try onlyfree
If request tier is missing, tier filtering is skipped (all providers can be considered).
Defining resources in an external file
resources_file can point to a JSON or TOML file.
ASYNCBALANCER_RESOURCES_FILE is also supported.
JSON example (examples/config.json):
{
"providers": {
"gemini": {
"resources": [
{ "name": "tpm", "value": 10000, "initial_ttl": 3600, "next_ttl": 3600 },
{ "name": "rpm", "value": 500, "initial_ttl": 60, "next_ttl": 60 }
]
}
}
}
Library usage
- Register provider classes in
ProviderRegistry. - Create an
ApiRouter. - Call
router.request(...).
Example:
import asyncio
from asyncbalancer import ApiRouter, ProviderRequest
from asyncbalancer.providers.provider_registry import ProviderRegistry
from asyncbalancer.providers.iprovider import IProvider
from asyncbalancer.models.client import ProviderResponse
from asyncbalancer.models.resource import ResourceUnitCosts, ResourceUnitCost
class MyProvider(IProvider):
def __init__(self, api_key: str, name: str):
self.api_key = api_key
self.name = name
async def request(self, request: ProviderRequest) -> ProviderResponse:
return ProviderResponse(success=True, data={"text": "ok"}, latency=120, error=None)
async def estimate_cost(self, request: ProviderRequest) -> ResourceUnitCosts:
return ResourceUnitCosts(costs={"tpm": ResourceUnitCost(key="tpm", amount=20)})
async def get_costs(self, response: ProviderResponse) -> ResourceUnitCosts:
return ResourceUnitCosts(costs={"tpm": ResourceUnitCost(key="tpm", amount=24)})
ProviderRegistry.register("gemini", MyProvider)
async def main():
router = ApiRouter()
response = await router.request(ProviderRequest(payload={"prompt": "Hello"}))
print(response)
asyncio.run(main())
CLI commands
Show all commands:
asyncbalancer --help
show-state
Shows current state for a provider.
asyncbalancer show-state gemini
reset-state
Resets provider state to values from config/resources.
asyncbalancer reset-state gemini
Dry-run mode:
asyncbalancer reset-state gemini --dry-run
set-resource-used
Sets used for a resource and recalculates score.
asyncbalancer set-resource-used gemini tpm 1200
adjust-resource-used
Increments/decrements used by delta and recalculates score.
asyncbalancer adjust-resource-used gemini tpm 150
asyncbalancer adjust-resource-used gemini tpm -80
set-resource-ttl
Sets resource ttl (and updates created_at to now) and recalculates score.
asyncbalancer set-resource-ttl gemini tpm 3600
sync-config
Synchronizes limits from config into Redis state:
- updates limits (
capacity,ttl), - keeps current usage (
used,reserved) unchanged, - recalculates score,
- prints state after update.
Single provider:
asyncbalancer sync-config --provider gemini
All providers:
asyncbalancer sync-config
CLI exit codes
0success1provider state not found / no providers found2argument or configuration validation error
Locking note
State-mutating commands (set-resource-used, adjust-resource-used, set-resource-ttl, sync-config) wait for a provider lock before writing state to avoid clobbering concurrent updates.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asyncbalancer-0.1.0b1.tar.gz.
File metadata
- Download URL: asyncbalancer-0.1.0b1.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29c33f72981eba064ed870aaf90bff688083f5645332050143074c4205c06c7c
|
|
| MD5 |
3a94db9c3fbf11cc43a804e42fcb1186
|
|
| BLAKE2b-256 |
19b4667d79cb966b2334b3ca2f87b4e28b21eabfe8ffecaa1cb8ca4149bff633
|
Provenance
The following attestation bundles were made for asyncbalancer-0.1.0b1.tar.gz:
Publisher:
python-publish.yml on mjakubowski99/asyncbalancer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asyncbalancer-0.1.0b1.tar.gz -
Subject digest:
29c33f72981eba064ed870aaf90bff688083f5645332050143074c4205c06c7c - Sigstore transparency entry: 1382655834
- Sigstore integration time:
-
Permalink:
mjakubowski99/asyncbalancer@9892ad04af860df559a88ac7fce536511fd2e2ff -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mjakubowski99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@9892ad04af860df559a88ac7fce536511fd2e2ff -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file asyncbalancer-0.1.0b1-py3-none-any.whl.
File metadata
- Download URL: asyncbalancer-0.1.0b1-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6a55a513b96774a75e144f6a278365571cd4917510636f1f5813998090a5574
|
|
| MD5 |
c8ffb116a3749efe26d4af256884a8c7
|
|
| BLAKE2b-256 |
80e4175ee0e3627c8c1558335dc12cb353e7ed9c3a9af299913aad81c689396c
|
Provenance
The following attestation bundles were made for asyncbalancer-0.1.0b1-py3-none-any.whl:
Publisher:
python-publish.yml on mjakubowski99/asyncbalancer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asyncbalancer-0.1.0b1-py3-none-any.whl -
Subject digest:
e6a55a513b96774a75e144f6a278365571cd4917510636f1f5813998090a5574 - Sigstore transparency entry: 1382655875
- Sigstore integration time:
-
Permalink:
mjakubowski99/asyncbalancer@9892ad04af860df559a88ac7fce536511fd2e2ff -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mjakubowski99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@9892ad04af860df559a88ac7fce536511fd2e2ff -
Trigger Event:
workflow_dispatch
-
Statement type: