-
Notifications
You must be signed in to change notification settings - Fork 0
Conformance and Development
throttlekit-py never re-implements an algorithm — but it does vendor a contract, and that contract must not drift from the Node core it tracks. Two mechanisms keep it honest.
1. The drift-gate (checksums). scripts/sync_contract.py vendors, with sha256 checksums, from the core repo:
-
contract/— the dev/test artifacts:throttlekit.proto(→ the gRPC stubs) andgolden-vectors.json. The vendored proto now declares the read-onlyMonitorservice (GetSnapshot+Watch) and theFleetlease door (Reserve) alongsideRateLimiter, so the generated stubs cover theMonitorBackendandFleetBackenddoors too;golden-vectors.jsonnow carries theleasesuites in addition to therateLimitones. -
src/throttlekit/_scripts/— the runtime Lua theRedisBackendexecutes (shipped in the wheel), with the core'smanifest.json(which carries each script's sha256).
tests/test_contract.py fails if any vendored byte diverges from its pinned checksum, or if the pinned contractVersion moves unexpectedly.
2. The behavioral proof (golden vectors). The real guarantee isn't the bytes — it's the behavior:
-
tests/test_redis_backend.pyreplays every rate-limit golden vector — the full, time-parametrized timeline — through the Python client → vendored Lua → real Redis, and asserts every reply field equals the Node oracle bit-for-bit. (Because the direct path puts an explicitnowin ARGV, it can do the rigorous time-parametrized replay the cross-process service door can't.) -
tests/test_service_backend.pystarts a realthrottlekit-serverand asserts the clock-independent behavior over gRPC — a cold burst admits exactlyburstthen denies;debitspends a budget then refuses;admitholds a concurrency slot, releases it, heart-beats a long hold, and the server reclaims an abandoned one. -
tests/test_lease_spender.pyreplays every goldenleasevector — a scripted interleave of lease grants and local spends — through the Tier-2LeaseSpender, asserting each reply (an allowDecision, orNone= "refresh needed") matches the Node core'stwoTier(leased, windowCoupled)L1 path bit-for-bit. This is the same kind of byte-lock the rate-limit vectors get, now extended to the leased-budget spend theFleetBackenddraws against.
So a Python decision is the Node core's decision — verified, not hoped for.
git clone https://github.com/AmeyaBorkar/throttlekit-py
cd throttlekit-py
python -m venv .venv && . .venv/Scripts/activate # or .venv/bin/activate on POSIX
pip install -e .[dev]
python scripts/sync_contract.py # vendor proto + vectors + Lua from ../throttlekit (the core)
python scripts/gen_proto.py # generate the gRPC stubs from the vendored proto
pytest # unit + contract; the Redis/service tests skip if their backend is absent
ruff check . && ruff format --check . && mypyThe generated gRPC stubs (src/throttlekit/_generated/) are build artifacts — git-ignored, regenerated by gen_proto.py, and produced at build time by a hatchling hook so they ship in the wheel (you don't commit them).
-
RedisBackend conformance needs a reachable Redis: it uses
THROTTLEKIT_REDIS_URLor the project defaultredis://localhost:6380, and skips cleanly when neither is up.docker run -d --name tk-redis-6380 -p 6380:6379 redis:7-alpine
-
ServiceBackend integration needs
nodeonPATHand a built server. PointTHROTTLEKIT_REPOat your local core checkout (it defaults to../GreenfeildProject), then build the server once:( cd "$THROTTLEKIT_REPO/server" && npm ci && npm run build ) pytest -m integration
Both integration suites are skipped (not failed) when their backend isn't available, so a bare pytest is always green.
.github/workflows/ci.yml runs on every push and PR:
-
Lint & format —
ruff check+ruff format --check(one run; ruff's target version is pinned). -
Types & tests (py 3.10 / 3.11 / 3.12 / 3.13) —
mypy --python-version+pytestacross the matrix, with a Redis service container so the cross-languagetest_redis_backend.pyvector replay runs on every version (not just locally). The pure-Pythontest_lease_spender.pylease-vector replay runs here too (it needs no backend). -
Contract drift-gate — a standalone, pure-Python
pytest tests/test_contract.py, so vendored-contract drift is its own blocking red check (no gRPC / Redis / Node needed) — it covers the vendored proto (now incl. theFleet/Monitorservices), therateLimitandleasegolden vectors, and the runtime Lua checksums. -
Build hook & wheel import — builds the real wheel, asserts the generated gRPC stubs are inside it (
scripts/check_wheel_stubs.py), and imports both doors from a clean install — catching stub-packaging regressions on every PR.
Releases are tag-driven and publish to PyPI via trusted publishing (OIDC) — no long-lived API token. Push a vX.Y.Z tag and release.yml builds + smoke-tests the wheel, publishes over OIDC (skip-existing), and cuts the GitHub Release from the CHANGELOG. The full procedure — including the one-time PyPI trusted-publisher setup — is in RELEASING.md.
- The axes — the client surface these suites exercise.
- The core's Polyglot & Python wiki page — the design from the Node side.
-
research/polyglot/— the design + decision records for the whole polyglot arc. - The cross-repo battle test — a multi-process distributed workload that drives every axis through both backends against a real Redis-backed 3-server fleet (distributed cap exactness, the windowCoupled overshoot bound, crash-reclaim, heartbeat, one-oracle/two-door state sharing); the committed
logs/hold a green 11/11 run.