π release: v2.0.9 release notes (commit-by-commit)
swadhinbiswas committed 2 months ago
d98b137
1 parent a8adb2e
commit d98b137
1 file changed
+114 -0
Showing 1 changed file+114-0
βΌRELEASE_NOTES_2.0.9.md
+114-0
| @@ -0,0 +1,114 @@ | ||
1 | +# JustAPI v2.0.9 β Native async DB awaits, Rust-native SSE, tokenless CI publishing | |
2 | + | |
3 | +**Release date:** 2026-08-08 | |
4 | + | |
5 | +The release that makes "Python writes the logic, Rust does everything else" | |
6 | +literal: async DB queries run on Rust's runtime with the GIL released, SSE | |
7 | +streams are generated with zero Python per event, and publishing to PyPI now | |
8 | +happens from a tag push with no token. | |
9 | + | |
10 | +--- | |
11 | + | |
12 | +## Highlights | |
13 | + | |
14 | +### β‘ Native async DB awaits (ADR-093) | |
15 | +`await app.db.query_async(...)` / `execute_async(...)` run SQL on the DB's own | |
16 | +multi-threaded tokio runtime β the asyncio loop is **never blocked**, so slow | |
17 | +queries (Postgres, network DBs) don't serialize other requests. | |
18 | +**Measured: 53Γ faster than the blocking path on slow queries** (320 vs 6 RPS). | |
19 | + | |
20 | +```python | |
21 | +@app.get("/users/{uid}") | |
22 | +async def get_user(request, uid: int): | |
23 | + row = await app.db.query_async("SELECT * FROM users WHERE id = ?", [uid]) | |
24 | + return row | |
25 | +``` | |
26 | + | |
27 | +### π‘ Rust-native SSE streaming (ADR-088) | |
28 | +`app.sse_native(path, count, interval_ms)` β events generated entirely in Rust. | |
29 | +Zero Python, zero GIL per event. 100k events stream instantly. | |
30 | + | |
31 | +### π `@native_async` (ADR-089) + callback-driven async (ADR-086) | |
32 | +Mark handlers for the fastest dispatch; true parallel dispatch on free-threaded | |
33 | +CPython 3.14t. `_DoneNotifier` removes a thread hop from every async request. | |
34 | + | |
35 | +### π·οΈ Type-checked DX | |
36 | +`py.typed` + complete `.pyi` stubs β **mypy-clean** on user code. 200+ stub | |
37 | +errors fixed (implicit-Optional, missing imports, duplicate defs, missing route | |
38 | +methods). | |
39 | + | |
40 | +### π οΈ Multi-worker prefork β verified | |
41 | +`justapi serve --workers N --scale`: **1.88Γ at 4 workers** (99.7k RPS), | |
42 | +auto-scale verified. | |
43 | + | |
44 | +### π¨ Modern README | |
45 | +Animated SVG hero (matrix rain), request-pipeline diagram, benchmark chart, | |
46 | +feature matrix β all SMIL, GitHub-safe. | |
47 | + | |
48 | +### π Tokenless publishing | |
49 | +`wheels.yml` publishes to PyPI via **OIDC trusted publishing** β tag push | |
50 | +β 9-platform wheel matrix β PyPI β GitHub Release. No tokens, no secrets. | |
51 | + | |
52 | +--- | |
53 | + | |
54 | +## Full change log (27 commits) | |
55 | + | |
56 | +### Native async DB awaits β `ed4da41`, `8f63e8a` | |
57 | +- `query_async`/`execute_async` on `DbPool` (ADR-093) | |
58 | +- 2 new tests (query/execute roundtrip, 40-concurrent via HTTP) | |
59 | +- Benchmarks recorded: 53Γ on slow queries; fast queries at parity (~4-4.7k RPS) | |
60 | + | |
61 | +### Rust-native SSE β `1281187`, `d8c16dd`, `576a7be`, `96c6ac3`, `1ad2e27` | |
62 | +- `sse_stream_response(count, interval_ms)` in core (ADR-088) | |
63 | +- `app.sse_native()` registration + `sse_specs` route alignment (bug fixed: | |
64 | + route/vec index desync) | |
65 | +- Test client wiring + tests | |
66 | + | |
67 | +### Async dispatch β `3e6fe90`, `8d3c5dc`, `364904a`, `b750899` | |
68 | +- `_DoneNotifier` callback-driven completion (ADR-086) | |
69 | +- `run_python_parallel` for free-threaded dispatch (ADR-087) | |
70 | +- `@native_async` decorator + `_is_native_async` marker (ADR-089) | |
71 | + | |
72 | +### DX β `d663625`, `f05b19c`, `4322714` | |
73 | +- `py.typed` + mypy-clean stubs | |
74 | +- Scaffold demos differentiators (`query_async`, `@native_async`, `sse_native`) | |
75 | +- Animated SVG README (hero, pipeline, benchmark, feature matrix) | |
76 | + | |
77 | +### Experiments (recorded, not shipped) β `28d6fda`, `bfff404` | |
78 | +- ADR-090/091: native-awaitables β no driver beats asyncio's stepping | |
79 | + (16Β΅s vs 0.56Β΅s/await); justapi beats Granian on real async (3.9k vs 2.9k RPS) | |
80 | +- ADR-092: multi-loop dispatch A/B β neutral-to-worse, reverted | |
81 | + | |
82 | +### CI & Release β `bf007b1`, `0598cf5`, `76a363c`, `3537c75`, `7746001`, `51015a2`, `4188668`, `a9534e5`, `905df9e` | |
83 | +- OIDC trusted publishing (no token) + GitHub Release in-pipeline | |
84 | +- 9-platform wheel matrix: manylinux/musllinux Γ x86_64/aarch64, macOS arm64 | |
85 | + + x86_64 (zig cross), Windows x64, free-threaded 3.14t β all green | |
86 | +- Windows compile fix: Unix-only APIs `#[cfg(unix)]`-gated | |
87 | +- Dropped PyO3/maturin-action (invalid inputs, broken venv) β direct maturin | |
88 | + + zig from ziglang.org | |
89 | +- Repo hygiene: 160 MB purged from git history (.git 225 MB β 61 MB) | |
90 | + | |
91 | +### Honesty β `5426d7e` | |
92 | +- AI/inference phases (41-52) stay π‘/π΄ (no real GPU run) and are excluded | |
93 | + from the release narrative β the story is the verified web framework. | |
94 | + | |
95 | +--- | |
96 | + | |
97 | +## Install | |
98 | + | |
99 | +```bash | |
100 | +pip install justapi==2.0.9 | |
101 | +``` | |
102 | + | |
103 | +## Wheels | |
104 | + | |
105 | +- manylinux_2_17 + musllinux_1_2 Γ x86_64 + aarch64 | |
106 | +- macOS arm64 + x86_64 | |
107 | +- Windows x64 | |
108 | +- Free-threaded CPython 3.14t (cp314-cp314t) | |
109 | + | |
110 | +## Docs | |
111 | + | |
112 | +- [README](https://github.com/swadhinbiswas/JustAPI) β animated overview | |
113 | +- [BENCHMARKS.md](https://github.com/swadhinbiswas/JustAPI/blob/main/BENCHMARKS.md) β full performance ledger | |
114 | +- [CHANGELOG.md](https://github.com/swadhinbiswas/JustAPI/blob/main/CHANGELOG.md) β full history | |
0 | 115 | |