Metadata-Version: 2.4
Name: waitstate
Version: 0.1.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Classifier: Topic :: Software Development :: Libraries
Requires-Dist: pytest>=7.0 ; extra == 'dev'
Requires-Dist: fastapi>=0.100 ; extra == 'dev'
Requires-Dist: flask>=2.0 ; extra == 'dev'
Requires-Dist: django>=4.0 ; extra == 'dev'
Requires-Dist: httpx>=0.24 ; extra == 'dev'
Requires-Dist: django>=4.0 ; extra == 'django'
Requires-Dist: fastapi>=0.100 ; extra == 'fastapi'
Requires-Dist: starlette>=0.27 ; extra == 'fastapi'
Requires-Dist: flask>=2.0 ; extra == 'flask'
Provides-Extra: dev
Provides-Extra: django
Provides-Extra: fastapi
Provides-Extra: flask
License-File: LICENSE
Summary: WaitState SDK — adaptive rate limiting for any language
Keywords: waitstate,rate-limiting,traffic-gating,circuit-breaker,load-shedding
Home-Page: https://waitstate.io
Author-email: WaitState <hello@waitstate.io>
License-Expression: Apache-2.0
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://waitstate.io/docs
Project-URL: Homepage, https://waitstate.io
Project-URL: Issues, https://github.com/waitstate-io/engine/issues
Project-URL: Repository, https://github.com/waitstate-io/engine

# waitstate

Python SDK for [WaitState](https://waitstate.io) - adaptive gating that adds fleet-wide traffic intelligence on top of your existing infrastructure.

Built from a single Rust core via [UniFFI](https://mozilla.github.io/uniffi-rs/). Native performance, no C toolchains required.

## Install

```bash
pip install waitstate
```

## Quick start

```python
import os
from waitstate import WaitstateClient

client = WaitstateClient(
    publish_key=os.environ["WAITSTATE_PUBLISH_KEY"],
    secret_key=os.environ["WAITSTATE_SECRET_KEY"],
)

# Synchronous, in-memory, zero network calls on the hot path
result = client.gate("free", 1.0)

if not result.allowed:
    return {"error": "rate_limited", "reason": str(result.reason)}, 429
```

## Framework middleware

### FastAPI

```python
from fastapi import Depends, FastAPI, Request
from waitstate import WaitstateClient
from waitstate.middleware.fastapi import create_dependency, create_response_hook

client = WaitstateClient(
    publish_key=os.environ["WAITSTATE_PUBLISH_KEY"],
    secret_key=os.environ["WAITSTATE_SECRET_KEY"],
)

app = FastAPI()
gate = create_dependency(client)
app.middleware("http")(create_response_hook(client))

@app.get("/search")
async def search(request: Request, _=Depends(gate)):
    ...
```

### Flask

```python
from flask import Flask
from waitstate import WaitstateClient
from waitstate.middleware.flask import init_app

client = WaitstateClient(
    publish_key=os.environ["WAITSTATE_PUBLISH_KEY"],
    secret_key=os.environ["WAITSTATE_SECRET_KEY"],
)

app = Flask(__name__)
init_app(app, client)
```

### Django

```python
# settings.py
WAITSTATE_PUBLISH_KEY = os.environ["WAITSTATE_PUBLISH_KEY"]
WAITSTATE_SECRET_KEY = os.environ["WAITSTATE_SECRET_KEY"]

MIDDLEWARE = [
    "waitstate.middleware.django.WaitstateMiddleware",
    # ...
]
```

## Agent mode

If you prefer not to embed the SDK, point it at a local [waitstate-agent](https://github.com/waitstate-io/engine) sidecar instead:

```python
client = WaitstateClient(agent_url="http://localhost:9000")

result = client.gate("free", 1.0)
```

In agent mode, gate calls are HTTP round-trips to the sidecar (~1ms on localhost). The agent handles all background sync and telemetry.

## Configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `publish_key` | `str` | - | Required (embedded mode). From the dashboard. |
| `secret_key` | `str` | - | Required (embedded mode). Store in env vars. |
| `agent_url` | `str` | `None` | Use agent mode instead of embedded. |
| `base_url` | `str` | `https://api.waitstate.io` | Control plane URL. |
| `site_id` | `str` | `None` | Shard key for DO routing. Isolates sites within one org. |

## How it works

- `gate()` checks an in-memory policy - synchronous, sub-millisecond in embedded mode.
- Background tasks send health telemetry (pulses) to the control plane and receive updated policies.
- If the control plane is unreachable, the SDK **fails open** (all requests allowed).
- If the lease expires, the SDK enters **safe mode** - a fixed RPS cap to prevent runaway traffic.
- Zero Python dependencies. The compiled Rust core is distributed as a platform-specific wheel.

## Supported platforms

Pre-built wheels are available for:

- Linux x86_64 / aarch64
- macOS x86_64 / aarch64 (Apple Silicon)
- Windows x86_64

## Documentation

Full docs, API reference, and reflex rule guides: [waitstate.io/docs](https://waitstate.io/docs)

## License

[Apache 2.0](./LICENSE)

