Skip to content

v1.0.29

Choose a tag to compare

@github-actions github-actions released this 26 Apr 01:39
· 138 commits to main since this release

TurboAPI v1.0.29

This is the real Zig 0.16.0 + Python 3.14t release. It supersedes v1.0.28.

v1.0.28 contained the runtime/performance work, but release smoke testing found packaging problems after publish:

  • free-threaded wheels were tagged as cp314t-cp314t, which pip/uv do not select for python3.14t
  • the macOS extension linked against a GitHub Actions-only PythonT.framework path

v1.0.29 fixes those packaging issues and was smoke-tested from a clean PyPI install with the native Zig backend.

Install

uv python install 3.14t
python3.14t -m pip install turboapi==1.0.29

TurboAPI now requires a free-threaded Python build. A regular GIL-enabled Python 3.14 install will refuse to import TurboAPI and tell you to use python3.14t.

Published artifacts:

  • turboapi-1.0.29-cp314-cp314t-macosx_10_15_universal2.whl
  • turboapi-1.0.29-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
  • turboapi-1.0.29.tar.gz

Major Runtime Changes

  • Migrated the Zig HTTP runtime to Zig 0.16.0.
  • Moved the server onto std.Io.net listener and stream APIs.
  • Centralized the shared std.Io.Threaded lifecycle in zig/src/runtime.zig.
  • Kept TurboAPI's explicit cross-core connection worker pool so each worker owns a reusable Python thread state.
  • Added TURBO_THREAD_POOL_SIZE support for controlling worker count at runtime.
  • Updated runtime synchronization to Zig 0.16-compatible std.Io.Mutex / std.Io.Condition paths where applicable.
  • Updated all CI and release workflows to use Zig 0.16.0.
  • Fixed Zig 0.16 compatibility issues across networking, time APIs, pthread mutexes, Smith fuzz callbacks, libc linking, multipart ownership, and removed std APIs.

Performance Work

  • Added eager no-await async dispatch for simple async routes: simple_async_eager.
  • Added eager no-await async dispatch for async body routes: body_async_eager.
  • Added safety checks so eager async mode is skipped for handlers that actually await, yield, or use loop-sensitive asyncio APIs.
  • Added reusable per-worker asyncio event-loop helpers for true-await async handlers.
  • Added async vectorcall/noargs fast paths.
  • Added cached async response handling.
  • Added entry-local atomic cached body pointers for no-arg handlers.
  • Added cached JSON response writing that avoids re-entering Python on cache hits.
  • Added precomputed scalar JSON body parsing for fast sync/async body wrappers.
  • Avoided redundant defensive body copies when Zig already passed immutable Python bytes.
  • Reused Zig helpers for path_params kwargs and skipped empty path-param dict allocation.
  • Switched hot route/parameter parsing paths to std.StaticStringMap.
  • Added SIMD-assisted header-end scanning and router child dispatch where available.
  • Reworked URL percent-decoding to bulk-copy clean spans and branch only on % / +.
  • Reworked telemetry JSON escaping to bulk-copy clean spans.
  • Replaced DHI field type parsing chains with StaticStringMap.
  • Used PyUnicode_AsUTF8AndSize in SQL value encoding to avoid extra length scans.
  • Reworked SQL literal escaping to bulk-copy normal spans and only escape when needed.

HTTP, Forms, Multipart, and Middleware

  • Added Zig-native multipart/form-data parsing support.
  • Fixed multipart, form, URL-encoded, and raw body handling across native, ASGI fallback, and TestClient paths.
  • Added UploadFile / File() / Form() TestClient coverage.
  • Added raw body: bytes injection.
  • Added populated Request injection for handlers that ask for request: Request.
  • Converted turboapi.middleware into a FastAPI-compatible package with submodules:
    • turboapi.middleware.gzip
    • turboapi.middleware.cors
    • turboapi.middleware.trustedhost
    • turboapi.middleware.httpsredirect
    • turboapi.middleware.sessions
  • Fixed middleware route handling so async routes under middleware stay on the correct enhanced path.
  • Fixed middleware compatibility for HTTPS redirect, custom logging-style middleware hooks, GZip passthrough, and header tunneling.
  • Made app.mount("/static", StaticFiles(...)) register real GET routes so the Zig runtime can serve mounted files.
  • Ensured middleware can apply to static-file responses.

Bug Fixes

  • Fixed implicit HTTP header binding for plain string parameters.
  • Fixed query parameter coercion for annotated types like int, float, bool, lists, and enums.
  • Fixed path parameter detection so parameter names are matched as {param} instead of substring matches.
  • Fixed response normalization to avoid mutating caller dictionaries.
  • Fixed response tuple ABI mismatches in the Zig FFI path.
  • Fixed set_cookie() propagation and multi-cookie response handling.
  • Fixed StreamingResponse / FileResponse cookie initialization.
  • Fixed middleware exception status propagation.
  • Fixed middleware on_error response content handling.
  • Fixed OpenAPI handling for Optional[X] / Union[X, None].
  • Fixed TestClient async dependency resolution.
  • Fixed ASGI lifespan handling to use __aenter__ / __aexit__.
  • Fixed Python 3.14 request failures caused by inline import inspect shadowing.
  • Fixed static file path traversal by replacing string-prefix checks with path ancestry checks.
  • Fixed CORS regex origin matching to use full matches.
  • Fixed CSRF cookie handling so existing cookies are not overwritten.
  • Fixed telemetry JSON hex escaping for control characters.
  • Fixed native turbopg fallback behavior and multiple DB route/runtime issues.
  • Fixed DB query parameter parsing, bool handling, large raw-cell lengths, and insert allocation leaks.
  • Fixed DHI schema arena cleanup.
  • Fixed turboapi-core router partial mutation on allocation failure.

