Skip to content

Releases: EeroEternal/xlb

v0.0.9

Choose a tag to compare

@EeroEternal EeroEternal released this 19 Oct 13:33

What's Changed

  • feat: add non-idempotent retry boundary, retry timeout ceiling, and redacted trace correlation by @EeroEternal in #10

Full Changelog: v0.0.8...v0.0.9

v0.0.8

Choose a tag to compare

@EeroEternal EeroEternal released this 17 Oct 12:41

What's Changed in v0.0.8

Changed

  • Coalesced Thin-L7 protocol probe & keep-alive buffer reuse (src/proxy/l7.rs, src/proxy/http1.rs): Replaced the 1-byte protocol classification read ([0u8; 1]) with a single 8192-byte read into client_buf so typical HTTP/1.1 request heads and JSON bodies are ingested in one read syscall and one timer registration instead of two; hoisted response_buf outside the keep-alive request loop (ConnBuffer::clear) and made \r\n\r\n header-end scanning incremental across multi-packet reads.

Full Changelog: v0.0.7...v0.0.8

v0.0.7

Choose a tag to compare

@EeroEternal EeroEternal released this 17 Oct 10:05

What's Changed in v0.0.7

Added

  • Pre-first-byte HTTP status rerouting (thin-l7): When a backend returns a status in retry.retry_statuses (default [402, 404, 429, 500, 502, 503, 504]) before any response byte is written to the client and another healthy backend is available within the retry budget, thin-l7 drains the error body, returns keep-alive sockets to the backend's idle pool, increments xlb_reroutes_total{backend, status}, and replays the request (up to retry.max_body_bytes, default 64 MiB for long-context prompts) onto the next healthy backend.
  • Core feature scenarios & architecture SVG diagrams (README.md, docs/assets/scenarios.svg, docs/assets/architecture.svg): Added a 6-card visual scenario overview and updated architecture diagram.

Changed

  • Default server.mode = "thin-l7" and retry.max_retries = -1: server.mode now defaults to "thin-l7" and retry.max_retries defaults to -1 (expanding to backends.servers.len() - 1 so every healthy backend can be tried once; set 0 to disable retries).

Full Changelog: v0.0.6...v0.0.7

v0.0.2

Choose a tag to compare

@EeroEternal EeroEternal released this 15 Oct 23:48

Added

  • Passive dial-failure ejection (backends.passive_unhealthy_threshold & backends.eject_cooldown):
    optional data-plane circuit breaking (default 0 = disabled) that marks a
    backend unhealthy after N consecutive TCP dial failures without waiting for
    the next active /health tick, purges its idle connection pool, and
    automatically re-admits it after eject_cooldown (default 5s) unless
    active health probes have marked it unhealthy (src/backend.rs,
    src/config.rs). Breaking: No.
  • Stale pooled connection redial (thin-l7): when a pooled keep-alive
    connection (reused = true) races with a backend keep-alive close (failing on
    request write or returning an immediate 0-byte EOF/RST before any response
    byte), thin-l7 transparently dials a fresh connection once on the same lease
    instead of surfacing a broken stream to the client (src/proxy/l7.rs).
    Breaking: No.
  • Per-backend concurrency cap (pool.max_conns_per_backend & pool.acquire_timeout):
    optional per-backend in-flight connection limit (default 0 = unlimited) with
    bounded queue wait (pool.acquire_timeout, defaulting to timeouts.connect)
    and capacity-aware scheduling spillover across healthy backends. When slot
    acquisition times out, xFlux increments
    xflux_rejected_total{reason="queue_full"} and returns 503 Service Unavailable
    in thin-l7 mode (src/backend.rs, src/proxy/l4.rs, src/proxy/l7.rs).
    Breaking: No.
  • Phased stream timeouts (timeouts.first_byte vs timeouts.idle): optional
    timeouts.first_byte decouples the pre-response TTFB budget from the in-stream
    chunk silence timeout (timeouts.idle, which remains the fallback when
    first_byte is omitted). In thin-l7, a timeout before any response byte is
    written to the client returns 504 Gateway Timeout and increments
    xflux_rejected_total{reason="timeout"} (src/config.rs, src/proxy/l4.rs,
    src/proxy/l7.rs). Breaking: No.
  • Local pre-push CI hook & console-kit skills: added .githooks/pre-push
    and scripts/install-hooks.sh to run scripts/local-gates.sh automatically
    before git push, plus path-filtered CI in .github/workflows/ci.yml and
    git-stash-safe, promote-lesson, and ci-concurrency-optimization skills
    under .agents/skills/. Breaking: No.

