π release: 2.0.8 wheels (5 platforms incl. free-threaded) + README/CHANGELOG refresh
swadhinbiswas committed 2 months ago
0598cf5
1 parent 8f63e8a
commit 0598cf5
2 files changed
+19 -1
Showing 2 changed files+19-1
βΌCHANGELOG.md
+9-0
| @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | ||
7 | 7 | |
8 | 8 | ## [2.0.8] - 2026-08-06 |
9 | 9 | |
10 | +### Added (2026-08-07) | |
11 | +- **Native async DB awaits** β `app.db.query_async(sql, params)` / `app.db.execute_async(...)`: awaitable DB ops on the DB's own tokio runtime, GIL released, loop never blocked. **53Γ faster than the blocking path on slow queries** (320 vs 6 RPS, ADR-093) | |
12 | +- **Multi-worker prefork verified** β `justapi serve --workers N --scale`: 4 workers = 1.88Γ throughput (99.7k RPS), auto-scale respawns (benchmarked 2026-08-07) | |
13 | +- **Type-checked DX** β `py.typed` marker + mypy-clean `.pyi` stubs (routes, `app.db`, `native_async`, `sse_native` all typed) | |
14 | +- **Scaffold demos differentiators** β `justapi create` generates a CRUD app exercising `query_async`, `@native_async`, and Rust-native SSE | |
15 | +- **Rust-native SSE streaming** β `app.sse_native(path, count, interval_ms)`: events generated entirely in Rust, zero Python per event (ADR-088) | |
16 | +- **`@native_async` decorator** β marks async handlers for the fastest dispatch; true parallel dispatch on free-threaded CPython (ADR-089) | |
17 | +- **Callback-driven async resolution** β `_DoneNotifier` fires on coroutine completion; no blocking wait, no thread hop (ADR-086) | |
18 | + | |
10 | 19 | ### Security Fixes |
11 | 20 | - **CRITICAL:** Fixed global panic hook race condition in `panic.rs` (P0-1) |
12 | 21 | - **CRITICAL:** Fixed RwLock poisoning panics in `PerRouteCircuitBreakerMiddleware` (P0-2) |
13 | 22 | |
βΌREADME.md
+10-1
| @@ -92,6 +92,14 @@ The Python path is used for general routes. For schema-backed routes with `nativ | ||
92 | 92 | |
93 | 93 | 2. **Agent-native serving.** Beyond REST, JustAPI exposes routes as MCP tools, streams validated structured output per-token, and carries multi-turn session state β without external SDKs. See [`ROADMAP.md`](ROADMAP.md) for the full agent roadmap. |
94 | 94 | |
95 | +3. **Native async DB awaits.** `await app.db.query_async(sql)` / `execute_async(sql)` run SQL on the DB's own multi-threaded tokio runtime with the GIL released β the asyncio loop is never blocked, so slow queries (Postgres, network DBs) do not serialize other requests. Measured **53Γ faster than the blocking path on slow queries** (320 RPS vs 6 RPS, 2M-row CTE). | |
96 | + | |
97 | +4. **Multi-worker prefork scaling.** `justapi serve --workers N --scale` spawns N worker processes sharing one bound socket. Verified: 4 workers = **1.88Γ throughput** (99.7k RPS vs 53k), auto-scale respawns under load. | |
98 | + | |
99 | +5. **Type-checked DX.** Ships `py.typed` + complete `.pyi` stubs β mypy-clean on user code (routes, `app.db`, `native_async`, `sse_native`). `justapi create` scaffolds a full CRUD project demonstrating every differentiator. | |
100 | + | |
101 | +6. **Free-threaded CPython support.** 3.14t wheels (Py_GIL_DISABLED auto-detected): CPU-bound Python handlers scale with cores (12.4Γ measured). | |
102 | + | |
95 | 103 | ## Competitors, named honestly |
96 | 104 | |
97 | 105 | JustAPI is not the first Rust-backed Python web framework. The following table compares the closest alternatives on raw throughput (Python handler path, same hardware): |
| @@ -118,7 +126,8 @@ For routes registered with `native=True` and a schema, JustAPI serves entirely i | ||
118 | 126 | |
119 | 127 | - **Native fast path requires a schema.** Routes without a `Schema` registered fall back to the Python handler path (~60k rps). The 724k rps number only applies to routes with `native=True` + `Schema`. |
120 | 128 | - **Python handler throughput is GIL-bound.** On CPython, the Python dispatch path is capped at ~100-120k rps on this hardware regardless of framework β that is the GIL, not a framework limitation. Free-threaded Python (3.13t/3.14t) removes this ceiling. |
121 | -- **Agent-native workloads are the differentiator.** The benchmarks that matter most for JustAPI are structured-LLM streaming, MCP tool dispatch, and durable agent sessions β not hello-world req/s. These workloads are impossible or awkward in every alternative listed above. | |
129 | +- **Light async handlers are loop-bound.** Async Python handlers that only sleep/echo (~4-12k rps) are capped by the asyncio loop + thread hop β Granian's direct loop dispatch is ~44k there (ADR-090/091/092 proved no coroutine-driver or multi-loop approach beats asyncio's stepping). We win on real async workloads (1ms-sleep handlers: 3.9k vs Granian 2.9k RPS) and on anything DB/SSE-heavy via native ops. | |
130 | +- **Native fast path requires a schema.** Routes without a `Schema` registered fall back to the Python handler path (~60k rps). The 724k rps number only applies to routes with `native=True` + `Schema`. | |
122 | 131 | |
123 | 132 | ## Non-goals & not-yet-built |
124 | 133 | |
125 | 134 | |