Structured Logging and Telemetry

  • Added zig/src/telemetry.zig with event-sourced log/span/counter/histogram/gauge events.
  • Added text and JSON-lines stderr exporters.
  • Added TURBO_LOG_LEVEL and TURBO_LOG_FORMAT.
  • Added zig/src/logger.zig wrappers for leveled Zig logs.
  • Replaced direct std.debug.print calls in the server and DB layer with structured logger calls.
  • Added Python logging helpers and JSON formatting in python/turboapi/logger.py.
  • Added telemetry/logging regression coverage.

Protocol and Deployment Docs

  • Added docs/HTTP3_QUIC.md.
  • Clarified that native QUIC/HTTP/3 is not implemented in TurboAPI yet.
  • Documented the supported production path for QUIC/HTTP/3: put TurboAPI behind Caddy, nginx, Cloudflare, cloudflared, or another edge/reverse proxy.
  • Updated HTTP/2 docs to avoid claiming unsupported native protocol behavior.
  • Updated TLS docs to recommend edge termination / reverse proxy TLS for production.
  • Updated WebSocket docs to match the current runtime support model.
  • Updated performance tuning docs for worker-pool sizing and TURBO_THREAD_POOL_SIZE.
  • Added Zig 0.16 migration docs and a project-agnostic Zig 0.15.2 to 0.16 migration reference.
  • Added a zigup multi-version workflow guide.
  • Added a frontend release notes page for the 1.0.28/1.0.29 work.

Benchmarking and CI

  • Added PR performance regression gating.
  • Added benchmark trend/history tooling.
  • Added benchmarks/thresholds.json.
  • Added scripts/bench-http.sh.
  • Added worker-count tracking through WORKERS=N ./scripts/bench-http.sh.
  • Updated benchmark result JSON/history/PR output to record worker count, duration, wrk threads, and connections.
  • Raised adversarial benchmark thresholds for GitHub-hosted runner stability.
  • Fixed the release workflow so it can push tags and dispatch the publish workflow.
  • Fixed the build/publish workflow so manual dispatch creates the GitHub Release.
  • Added wheel smoke checks in CI:
    • install the produced wheel into a fresh venv
    • import turboapi.turbonet
    • assert TurboServer and ResponseView exist
    • on macOS, assert the wheel does not link to Python.framework or PythonT.framework
  • Limited release wheels to the actually supported Python 3.14t runtime.

Packaging Fixes in v1.0.29

  • Fixed free-threaded wheel tags from cp314t-cp314t to cp314-cp314t.
  • Stopped linking the Zig extension against libpython for release wheels, so macOS wheels no longer embed a non-portable framework path.
  • Verified the macOS wheel links only against @rpath/libturbonet.dylib and /usr/lib/libSystem.B.dylib.
  • Verified a clean PyPI install of turboapi==1.0.29 imports the native backend.
  • Verified a clean PyPI install starts the native Zig HTTP server.

Performance Results

Local no-await async body route measurements with cache disabled:

Route Before After
POST /body0 ~70.9k req/s ~110.8k req/s
POST /body_params ~67.2k req/s ~103.6k req/s
POST /body_sleep0 ~57k req/s ~57k req/s

body_sleep0 is unchanged because it truly awaits and stays on the event-loop path.

Latest mixed-app local HTTP benchmark with TURBO_DISABLE_CACHE=1, TURBO_THREAD_POOL_SIZE=24, and wrk -t8 -c128 -d5s --latency:

Route Median
GET /sync 91.7k req/s
GET /async no-await 89.0k req/s
POST /body no-await async body 83.1k req/s

The same local POST /body route was 49.2k req/s before the precomputed parser pass, so this was about a 69% improvement under the same load.

Validation

Local validation before merge/release:

  • make check passed
  • full test suite passed: 388 passed, 20 warnings
  • sample app smoke passed for:
    • sync GET
    • no-await async GET
    • async POST body
    • path/query route
    • true-await async route
  • benchmark wrapper smoke passed with WORKERS=4 BENCH_DURATION=1 BENCH_THREADS=2 BENCH_CONNECTIONS=16 ./scripts/bench-http.sh
  • /tmp/bench_results.json recorded "workers": 4

Release validation for v1.0.29:

  • Release workflow passed
  • Build & Publish workflow passed
  • Linux 3.14t wheel built and imported the native backend in CI
  • macOS 3.14t wheel built, imported the native backend in CI, and passed the no-Python-framework link check
  • PyPI publish passed
  • GitHub Release creation passed
  • clean PyPI install of turboapi==1.0.29 on python3.14t passed
  • native server smoke from the PyPI wheel passed:
    • GET /ping
    • GET /async
    • GET /items/21
    • POST /items

Issues and PRs

  • Closed #115: HTTP/2/TLS runtime support clarified through reverse proxy / edge termination docs
  • Closed #132: implicit HTTP header binding
  • Closed #137: compatibility bug batch
  • Opened/left #138 for future native HTTP/3 and QUIC support
  • Main release work: #136 and #139

Links