Changed

  • LIFO idle connection pooling: ConnPool now checks out the most recently
    returned connection first (pop_back) to maximize socket warmth and reduce
    peer keep-alive close races, while evicting expired/oldest connections from
    the front (pop_front) (src/pool.rs). Breaking: No.
  • Renamed project to xFlux (xflux): crate, binary (xflux), server type
    (XFluxServer), health probe User-Agent (xflux-health), JSON log env var
    (XFLUX_LOG_JSON), default log filter (xflux=info), and all Prometheus
    metric names (xflux_*) are unified under the xflux namespace.
    Breaking: Yes (binary name, XFLUX_LOG_JSON env var, and xflux_* Prometheus
    metric prefix replace flux / FLUX_LOG_JSON / flux_*).
  • Documented HAProxy-like LB boundary: xFlux inspects HTTP/TCP framing only
    and never payload semantics (SSE, JSON, tokens). Metric help strings now state
    TTFB rather than token-aware TTFT (AGENTS.md, docs/). Breaking: No.

Fixed

  • First-byte histograms are recorded only on the first response head, not again
    after a 1xx informational response (src/proxy/l7.rs). Breaking: No.
  • Connect retries redispatch to a different healthy backend when one is
    available, instead of leastconn repeatedly picking the same refused server
    (src/backend.rs, src/proxy/l4.rs). Breaking: No.
  • 504 Gateway Timeout error responses in thin-l7 use a fresh write deadline
    so the status line is still delivered when first_byte reaches total
    (src/proxy/l7.rs). Breaking: No.

v0.0.1

Choose a tag to compare

@EeroEternal EeroEternal released this 14 Oct 12:30

Added

  • L4 forwarding (mode = "l4", default): pure TCP splice built on
    copy_bidirectional with an activity watchdog. Zero HTTP parsing, zero body
    buffering, half-close aware. One client connection maps to one backend
    connection. Applies to any protocol (HTTP/1.1, HTTP/2, WebSocket, gRPC, TLS).
  • Thin-L7 forwarding (mode = "thin-l7"): parses only the request/response
    heads with httparse and streams bodies verbatim. Because response
    boundaries are known, completed responses return their backend connection to
    the idle pool, enabling request-level connection reuse for POST as well.
  • Automatic L4 fallback (thin-l7): TLS/binary first bytes, the HTTP/2
    preface, Upgrade/CONNECT requests and unparseable heads switch the
    connection to the raw splice, forwarding already-buffered bytes first. The
    client observes no protocol change.
  • Backend connection pool (src/pool.rs): per-backend idle pool, idle
    timeout decoupled from stream duration, non-blocking liveness probing on both
    acquire and release. Applies to all HTTP methods.
  • Layered timeouts: connect, per-direction idle, whole-stream total,
    and half-close fin, each independently configurable.
  • Weighted least-connections scheduler plus round-robin, with health-aware
    filtering and an RAII in-flight Lease.
  • Active health checking on a lightweight path with unhealthy/healthy
    hysteresis; never touches in-flight streams.
  • Optional client-facing TLS termination via rustls (ring provider), PEM
    cert/key, http/1.1 ALPN. Orthogonal to the forwarding mode.
  • Prometheus metrics: flux_ttft_delta_ms, flux_upstream_ttft_ms,
    flux_client_ttft_ms, flux_stream_duration_seconds,
    flux_active_streams, flux_conn_reuse_total, flux_conn_new_total,
    flux_conn_dial_errors_total, flux_rejected_total,
    flux_health_check_failures, flux_health_check_success_total,
    flux_backend_healthy, flux_upstream_errors_total, flux_bytes_total,
    flux_connections_total, flux_active_connections. Served on GET /metrics.
  • Operations: single binary, TOML config, --check validation, graceful
    shutdown on SIGINT/SIGTERM, SO_REUSEPORT.
  • Agent governance: AGENTS.md, docs/ai/agents/, and
    .agents/skills/ imported from console-kit conventions, plus a CI workflow
    mirroring the local gates.